1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
/*
** Copyright 1998 - 2004 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.25 2005/02/20 04:41:20 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 *);
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);
}
int auth_vchkpw(const char *service, const char *authtype, 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 (strcmp(authtype, AUTHTYPE_LOGIN) ||
(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;
}
|