-/*
-** Copyright 1998 - 2007 Double Precision, Inc. See COPYING for
-** distribution information.
-*/
-
-#if HAVE_CONFIG_H
-#include "courier_auth_config.h"
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <pwd.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include "auth.h"
-#include "authstaticlist.h"
-#include "courierauthdebug.h"
-#include "vpopmail_config.h"
-#include <vpopmail.h>
-#include <vauth.h>
-
-static const char rcsid[]="$Id: authvchkpw.c,v 1.29 2007/10/07 02:50:45 mrsam Exp $";
-
-
-extern int auth_vchkpw_pre(const char *userid, const char *service,
- int (*callback)(struct authinfo *, void *),
- void *arg);
-
-extern FILE *authvchkpw_file(const char *, const char *);
-
-static int auth_vchkpw_login(const char *service, char *authdata,
- int (*callback_func)(struct authinfo *, void *), void *callback_arg);
-
-struct callback_info {
- const char *pass;
- int (*callback_func)(struct authinfo *, void *);
- void *callback_arg;
- };
-
-static int callback_vchkpw(struct authinfo *a, void *p)
-{
-struct callback_info *i=(struct callback_info *)p;
-
- /* exit with perm failure if the supplied password is empty,
- * or if the supplied password doesnt match the retrieved password */
- if (a->passwd == 0)
- {
- DPRINTF("no password supplied");
- return (-1);
- }
-
- if (authcheckpassword(i->pass, a->passwd))
- return (-1);
-
- a->clearpasswd=i->pass;
- return (*i->callback_func)(a, i->callback_arg);
-}
-
-#if HAVE_HMACLIB
-
-#include "libhmac/hmac.h"
-#include "cramlib.h"
-
-static int auth_vchkpw_login(const char *service, char *authdata,
- int (*callback_func)(struct authinfo *, void *), void *callback_arg);
-
-static int auth_vchkpw_cram(const char *service,
- const char *authtype, char *authdata,
- int (*callback_func)(struct authinfo *, void *),
- void *callback_arg)
-{
- struct cram_callback_info cci;
-
- if (auth_get_cram(authtype, authdata, &cci))
- return (-1);
-
- cci.callback_func=callback_func;
- cci.callback_arg=callback_arg;
-
- return auth_vchkpw_pre(cci.user, service, &auth_cram_callback, &cci);
-}
-#endif
-
-int auth_vchkpw(const char *service, const char *authtype, char *authdata,
- int (*callback_func)(struct authinfo *, void *),
- void *callback_arg)
-{
- if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
- return (auth_vchkpw_login(service, authdata,
- callback_func, callback_arg));
-
-#if HAVE_HMACLIB
- return (auth_vchkpw_cram(service, authtype, authdata,
- callback_func, callback_arg));
-#else
- errno=EPERM;
- return (-1);
-#endif
-
-}
-
-
-
-static int auth_vchkpw_login(const char *service, char *authdata,
- int (*callback_func)(struct authinfo *, void *), void *callback_arg)
-{
-char *user, *pass;
-struct callback_info ci;
-int rc;
- /* Make sure that we have been supplied with the correct
- * AUTHDATA format which is : userid<NEWLINE>password<NEWLINE>
- */
- if ( (user=strtok(authdata, "\n")) == 0 || (pass=strtok(0, "\n")) == 0)
- {
- /* login syntax was invalid */
- errno=EPERM;
- return (-1);
- }
-
- ci.pass=pass;
- ci.callback_func=callback_func;
- ci.callback_arg=callback_arg;
-
- /* auth_vchkpw_pre() does this :
- * - lookup the passwd entry for this user from the auth backend
- * - check to see if this user is permitted to use this service type
- * If successful it will populate the ci struct with the
- * user's passwd entry. Return value of function will be 0.
- * If unsuccessful (eg user doesnt exist, or is not permitted to
- * use this auth method), it will return :
- * <0 on a permanent failure (eg user doesnt exist)
- * >0 on a temp failure
- */
- rc=auth_vchkpw_pre(user, service, &callback_vchkpw, &ci);
-
- if (rc)
- return rc;
-
- /* user has been successfully auth'ed at this point */
-
-#if 0
- /*
- ** sam - new courier-authlib never receives TCPREMOTEIP, at this
- ** time.
- */
-
-#ifdef HAVE_OPEN_SMTP_RELAY
- if ( (strcmp("pop3", service)==0) || (strcmp("imap", service)==0) ) {
- /* Michael Bowe 13th August 2003
- *
- * There is a problem here because open_smtp_relay needs
- * to get the user's ip from getenv("TCPREMOTEIP").
- * If we run --with-authvchkpw --without-authdaemon,
- * then this var is available.
- * But if we run --with-authvchkpw --with-authdaemon,
- * then TCPREMOTEIP is null
- *
- * If TCPREMOTEIP isnt available, then open_smtp_relay()
- * will just return() back immediately.
- */
- open_smtp_relay();
- }
-#endif
-#endif
-
- return 0;
-}
-
-static void authvchkpwclose()
-{
-}
-
-static int auth_vchkpw_changepass(const char *service,
- const char *username,
- const char *pass,
- const char *npass)
-{
-struct vqpasswd *vpw;
-char User[256];
-char Domain[256];
-
- /* Take the supplied userid, and split it out into the user and domain
- * parts. (If a domain was not supplied, then set the domain to be
- * the default domain)
- */
- /* WARNING: parse_email lowercases the username in place - not const!! */
- if ( parse_email(username, User, Domain, 256) != 0) {
- /* Failed to successfully extract user and domain.
- * So now exit with a permanent failure code
- */
- return(-1);
- }
-
- /* check to see if domain exists.
- * If you pass an alias domain to vget_assign, it will change it
- * to be the real domain on return from the function
- */
- if ( vget_assign(Domain,NULL,0,NULL,NULL) ==NULL ) {
- /* domain doesnt exist */
- return (-1);
- }
-
- if ( (vpw=vauth_getpw(User, Domain)) == NULL) {
- /* That user doesnt exist in the auth backend */
- errno=ENOENT;
- return (-1);
- }
-
- /* Exit if any of the following :
- * - user's password field in the passwd entry is empty
- * - supplied current password doesnt match stored password
- */
- if (vpw->pw_passwd == 0 || authcheckpassword(pass, vpw->pw_passwd)) {
- errno=EPERM;
- return (-1);
- }
-
- /* save the new password into the auth backend */
- if ( vpasswd(User, Domain, (char *)npass, 0) != 0 ) {
- /* password set failed */
- return (-1);
- };
-
- return (0);
-}
-
-struct authstaticinfo authvchkpw_info={
- "authvchkpw",
- auth_vchkpw,
- auth_vchkpw_pre,
- authvchkpwclose,
- auth_vchkpw_changepass,
- authvchkpwclose,
- NULL};
-
-
-struct authstaticinfo *courier_authvchkpw_init()
-{
- return &authvchkpw_info;
-}