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