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	"courierauth.h"
20 #include	"courierauthstaticlist.h"
21 #include	"courierauthdebug.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 
callback_userdb(struct authinfo * a,void * p)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 
auth_cram(const char * service,const char * authtype,char * authdata,int (* callback_func)(struct authinfo *,void *),void * callback_arg)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 
auth_userdb(const char * service,const char * authtype,char * authdata,int (* callback_func)(struct authinfo *,void *),void * callback_arg)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 
courier_authuserdb_init()209 struct authstaticinfo *courier_authuserdb_init()
210 {
211 	return &authuserdb_info;
212 }
213