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 
auth_sqlite_pre(const char * user,const char * service,int (* callback)(struct authinfo *,void *),void * arg)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 
docheckpw(authsqliteuserinfo & authinfo,const char * pass)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 
auth_sqlite_login(const char * service,char * authdata,int (* callback_func)(struct authinfo *,void *),void * callback_arg)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 
auth_sqlite_changepw(const char * service,const char * user,const char * pass,const char * newpass)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 
auth_sqlite_cram(const char * service,const char * authtype,char * authdata,int (* callback_func)(struct authinfo *,void *),void * callback_arg)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 
auth_sqlite(const char * service,const char * authtype,char * authdata,int (* callback_func)(struct authinfo *,void *),void * callback_arg)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" {
courier_authsqlite_init()214 	struct authstaticinfo *courier_authsqlite_init()
215 	{
216 		return &authsqlite_info;
217 	}
218 }
219