Merge branch 'upstream'
[hcoop/debian/courier-authlib.git] / preauthvchkpw.c
1 /*
2 ** Copyright 1998 - 2001 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "courier_auth_config.h"
8 #endif
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <pwd.h>
14 #if HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 #include "auth.h"
18 #include "courierauthdebug.h"
19 #include <vpopmail.h>
20 #include <vauth.h>
21 #include "vpopmail_config.h"
22
23 /* make use of pw_flags only if available */
24 #ifndef VQPASSWD_HAS_PW_FLAGS
25 #define pw_flags pw_gid
26 #endif
27
28 extern FILE *authvchkpw_file(const char *, const char *);
29
30 static const char rcsid[]="$Id: preauthvchkpw.c,v 1.26 2007/04/22 18:53:30 mrsam Exp $";
31
32 /* This function is called by the auth_vchkpw() function
33 *
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
39 *
40 * Return -1 on perm failure
41 * Return 0 on success
42 * Return 1 on temp failure
43 *
44 */
45
46 int auth_vchkpw_pre(
47 const char *userid,
48 const char *service,
49 int (*callback)(struct authinfo *, void *),
50 void *arg)
51 {
52 struct vqpasswd *vpw;
53 static uid_t uid;
54 gid_t gid;
55 struct authinfo auth;
56 static char User[256];
57 static char Domain[256];
58 static char options[80];
59
60 /* Make sure the auth struct is empty */
61 memset(&auth, 0, sizeof(auth));
62
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
65 * the default domain)
66 */
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
70 */
71 DPRINTF("vchkpw: unable to split into user and domain");
72 return(-1);
73 }
74
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
79 */
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");
84 return (-1);
85 }
86
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
91 */
92 DPRINTF("vchkpw: user does not exist");
93 return (-1);
94 }
95
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)
101 */
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
107 */
108 DPRINTF("vchkpw: make_user_dir failed");
109 return(1);
110 }
111 /* We have allocated the user a dir now.
112 * Go and grab the updated passwd entry
113 */
114 if ( (vpw=vauth_getpw(User, Domain)) == NULL ) {
115 /* Could not get the passwd entry
116 * So exit with a permanent failure code
117 */
118 DPRINTF("vchkpw: could not get the password entry");
119 return(-1);
120 }
121 }
122
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);
128
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()
140 */
141 vset_lastauth(User, Domain, service);
142 #endif
143
144 /* save the user's passwd fields into the appropriate
145 * courier structure
146 */
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);
157
158 return ((*callback)(&auth, arg));
159 }