Merge branch 'debian'
[hcoop/debian/courier-authlib.git] / authsqlite.cpp
1 /*
2 ** Copyright 2000-2008 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5 #if HAVE_CONFIG_H
6 #include "courier_auth_config.h"
7 #endif
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <pwd.h>
13 #if HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16
17 extern "C" {
18 #include "auth.h"
19 #include "courierauthstaticlist.h"
20 #include "courierauth.h"
21 #include "courierauthdebug.h"
22 #include "libhmac/hmac.h"
23 }
24
25 #include "authsqlite.h"
26
27 static int auth_sqlite_pre(const char *user, const char *service,
28 int (*callback)(struct authinfo *, void *), void *arg)
29 {
30 authsqliteuserinfo authinfo;
31 struct authinfo aa;
32
33 if (!auth_sqlite_getuserinfo(user, service, authinfo))
34 // Fatal error - such as Sqlite being down
35 return (1);
36
37 if (authinfo.home.empty()) // User not found
38 return (-1);
39
40 memset(&aa, 0, sizeof(aa));
41
42 /*aa.sysusername=user;*/
43 aa.sysuserid= &authinfo.uid;
44 aa.sysgroupid= authinfo.gid;
45 aa.homedir=authinfo.home.c_str();
46 aa.maildir=authinfo.maildir.empty() ? NULL:authinfo.maildir.c_str();
47 aa.address=authinfo.username.c_str();
48 aa.passwd=authinfo.cryptpw.c_str();
49 aa.clearpasswd=authinfo.clearpw.c_str();
50 aa.fullname=authinfo.fullname.c_str();
51 aa.quota=authinfo.quota.empty() ? NULL:authinfo.quota.c_str();
52 aa.options=authinfo.options.c_str();
53 return ((*callback)(&aa, arg));
54 }
55
56 extern void auth_sqlite_enumerate( void(*cb_func)(const char *name,
57 uid_t uid,
58 gid_t gid,
59 const char *homedir,
60 const char *maildir,
61 const char *options,
62 void *void_arg),
63 void *void_arg);
64
65 static bool docheckpw(authsqliteuserinfo &authinfo, const char *pass)
66 {
67 if (!authinfo.cryptpw.empty())
68 {
69 if (authcheckpassword(pass, authinfo.cryptpw.c_str()))
70 {
71 errno=EPERM;
72 return false; /* User/Password not found. */
73 }
74 }
75 else if (!authinfo.clearpw.empty())
76 {
77 if (authinfo.clearpw != pass)
78 {
79 if (courier_authdebug_login_level >= 2)
80 {
81 DPRINTF("supplied password '%s' does not match clearpasswd '%s'",
82 pass, authinfo.clearpw.c_str());
83 }
84 else
85 {
86 DPRINTF("supplied password does not match clearpasswd");
87 }
88 errno=EPERM;
89 return false;
90 }
91 }
92 else
93 {
94 DPRINTF("no password available to compare");
95 errno=EPERM;
96 return false; /* Username not found */
97 }
98 return true;
99 }
100
101 static int auth_sqlite_login(const char *service, char *authdata,
102 int (*callback_func)(struct authinfo *, void *),
103 void *callback_arg)
104 {
105 char *user, *pass;
106 authsqliteuserinfo authinfo;
107 struct authinfo aa;
108
109
110 if ((user=strtok(authdata, "\n")) == 0 ||
111 (pass=strtok(0, "\n")) == 0)
112 {
113 errno=EPERM;
114 return (-1);
115 }
116
117 if (!auth_sqlite_getuserinfo(user, service, authinfo))
118 // Fatal error - such as Sqlite being down
119 {
120 errno=EACCES;
121 return (1);
122 }
123
124 if (!docheckpw(authinfo, pass))
125 return (-1);
126
127 memset(&aa, 0, sizeof(aa));
128
129 aa.sysuserid= &authinfo.uid;
130 aa.sysgroupid= authinfo.gid;
131 aa.homedir=authinfo.home.c_str();
132 aa.maildir=authinfo.maildir.empty() ? NULL:authinfo.maildir.c_str();
133 aa.address=authinfo.username.c_str();
134 aa.quota=authinfo.quota.empty() ? NULL:authinfo.quota.c_str();
135 aa.fullname=authinfo.fullname.c_str();
136 aa.options=authinfo.options.c_str();
137 aa.clearpasswd=pass;
138 aa.passwd=authinfo.cryptpw.c_str();
139 courier_authdebug_authinfo("DEBUG: authsqlite: ", &aa,
140 authinfo.clearpw.c_str(),
141 authinfo.cryptpw.c_str());
142
143 return (*callback_func)(&aa, callback_arg);
144 }
145
146 static int auth_sqlite_changepw(const char *service, const char *user,
147 const char *pass,
148 const char *newpass)
149 {
150 authsqliteuserinfo authinfo;
151
152 if (!auth_sqlite_getuserinfo(user, service, authinfo))
153 {
154 errno=ENOENT;
155 return (-1);
156 }
157
158 if (!docheckpw(authinfo, pass))
159 {
160 errno=EPERM;
161 return (-1); /* User/Password not found. */
162 }
163
164 if (auth_sqlite_setpass(user, newpass, authinfo.cryptpw.c_str()))
165 {
166 errno=EPERM;
167 return (-1);
168 }
169 return (0);
170 }
171
172 static int auth_sqlite_cram(const char *service,
173 const char *authtype, char *authdata,
174 int (*callback_func)(struct authinfo *, void *),
175 void *callback_arg)
176 {
177 struct cram_callback_info cci;
178
179 if (auth_get_cram(authtype, authdata, &cci))
180 return (-1);
181
182 cci.callback_func=callback_func;
183 cci.callback_arg=callback_arg;
184
185 return auth_sqlite_pre(cci.user, service, &auth_cram_callback, &cci);
186 }
187
188 int auth_sqlite(const char *service, const char *authtype, char *authdata,
189 int (*callback_func)(struct authinfo *, void *),
190 void *callback_arg)
191 {
192 if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
193 return (auth_sqlite_login(service, authdata,
194 callback_func, callback_arg));
195
196 return (auth_sqlite_cram(service, authtype, authdata,
197 callback_func, callback_arg));
198 }
199
200 extern int auth_sqlite_pre(const char *user, const char *service,
201 int (*callback)(struct authinfo *, void *),
202 void *arg);
203
204 static struct authstaticinfo authsqlite_info={
205 "authsqlite",
206 auth_sqlite,
207 auth_sqlite_pre,
208 auth_sqlite_cleanup,
209 auth_sqlite_changepw,
210 auth_sqlite_cleanup,
211 auth_sqlite_enumerate};
212
213 extern "C" {
214 struct authstaticinfo *courier_authsqlite_init()
215 {
216 return &authsqlite_info;
217 }
218 }