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 | |
d9898ee8 |
66 | static int auth_cram(const char *service, const char *authtype, char *authdata, |
67 | int (*callback_func)(struct authinfo *, void *), |
68 | void *callback_arg) |
69 | { |
70 | char *u; |
71 | char *udbs; |
72 | char *passwords; |
73 | char *services; |
74 | struct userdbs *udb; |
75 | struct cram_callback_info cci; |
76 | |
77 | struct authinfo aa; |
78 | int rc; |
79 | |
80 | if (auth_get_cram(authtype, authdata, &cci)) |
81 | return (-1); |
82 | |
83 | userdb_set_debug(courier_authdebug_login_level); |
84 | userdb_init(USERDB ".dat"); |
85 | if ( (u=userdb(cci.user)) == 0) |
86 | { |
87 | userdb_close(); |
88 | return (-1); |
89 | } |
90 | |
91 | if ( (udbs=userdbshadow(USERDB "shadow.dat", cci.user)) == 0) |
92 | { |
93 | free(u); |
94 | userdb_close(); |
95 | return (-1); |
96 | } |
97 | |
98 | if ((services=malloc(strlen(service)+strlen(cci.h->hh_name) |
99 | +sizeof("-hmac-pw"))) == 0) |
100 | { |
101 | free(udbs); |
102 | free(u); |
103 | userdb_close(); |
104 | errno=ENOSPC; |
105 | return (1); /* tempfail */ |
106 | } |
107 | |
108 | strcat(strcat(strcat(strcpy(services, service), "-hmac-"), |
109 | cci.h->hh_name), "pw"); |
110 | |
111 | passwords=userdb_gets(udbs, services); |
112 | if (passwords == 0) |
113 | { |
114 | strcat(strcat(strcpy(services, "hmac-"), |
115 | cci.h->hh_name), "pw"); |
116 | passwords=userdb_gets(udbs, services); |
117 | } |
118 | if (passwords == 0) |
119 | { |
120 | DPRINTF("authcram: no %s-%s or %s value found", |
121 | service, services, services); |
122 | } |
123 | free(services); |
124 | |
125 | if (passwords == 0) |
126 | { |
127 | free(udbs); |
128 | free(u); |
129 | userdb_close(); |
130 | return (-1); |
131 | } |
132 | |
133 | if (auth_verify_cram(cci.h, cci.challenge, cci.response, |
134 | passwords)) |
135 | { |
136 | free(passwords); |
137 | free(udbs); |
138 | free(u); |
139 | userdb_close(); |
140 | return (-1); |
141 | } |
142 | |
143 | free(passwords); |
144 | free(udbs); |
145 | if ((udb=userdb_creates(u)) == 0) |
146 | { |
147 | free(u); |
148 | userdb_close(); |
149 | return (1); |
150 | } |
151 | |
152 | |
153 | memset(&aa, 0, sizeof(aa)); |
154 | |
155 | /*aa.sysusername=user;*/ |
156 | aa.sysuserid= &udb->udb_uid; |
157 | aa.sysgroupid= udb->udb_gid; |
158 | aa.homedir=udb->udb_dir; |
159 | aa.address=cci.user; |
160 | aa.maildir=udb->udb_mailbox; |
161 | aa.options=udb->udb_options; |
1b37e792 |
162 | |
d9898ee8 |
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 | } |