d9898ee8 |
1 | /* |
2 | ** Copyright 1998 - 2004 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 | |
18 | #include "auth.h" |
19 | #include "authstaticlist.h" |
20 | #include "courierauthdebug.h" |
21 | #include "cramlib.h" |
22 | #include "libhmac/hmac.h" |
23 | #include "userdb/userdb.h" |
24 | |
25 | static const char rcsid[]="$Id: authuserdb.c,v 1.24 2006/10/28 19:22:52 mrsam Exp $"; |
26 | |
27 | extern void auth_userdb_enumerate( void(*cb_func)(const char *name, |
28 | uid_t uid, |
29 | gid_t gid, |
30 | const char *homedir, |
31 | const char *maildir, |
32 | const char *options, |
33 | void *void_arg), |
34 | void *void_arg); |
35 | |
36 | extern int auth_userdb_pre_common(const char *, const char *, int, |
37 | int (*callback)(struct authinfo *, void *), |
38 | void *arg); |
39 | |
40 | extern void auth_userdb_cleanup(); |
41 | |
42 | struct callback_info { |
43 | const char *pass; |
44 | int (*callback_func)(struct authinfo *, void *); |
45 | void *callback_arg; |
46 | }; |
47 | |
48 | static int callback_userdb(struct authinfo *a, void *p) |
49 | { |
50 | struct callback_info *i=(struct callback_info *)p; |
51 | |
52 | if (a->passwd == 0) |
53 | { |
54 | DPRINTF("no password available to compare\n"); |
55 | errno=EPERM; |
56 | return (-1); |
57 | } |
58 | |
59 | if (authcheckpassword(i->pass, a->passwd)) |
60 | return (-1); |
61 | |
62 | a->clearpasswd=i->pass; |
63 | return (*i->callback_func)(a, i->callback_arg); |
64 | } |
65 | |
66 | |
67 | static int auth_cram(const char *service, const char *authtype, char *authdata, |
68 | int (*callback_func)(struct authinfo *, void *), |
69 | void *callback_arg) |
70 | { |
71 | char *u; |
72 | char *udbs; |
73 | char *passwords; |
74 | char *services; |
75 | struct userdbs *udb; |
76 | struct cram_callback_info cci; |
77 | |
78 | struct authinfo aa; |
79 | int rc; |
80 | |
81 | if (auth_get_cram(authtype, authdata, &cci)) |
82 | return (-1); |
83 | |
84 | userdb_set_debug(courier_authdebug_login_level); |
85 | userdb_init(USERDB ".dat"); |
86 | if ( (u=userdb(cci.user)) == 0) |
87 | { |
88 | userdb_close(); |
89 | return (-1); |
90 | } |
91 | |
92 | if ( (udbs=userdbshadow(USERDB "shadow.dat", cci.user)) == 0) |
93 | { |
94 | free(u); |
95 | userdb_close(); |
96 | return (-1); |
97 | } |
98 | |
99 | if ((services=malloc(strlen(service)+strlen(cci.h->hh_name) |
100 | +sizeof("-hmac-pw"))) == 0) |
101 | { |
102 | free(udbs); |
103 | free(u); |
104 | userdb_close(); |
105 | errno=ENOSPC; |
106 | return (1); /* tempfail */ |
107 | } |
108 | |
109 | strcat(strcat(strcat(strcpy(services, service), "-hmac-"), |
110 | cci.h->hh_name), "pw"); |
111 | |
112 | passwords=userdb_gets(udbs, services); |
113 | if (passwords == 0) |
114 | { |
115 | strcat(strcat(strcpy(services, "hmac-"), |
116 | cci.h->hh_name), "pw"); |
117 | passwords=userdb_gets(udbs, services); |
118 | } |
119 | if (passwords == 0) |
120 | { |
121 | DPRINTF("authcram: no %s-%s or %s value found", |
122 | service, services, services); |
123 | } |
124 | free(services); |
125 | |
126 | if (passwords == 0) |
127 | { |
128 | free(udbs); |
129 | free(u); |
130 | userdb_close(); |
131 | return (-1); |
132 | } |
133 | |
134 | if (auth_verify_cram(cci.h, cci.challenge, cci.response, |
135 | passwords)) |
136 | { |
137 | free(passwords); |
138 | free(udbs); |
139 | free(u); |
140 | userdb_close(); |
141 | return (-1); |
142 | } |
143 | |
144 | free(passwords); |
145 | free(udbs); |
146 | if ((udb=userdb_creates(u)) == 0) |
147 | { |
148 | free(u); |
149 | userdb_close(); |
150 | return (1); |
151 | } |
152 | |
153 | |
154 | memset(&aa, 0, sizeof(aa)); |
155 | |
156 | /*aa.sysusername=user;*/ |
157 | aa.sysuserid= &udb->udb_uid; |
158 | aa.sysgroupid= udb->udb_gid; |
159 | aa.homedir=udb->udb_dir; |
160 | aa.address=cci.user; |
161 | aa.maildir=udb->udb_mailbox; |
162 | aa.options=udb->udb_options; |
163 | rc=(*callback_func)(&aa, callback_arg); |
164 | |
165 | free(u); |
166 | userdb_close(); |
167 | |
168 | userdb_frees(udb); |
169 | return rc; |
170 | } |
171 | |
172 | int auth_userdb(const char *service, const char *authtype, char *authdata, |
173 | int (*callback_func)(struct authinfo *, void *), |
174 | void *callback_arg) |
175 | { |
176 | const char *user, *pass; |
177 | struct callback_info ci; |
178 | |
179 | if (strcmp(authtype, AUTHTYPE_LOGIN) || |
180 | (user=strtok(authdata, "\n")) == 0 || |
181 | (pass=strtok(0, "\n")) == 0) |
182 | return auth_cram(service, authtype, authdata, |
183 | callback_func, callback_arg); |
184 | |
185 | ci.pass=pass; |
186 | ci.callback_func=callback_func; |
187 | ci.callback_arg=callback_arg; |
188 | return auth_userdb_pre_common(user, service, 1, &callback_userdb, &ci); |
189 | } |
190 | |
191 | extern int auth_userdb_pre(const char *userid, const char *service, |
192 | int (*callback)(struct authinfo *, void *), |
193 | void *arg); |
194 | |
195 | extern int auth_userdb_passwd(const char *service, |
196 | const char *userid, |
197 | const char *opwd_buf, |
198 | const char *npwd_buf); |
199 | |
200 | static struct authstaticinfo authuserdb_info={ |
201 | "authuserdb", |
202 | auth_userdb, |
203 | auth_userdb_pre, |
204 | auth_userdb_cleanup, |
205 | auth_userdb_passwd, |
206 | auth_userdb_cleanup, |
207 | auth_userdb_enumerate}; |
208 | |
209 | |
210 | struct authstaticinfo *courier_authuserdb_init() |
211 | { |
212 | return &authuserdb_info; |
213 | } |