d9898ee8 |
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 | } |