1 /*
2 ** Copyright 1998 - 2015 Double Precision, Inc.  See COPYING for
3 ** distribution information.
4 */
5 
6 
7 /*
8 */
9 
10 #include	"sqwebmail.h"
11 #include	"config.h"
12 
13 #if	HAVE_SYS_STAT_H
14 #include	<sys/stat.h>
15 #endif
16 #if HAVE_SYS_WAIT_H
17 #include	<sys/wait.h>
18 #endif
19 
20 #if	HAVE_UNISTD_H
21 #include	<unistd.h>
22 #endif
23 
24 #include	<stdio.h>
25 #include	<stdlib.h>
26 #include	<ctype.h>
27 #include	<courierauth.h>
28 #if	HAVE_UNISTD_H
29 #include	<unistd.h>
30 #endif
31 #include	<string.h>
32 #include	<errno.h>
33 
34 #include	"maildir/loginexec.h"
35 #include	"courierauthdebug.h"
36 #include	"auth.h"
37 #include	"htmllibdir.h"
38 
39 extern int check_sqwebpass(const char *);
40 
41 extern char *sqwebmail_content_charset, *sqwebmail_system_charset;
42 #include	<courier-unicode.h>
43 
myhostname()44 const char *myhostname()
45 {
46 char    buf[512];
47 static char *my_hostname=0;
48 FILE	*f;
49 
50 	if (my_hostname == 0)
51 	{
52 		buf[0]=0;
53 		if ((f=fopen(HOSTNAMEFILE, "r")) != 0)
54 		{
55 		char *p;
56 
57 			if (fgets(buf, sizeof(buf), f) == NULL)
58 				buf[0]=0;
59 
60 			fclose(f);
61 
62 			if ((p=strchr(buf, '\n')) != 0)
63 				*p=0;
64 		}
65 
66 		if (buf[0] == 0 && gethostname(buf, sizeof(buf)-1))
67 			strcpy(buf, "localhost");
68 
69 		if ((my_hostname=malloc(strlen(buf)+1)) == 0)
70 			enomem();
71 		strcpy(my_hostname, buf);
72 	}
73 	return (my_hostname);
74 }
75 
login_maildir(const char * maildir)76 static int login_maildir(const char *maildir)
77 {
78 	if (!maildir || !*maildir)
79 		maildir=getenv("MAILDIRPATH");
80 	if (!maildir || !*maildir)
81 		maildir="Maildir";
82 	if (chdir(maildir))	return (-1);
83 	maildir_loginexec();
84 	return (0);
85 }
86 
doauthlogin(struct authinfo * a,void * vp)87 static int doauthlogin(struct authinfo *a, void *vp)
88 {
89 	const char *p=auth_getoption(a->options ? a->options:"",
90 				     "disablewebmail");
91 	const char *c=(const char *)vp;
92 
93 	static char *authaddr=NULL;
94 	static char *authfullname=NULL;
95 	static char *authoptions=NULL;
96 	static char *authenticated=NULL;
97 	const char *n;
98 	char *b;
99 	int rc;
100 
101 
102 	if (p && atoi(p))
103 		return -1;
104 
105 	if ((rc = auth_callback_default_autocreate(a)) != 0)
106 	{
107 		if (rc > 0)
108 			perror("ERR: authentication error");
109 		return -1;
110 	}
111 
112 	if (login_maildir(a->maildir))
113 	{
114 		error("Unable to open the maildir for this account -- the maildir doesn't exist or has incorrect ownership or permissions.");
115 		return (-1);
116 	}
117 
118 	b=malloc(sizeof("AUTHADDR=")+strlen(c));
119 
120 	if (!b)
121 		enomem();
122 	strcat(strcpy(b, "AUTHADDR="), c);
123 	putenv(b);
124 	if (authaddr)
125 		free(authaddr);
126 	authaddr=b;
127 
128 
129 	n=a->fullname;
130 	if (!n) n="";
131 	b=malloc(sizeof("AUTHFULLNAME=")+strlen(n));
132 
133 	if (!b)
134 		enomem();
135 	strcat(strcpy(b, "AUTHFULLNAME="), n);
136 	putenv(b);
137 	if (authfullname)
138 		free(authfullname);
139 	authfullname=b;
140 
141 	n=a->options;
142 	if (!n) n="";
143 
144 	b=malloc(sizeof("OPTIONS=")+strlen(n));
145 
146 	if (!b)
147 		enomem();
148 	strcat(strcpy(b, "OPTIONS="), n);
149 	putenv(b);
150 	if (authoptions)
151 		free(authoptions);
152 	authoptions=b;
153 
154 	n=a->address;
155 	if (!n) n="";
156 
157 	b=malloc(sizeof("AUTHENTICATED=")+strlen(n));
158 
159 	if (!b)
160 		enomem();
161 	strcat(strcpy(b, "AUTHENTICATED="), n);
162 	putenv(b);
163 	if (authenticated)
164 		free(authenticated);
165 	authenticated=b;
166 
167 	return (0);
168 }
169 
do_login(const char * u,const char * p,const char * ip)170 const char *do_login(const char *u, const char *p, const char *ip)
171 {
172 	char ipbuf[strlen(ip)+sizeof("TCPREMOTEIP=")];
173 	char *envvars[2]={ipbuf, 0};
174 	struct auth_meta meta;
175 
176 	strcat(strcpy(ipbuf, "TCPREMOTEIP="), ip);
177 
178 	memset(&meta, 0, sizeof(meta));
179 	meta.envvars=envvars;
180 
181 	if (auth_login_meta(&meta, "webmail", u, p, doauthlogin, (void *)u))
182 	{
183 		courier_safe_printf("INFO: LOGIN FAILED, user=%s, ip=[%s]",
184 				  u?u:"", ip);
185 		return NULL;
186 	}
187 
188 	fprintf(stderr, "INFO: LOGIN, user=%s, ip=[%s]\n", u, ip);
189 	return u;
190 }
191 
nochangepass()192 int nochangepass()
193 {
194 	if (auth_getoptionenvint("wbnochangepass")) return 1;
195 	if (access(SQWEBPASSWD, X_OK)) return 1;
196 	return 0;
197 }
198 
199 /*
200 ** login_changepwd tries to call the password change function for the
201 ** authentication module.
202 **
203 ** Returns -1 if authentication module does not have a password change
204 ** function.
205 **
206 ** Returns 0 if the authentication module has a password change function.
207 **
208 ** *rc is set to 0 if password was changed, non-zero otherwise
209 */
210 
login_changepwd(const char * u,const char * oldpwd,const char * newpwd,int * rc)211 int login_changepwd(const char *u, const char *oldpwd, const char *newpwd,
212 		    int *rc)
213 {
214 	if (nochangepass())
215 		return -1;
216 
217 	*rc= -1;
218 
219 	if (changepw("webmail", u, oldpwd, newpwd) == 0)
220 	{
221 		*rc=0;
222 	}
223 	return 0;
224 }
225 
prelogin(const char * u)226 int prelogin(const char *u)
227 {
228 	return auth_getuserinfo("webmail", u, doauthlogin, (void *)u);
229 }
230 
login_returnaddr()231 const char *login_returnaddr()
232 {
233 	static char *addrbuf=0;
234 	const char *p, *domain="";
235 
236 	if ((p=getenv("AUTHENTICATED")) == NULL || *p == 0)
237 		p=getenv("AUTHADDR");
238 	if (!p)	p="";
239 	if (strchr(p, '@') == 0)
240 		domain=myhostname();
241 
242 	if (addrbuf)	free(addrbuf);
243 	addrbuf=malloc(strlen(domain)+strlen(p)+2);
244 	if (!addrbuf)	enomem();
245 
246 	strcpy(addrbuf, p);
247 	if (*domain)
248 		strcat(strcat(addrbuf, "@"), domain);
249 	return (addrbuf);
250 }
251 
login_fromhdr()252 const char *login_fromhdr()
253 {
254 const char *address=login_returnaddr();
255 const char *fullname=getenv("AUTHFULLNAME");
256 int	l;
257 const char *p;
258 char	*q;
259 
260 static char *hdrbuf=0;
261 
262 FILE *fp;
263 char authcharset[128];
264 char *ufullname=0;
265 static char *uhdrbuf=0;
266 
267 	if (!fullname || !*fullname)
268 		return (address);	/* That was easy */
269 
270 	authcharset[0] = 0;
271 	if ((fp=fopen(AUTHCHARSET, "r")))
272 	{
273 		char *p;
274 		if (fgets(authcharset, sizeof(authcharset), fp) == NULL)
275 			authcharset[0]=0;
276 		fclose(fp);
277 
278 		if ((p=strchr(authcharset, '\n')))
279 			*p = '\0';
280 	}
281 
282 	if (authcharset[0] == 0
283 	    && sqwebmail_system_charset && *sqwebmail_system_charset
284 	    && strcasecmp(sqwebmail_system_charset, "ASCII"))
285 		strncat(authcharset, sqwebmail_system_charset,
286 			sizeof(authcharset)-1);
287 
288 	if (authcharset[0]
289 	    && sqwebmail_content_charset && *sqwebmail_content_charset
290 	    && (ufullname=unicode_convert_toutf8(fullname, authcharset,NULL)))
291 		fullname = ufullname;
292 
293 	l=sizeof("\"\" <>")+strlen(address)+strlen(fullname);
294 
295 	for (p=fullname; *p; p++)
296 		if (*p == '"' || *p == '\\' || *p == '(' || *p == ')' ||
297 			*p == '<' || *p == '>')	++l;
298 
299 	for (p=address; *p; p++)
300 		if (*p == '"' || *p == '\\' || *p == '(' || *p == ')' ||
301 			*p == '<' || *p == '>')	++l;
302 
303 	if (hdrbuf)	free(hdrbuf);
304 	hdrbuf=malloc(l);
305 	if (!hdrbuf)	enomem();
306 	q=hdrbuf;
307 	*q++='"';
308 	for (p=fullname; *p; p++)
309 	{
310 		if (*p == '"' || *p == '\\' || *p == '(' || *p == ')' ||
311 			*p == '<' || *p == '>')	*q++ = '\\';
312 		*q++= *p;
313 	}
314 	*q++='"';
315 	*q++=' ';
316 	*q++='<';
317 	for (p=address; *p; p++)
318 	{
319 		if (*p == '"' || *p == '\\' || *p == '(' || *p == ')' ||
320 			*p == '<' || *p == '>')	*q++ = '\\';
321 		*q++= *p;
322 	}
323 	*q++='>';
324 	*q=0;
325 
326 	if (ufullname)	free(ufullname);
327 	if (uhdrbuf)	free(uhdrbuf);
328 	if ((uhdrbuf=unicode_convert_fromutf8(hdrbuf,
329 						sqwebmail_content_charset,
330 						NULL)) != NULL)
331 		return (uhdrbuf);
332 
333 	return (hdrbuf);
334 }
335