2 ** Copyright 1998 - 2004 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courier_auth_config.h"
18 #include "authstaticlist.h"
19 #include "courierauthdebug.h"
20 #include "vpopmail_config.h"
24 static const char rcsid
[]="$Id: authvchkpw.c,v 1.26 2007/04/22 18:53:30 mrsam Exp $";
27 extern int auth_vchkpw_pre(const char *userid
, const char *service
,
28 int (*callback
)(struct authinfo
*, void *),
31 extern FILE *authvchkpw_file(const char *, const char *);
33 struct callback_info
{
35 int (*callback_func
)(struct authinfo
*, void *);
39 static int callback_vchkpw(struct authinfo
*a
, void *p
)
41 struct callback_info
*i
=(struct callback_info
*)p
;
43 /* exit with perm failure if the supplied password is empty,
44 * or if the supplied password doesnt match the retrieved password */
47 DPRINTF("no password supplied");
51 if (authcheckpassword(i
->pass
, a
->passwd
))
54 a
->clearpasswd
=i
->pass
;
55 return (*i
->callback_func
)(a
, i
->callback_arg
);
60 #include "libhmac/hmac.h"
64 static int auth_vchkpw_cram(const char *service
,
65 const char *authtype
, char *authdata
,
66 int (*callback_func
)(struct authinfo
*, void *),
69 struct cram_callback_info cci
;
71 if (auth_get_cram(authtype
, authdata
, &cci
))
74 cci
.callback_func
=callback_func
;
75 cci
.callback_arg
=callback_arg
;
77 return auth_vchkpw_pre(cci
.user
, service
, &auth_cram_callback
, &cci
);
81 int auth_vchkpw(const char *service
, const char *authtype
, char *authdata
,
82 int (*callback_func
)(struct authinfo
*, void *),
85 if (strcmp(authtype
, AUTHTYPE_LOGIN
) == 0)
86 return (auth_vchkpw_login(service
, authdata
,
87 callback_func
, callback_arg
));
90 return (auth_vchkpw_cram(service
, authtype
, authdata
,
91 callback_func
, callback_arg
));
101 static int auth_vchkpw_login(const char *service
, char *authdata
,
102 int (*callback_func
)(struct authinfo
*, void *), void *callback_arg
)
105 struct callback_info ci
;
107 /* Make sure that we have been supplied with the correct
108 * AUTHDATA format which is : userid<NEWLINE>password<NEWLINE>
110 if ( (user
=strtok(authdata
, "\n")) == 0 || (pass
=strtok(0, "\n")) == 0)
112 /* login syntax was invalid */
118 ci
.callback_func
=callback_func
;
119 ci
.callback_arg
=callback_arg
;
121 /* auth_vchkpw_pre() does this :
122 * - lookup the passwd entry for this user from the auth backend
123 * - check to see if this user is permitted to use this service type
124 * If successful it will populate the ci struct with the
125 * user's passwd entry. Return value of function will be 0.
126 * If unsuccessful (eg user doesnt exist, or is not permitted to
127 * use this auth method), it will return :
128 * <0 on a permanent failure (eg user doesnt exist)
129 * >0 on a temp failure
131 rc
=auth_vchkpw_pre(user
, service
, &callback_vchkpw
, &ci
);
136 /* user has been successfully auth'ed at this point */
140 ** sam - new courier-authlib never receives TCPREMOTEIP, at this
144 #ifdef HAVE_OPEN_SMTP_RELAY
145 if ( (strcmp("pop3", service
)==0) || (strcmp("imap", service
)==0) ) {
146 /* Michael Bowe 13th August 2003
148 * There is a problem here because open_smtp_relay needs
149 * to get the user's ip from getenv("TCPREMOTEIP").
150 * If we run --with-authvchkpw --without-authdaemon,
151 * then this var is available.
152 * But if we run --with-authvchkpw --with-authdaemon,
153 * then TCPREMOTEIP is null
155 * If TCPREMOTEIP isnt available, then open_smtp_relay()
156 * will just return() back immediately.
166 static void authvchkpwclose()
170 static int auth_vchkpw_changepass(const char *service
,
171 const char *username
,
175 struct vqpasswd
*vpw
;
179 /* Take the supplied userid, and split it out into the user and domain
180 * parts. (If a domain was not supplied, then set the domain to be
181 * the default domain)
183 /* WARNING: parse_email lowercases the username in place - not const!! */
184 if ( parse_email(username
, User
, Domain
, 256) != 0) {
185 /* Failed to successfully extract user and domain.
186 * So now exit with a permanent failure code
191 /* check to see if domain exists.
192 * If you pass an alias domain to vget_assign, it will change it
193 * to be the real domain on return from the function
195 if ( vget_assign(Domain
,NULL
,0,NULL
,NULL
) ==NULL
) {
196 /* domain doesnt exist */
200 if ( (vpw
=vauth_getpw(User
, Domain
)) == NULL
) {
201 /* That user doesnt exist in the auth backend */
206 /* Exit if any of the following :
207 * - user's password field in the passwd entry is empty
208 * - supplied current password doesnt match stored password
210 if (vpw
->pw_passwd
== 0 || authcheckpassword(pass
, vpw
->pw_passwd
)) {
215 /* save the new password into the auth backend */
216 if ( vpasswd(User
, Domain
, (char *)npass
, 0) != 0 ) {
217 /* password set failed */
224 struct authstaticinfo authvchkpw_info
={
229 auth_vchkpw_changepass
,
234 struct authstaticinfo
*courier_authvchkpw_init()
236 return &authvchkpw_info
;