2 ** Copyright 1998 - 2001 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courier_auth_config.h"
18 #include "courierauthdebug.h"
21 #include "vpopmail_config.h"
23 /* make use of pw_flags only if available */
24 #ifndef VQPASSWD_HAS_PW_FLAGS
25 #define pw_flags pw_gid
28 extern FILE *authvchkpw_file(const char *, const char *);
30 static const char rcsid
[]="$Id: preauthvchkpw.c,v 1.26 2007/04/22 18:53:30 mrsam Exp $";
32 /* This function is called by the auth_vchkpw() function
34 * This function does the following :
35 * - extract the username and domain from the supplied userid
36 * - lookup the passwd entry for that user from the auth backend
37 * - populate *and return) a courier authinfo structure with the values
38 * from the vpopmail passwd entry
40 * Return -1 on perm failure
42 * Return 1 on temp failure
49 int (*callback
)(struct authinfo
*, void *),
56 static char User
[256];
57 static char Domain
[256];
58 static char options
[80];
60 /* Make sure the auth struct is empty */
61 memset(&auth
, 0, sizeof(auth
));
63 /* Take the supplied userid, and split it out into the user and domain
64 * parts. (If a domain was not supplied, then set the domain to be
67 if ( parse_email(userid
, User
, Domain
, 256) != 0) {
68 /* Failed to successfully extract user and domain.
69 * So now exit with a permanent failure code
71 DPRINTF("vchkpw: unable to split into user and domain");
75 /* Check to see if the domain exists.
76 * If so, on return vget_assign will :
77 * Rewrite Domain to be the real domain if it was sent as an alias domain
78 * Retrieve the domain's uid and gid
80 if ( vget_assign(Domain
,NULL
,0,&uid
, &gid
) == NULL
) {
81 /* Domain does not exist
82 * So now exit with a permanent failure code */
83 DPRINTF("vchkpw: domain does not exist");
87 /* Try and retrieve the user's passwd entry from the auth backend */
88 if ( (vpw
=vauth_getpw(User
, Domain
)) == NULL
) {
89 /* User does not exist
90 * So now exit with a permanent failure code
92 DPRINTF("vchkpw: user does not exist");
96 /* Check to see if the user has been allocated a dir yet.
97 * Some of the vpopmail backends (eg mysql) allow users to
98 * be manually inserted into the auth backend but without
99 * allocating a dir. A dir will be created when the user
100 * first trys to auth (or when they 1st receive mail)
102 if (vpw
->pw_dir
== NULL
|| strlen(vpw
->pw_dir
) == 0 ) {
103 /* user does not have a dir allocated yet */
104 if ( make_user_dir(User
, Domain
, uid
, gid
) == NULL
) {
105 /* Could not allocate a user dir at this time
106 * so exit with a temp error code
108 DPRINTF("vchkpw: make_user_dir failed");
111 /* We have allocated the user a dir now.
112 * Go and grab the updated passwd entry
114 if ( (vpw
=vauth_getpw(User
, Domain
)) == NULL
) {
115 /* Could not get the passwd entry
116 * So exit with a permanent failure code
118 DPRINTF("vchkpw: could not get the password entry");
123 snprintf(options
, sizeof(options
),
124 "disablewebmail=%d,disablepop3=%d,disableimap=%d",
125 vpw
->pw_flags
& NO_WEBMAIL
? 1 : 0,
126 vpw
->pw_flags
& NO_POP
? 1 : 0,
127 vpw
->pw_flags
& NO_IMAP
? 1 : 0);
129 #ifdef HAVE_VSET_LASTAUTH
130 /* if we are keeping track of their last auth time,
131 * then store this value now. Note that this isnt
132 * consistent with the authentication via vchkpw
133 * because it only stores the lastauth attempt
134 * after the password has been verified. Here we are
135 * logging it after the user has been found to exist,
136 * but before the password has been verified. We could
137 * do the logging inside authvchkpw.c, but that would
138 * be a lot harder because we would have to go and
139 * parse_email() again there before calling vset_lastauth()
141 vset_lastauth(User
, Domain
, service
);
144 /* save the user's passwd fields into the appropriate
147 /*auth.sysusername = userid;*/
148 auth
.sysuserid
= &uid
;
149 auth
.sysgroupid
= gid
;
150 auth
.homedir
= vpw
->pw_dir
;
151 auth
.address
= userid
;
152 auth
.fullname
= vpw
->pw_gecos
;
153 auth
.passwd
= vpw
->pw_passwd
;
154 auth
.clearpasswd
= vpw
->pw_clear_passwd
;
155 auth
.options
= options
;
156 courier_authdebug_authinfo("DEBUG: authvchkpw: ", &auth
, 0, vpw
->pw_passwd
);
158 return ((*callback
)(&auth
, arg
));