Import Upstream version 0.69.0
[hcoop/debian/courier-authlib.git] / authsqlite.cpp
CommitLineData
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 17extern "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
27static 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
56extern 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 65static 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
101static 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
146static 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
172static 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
188int 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
200extern int auth_sqlite_pre(const char *user, const char *service,
201 int (*callback)(struct authinfo *, void *),
202 void *arg);
203
204static 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
213extern "C" {
214 struct authstaticinfo *courier_authsqlite_init()
215 {
216 return &authsqlite_info;
217 }
b0322a85 218}