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