Commit | Line | Data |
---|---|---|
b0322a85 CE |
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 | ||
0e333c05 | 17 | extern "C" { |
b0322a85 | 18 | #include "auth.h" |
b0322a85 | 19 | #include "courierauthstaticlist.h" |
0e333c05 | 20 | #include "courierauth.h" |
b0322a85 CE |
21 | #include "courierauthdebug.h" |
22 | #include "libhmac/hmac.h" | |
0e333c05 CE |
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; | |
b0322a85 | 32 | |
0e333c05 CE |
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 | } | |
b0322a85 CE |
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 | ||
0e333c05 | 65 | static bool docheckpw(authsqliteuserinfo &authinfo, const char *pass) |
b0322a85 | 66 | { |
0e333c05 | 67 | if (!authinfo.cryptpw.empty()) |
b0322a85 | 68 | { |
0e333c05 | 69 | if (authcheckpassword(pass, authinfo.cryptpw.c_str())) |
b0322a85 CE |
70 | { |
71 | errno=EPERM; | |
0e333c05 | 72 | return false; /* User/Password not found. */ |
b0322a85 CE |
73 | } |
74 | } | |
0e333c05 | 75 | else if (!authinfo.clearpw.empty()) |
b0322a85 | 76 | { |
0e333c05 | 77 | if (authinfo.clearpw != pass) |
b0322a85 CE |
78 | { |
79 | if (courier_authdebug_login_level >= 2) | |
80 | { | |
81 | DPRINTF("supplied password '%s' does not match clearpasswd '%s'", | |
0e333c05 | 82 | pass, authinfo.clearpw.c_str()); |
b0322a85 CE |
83 | } |
84 | else | |
85 | { | |
86 | DPRINTF("supplied password does not match clearpasswd"); | |
87 | } | |
88 | errno=EPERM; | |
0e333c05 | 89 | return false; |
b0322a85 CE |
90 | } |
91 | } | |
92 | else | |
93 | { | |
94 | DPRINTF("no password available to compare"); | |
95 | errno=EPERM; | |
0e333c05 CE |
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); | |
b0322a85 CE |
115 | } |
116 | ||
0e333c05 CE |
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 | ||
b0322a85 CE |
127 | memset(&aa, 0, sizeof(aa)); |
128 | ||
0e333c05 CE |
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(); | |
b0322a85 | 137 | aa.clearpasswd=pass; |
0e333c05 | 138 | aa.passwd=authinfo.cryptpw.c_str(); |
b0322a85 | 139 | courier_authdebug_authinfo("DEBUG: authsqlite: ", &aa, |
0e333c05 CE |
140 | authinfo.clearpw.c_str(), |
141 | authinfo.cryptpw.c_str()); | |
b0322a85 CE |
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 | { | |
0e333c05 | 150 | authsqliteuserinfo authinfo; |
b0322a85 | 151 | |
0e333c05 | 152 | if (!auth_sqlite_getuserinfo(user, service, authinfo)) |
b0322a85 CE |
153 | { |
154 | errno=ENOENT; | |
155 | return (-1); | |
156 | } | |
157 | ||
0e333c05 | 158 | if (!docheckpw(authinfo, pass)) |
b0322a85 CE |
159 | { |
160 | errno=EPERM; | |
0e333c05 | 161 | return (-1); /* User/Password not found. */ |
b0322a85 CE |
162 | } |
163 | ||
0e333c05 | 164 | if (auth_sqlite_setpass(user, newpass, authinfo.cryptpw.c_str())) |
b0322a85 CE |
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 | ||
0e333c05 CE |
213 | extern "C" { |
214 | struct authstaticinfo *courier_authsqlite_init() | |
215 | { | |
216 | return &authsqlite_info; | |
217 | } | |
b0322a85 | 218 | } |