34630ceaea19472592b138cc11ada2118906f8f5
[hcoop/debian/courier-authlib.git] / authuserdb.c
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 #define TOKEN_CMD "/etc/courier/get-token "
67
68 static int auth_cram(const char *service, const char *authtype, char *authdata,
69 int (*callback_func)(struct authinfo *, void *),
70 void *callback_arg)
71 {
72 char *u;
73 char *udbs;
74 char *passwords;
75 char *services;
76 struct userdbs *udb;
77 struct cram_callback_info cci;
78
79 struct authinfo aa;
80 int rc;
81
82 if (auth_get_cram(authtype, authdata, &cci))
83 return (-1);
84
85 userdb_set_debug(courier_authdebug_login_level);
86 userdb_init(USERDB ".dat");
87 if ( (u=userdb(cci.user)) == 0)
88 {
89 userdb_close();
90 return (-1);
91 }
92
93 if ( (udbs=userdbshadow(USERDB "shadow.dat", cci.user)) == 0)
94 {
95 free(u);
96 userdb_close();
97 return (-1);
98 }
99
100 if ((services=malloc(strlen(service)+strlen(cci.h->hh_name)
101 +sizeof("-hmac-pw"))) == 0)
102 {
103 free(udbs);
104 free(u);
105 userdb_close();
106 errno=ENOSPC;
107 return (1); /* tempfail */
108 }
109
110 strcat(strcat(strcat(strcpy(services, service), "-hmac-"),
111 cci.h->hh_name), "pw");
112
113 passwords=userdb_gets(udbs, services);
114 if (passwords == 0)
115 {
116 strcat(strcat(strcpy(services, "hmac-"),
117 cci.h->hh_name), "pw");
118 passwords=userdb_gets(udbs, services);
119 }
120 if (passwords == 0)
121 {
122 DPRINTF("authcram: no %s-%s or %s value found",
123 service, services, services);
124 }
125 free(services);
126
127 if (passwords == 0)
128 {
129 free(udbs);
130 free(u);
131 userdb_close();
132 return (-1);
133 }
134
135 if (auth_verify_cram(cci.h, cci.challenge, cci.response,
136 passwords))
137 {
138 free(passwords);
139 free(udbs);
140 free(u);
141 userdb_close();
142 return (-1);
143 }
144
145 free(passwords);
146 free(udbs);
147 if ((udb=userdb_creates(u)) == 0)
148 {
149 free(u);
150 userdb_close();
151 return (1);
152 }
153
154
155 memset(&aa, 0, sizeof(aa));
156
157 /*aa.sysusername=user;*/
158 aa.sysuserid= &udb->udb_uid;
159 aa.sysgroupid= udb->udb_gid;
160 aa.homedir=udb->udb_dir;
161 aa.address=cci.user;
162 aa.maildir=udb->udb_mailbox;
163 aa.options=udb->udb_options;
164
165 /* Get tokens for AFS */
166 { char uidstr[32] = "<null>";
167 char *token_cmd;
168 if (aa.sysuserid)
169 {
170 snprintf(uidstr, sizeof(uidstr), "%ld", (long)*aa.sysuserid);
171 if ((token_cmd=malloc(sizeof(TOKEN_CMD)+strlen(uidstr))))
172 {
173 strcat(strcpy(token_cmd, TOKEN_CMD),uidstr);
174 system(token_cmd);
175 free(token_cmd);
176 }
177 }
178 }
179
180 rc=(*callback_func)(&aa, callback_arg);
181
182 free(u);
183 userdb_close();
184
185 userdb_frees(udb);
186 return rc;
187 }
188
189 int auth_userdb(const char *service, const char *authtype, char *authdata,
190 int (*callback_func)(struct authinfo *, void *),
191 void *callback_arg)
192 {
193 const char *user, *pass;
194 struct callback_info ci;
195
196 if (strcmp(authtype, AUTHTYPE_LOGIN) ||
197 (user=strtok(authdata, "\n")) == 0 ||
198 (pass=strtok(0, "\n")) == 0)
199 return auth_cram(service, authtype, authdata,
200 callback_func, callback_arg);
201
202 ci.pass=pass;
203 ci.callback_func=callback_func;
204 ci.callback_arg=callback_arg;
205 return auth_userdb_pre_common(user, service, 1, &callback_userdb, &ci);
206 }
207
208 extern int auth_userdb_pre(const char *userid, const char *service,
209 int (*callback)(struct authinfo *, void *),
210 void *arg);
211
212 extern int auth_userdb_passwd(const char *service,
213 const char *userid,
214 const char *opwd_buf,
215 const char *npwd_buf);
216
217 static struct authstaticinfo authuserdb_info={
218 "authuserdb",
219 auth_userdb,
220 auth_userdb_pre,
221 auth_userdb_cleanup,
222 auth_userdb_passwd,
223 auth_userdb_cleanup,
224 auth_userdb_enumerate};
225
226
227 struct authstaticinfo *courier_authuserdb_init()
228 {
229 return &authuserdb_info;
230 }