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" |
b0322a85 |
19 | #include "courierauthstaticlist.h" |
d9898ee8 |
20 | #include "courierauthdebug.h" |
21 | #include "cramlib.h" |
22 | #include "libhmac/hmac.h" |
23 | #include "userdb/userdb.h" |
24 | |
d9898ee8 |
25 | |
26 | extern void auth_userdb_enumerate( void(*cb_func)(const char *name, |
27 | uid_t uid, |
28 | gid_t gid, |
29 | const char *homedir, |
30 | const char *maildir, |
31 | const char *options, |
32 | void *void_arg), |
33 | void *void_arg); |
34 | |
35 | extern int auth_userdb_pre_common(const char *, const char *, int, |
36 | int (*callback)(struct authinfo *, void *), |
37 | void *arg); |
38 | |
39 | extern void auth_userdb_cleanup(); |
40 | |
41 | struct callback_info { |
42 | const char *pass; |
43 | int (*callback_func)(struct authinfo *, void *); |
44 | void *callback_arg; |
45 | }; |
46 | |
47 | static int callback_userdb(struct authinfo *a, void *p) |
48 | { |
49 | struct callback_info *i=(struct callback_info *)p; |
50 | |
51 | if (a->passwd == 0) |
52 | { |
53 | DPRINTF("no password available to compare\n"); |
54 | errno=EPERM; |
55 | return (-1); |
56 | } |
57 | |
58 | if (authcheckpassword(i->pass, a->passwd)) |
59 | return (-1); |
60 | |
61 | a->clearpasswd=i->pass; |
62 | return (*i->callback_func)(a, i->callback_arg); |
63 | } |
64 | |
65 | |
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; |
162 | rc=(*callback_func)(&aa, callback_arg); |
163 | |
164 | free(u); |
165 | userdb_close(); |
166 | |
167 | userdb_frees(udb); |
168 | return rc; |
169 | } |
170 | |
171 | int auth_userdb(const char *service, const char *authtype, char *authdata, |
172 | int (*callback_func)(struct authinfo *, void *), |
173 | void *callback_arg) |
174 | { |
175 | const char *user, *pass; |
176 | struct callback_info ci; |
177 | |
178 | if (strcmp(authtype, AUTHTYPE_LOGIN) || |
179 | (user=strtok(authdata, "\n")) == 0 || |
180 | (pass=strtok(0, "\n")) == 0) |
181 | return auth_cram(service, authtype, authdata, |
182 | callback_func, callback_arg); |
183 | |
184 | ci.pass=pass; |
185 | ci.callback_func=callback_func; |
186 | ci.callback_arg=callback_arg; |
187 | return auth_userdb_pre_common(user, service, 1, &callback_userdb, &ci); |
188 | } |
189 | |
190 | extern int auth_userdb_pre(const char *userid, const char *service, |
191 | int (*callback)(struct authinfo *, void *), |
192 | void *arg); |
193 | |
194 | extern int auth_userdb_passwd(const char *service, |
195 | const char *userid, |
196 | const char *opwd_buf, |
197 | const char *npwd_buf); |
198 | |
199 | static struct authstaticinfo authuserdb_info={ |
200 | "authuserdb", |
201 | auth_userdb, |
202 | auth_userdb_pre, |
203 | auth_userdb_cleanup, |
204 | auth_userdb_passwd, |
205 | auth_userdb_cleanup, |
206 | auth_userdb_enumerate}; |
207 | |
208 | |
209 | struct authstaticinfo *courier_authuserdb_init() |
210 | { |
211 | return &authuserdb_info; |
212 | } |