Imported Upstream version 0.66.1
[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 "courierauthstaticlist.h"
20 #include "courierauthdebug.h"
21 #include "cramlib.h"
22 #include "libhmac/hmac.h"
23 #include "userdb/userdb.h"
24
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 }