* All OS-level includes are now included from webcit.h instead of from
[citadel.git] / webcit / auth.c
1 /*
2  * $Id$
3  *
4  * Handles authentication of users to a Citadel server.
5  *
6  */
7
8
9 #include "webcit.h"
10
11 char *axdefs[] =
12 {
13         "Deleted",
14         "New User",
15         "Problem User",
16         "Local User",
17         "Network User",
18         "Preferred User",
19         "Aide"
20 };
21
22 /*
23  * Display the login screen
24  */
25 void display_login(char *mesg)
26 {
27         char buf[SIZ];
28
29         output_headers(1, 1, 2, 0, 0, 0, 0);
30         wprintf("<div style=\"position:absolute; top:20px; left:20px; right:20px\">\n");
31
32         if (mesg != NULL) if (strlen(mesg) > 0) {
33                 stresc(buf, mesg, 0, 0);
34                 svprintf("mesg", WCS_STRING, "%s", buf);
35         }
36
37         svprintf("hello", WCS_SERVCMD, "MESG hello");
38         svprintf("BOXTITLE", WCS_STRING, "%s - powered by Citadel",
39                 serv_info.serv_humannode);
40
41         do_template("login");
42
43         wDumpContent(2);
44 }
45
46
47
48
49 /*
50  * This function needs to get called whenever the session changes from
51  * not-logged-in to logged-in, either by an explicit login by the user or
52  * by a timed-out session automatically re-establishing with a little help
53  * from the browser cookie.  Either way, we need to load access controls and
54  * preferences from the server.
55  */
56 void become_logged_in(char *user, char *pass, char *serv_response)
57 {
58         char buf[SIZ];
59
60         WC->logged_in = 1;
61         extract_token(WC->wc_username, &serv_response[4], 0, '|', sizeof WC->wc_username);
62         safestrncpy(WC->wc_password, pass, sizeof WC->wc_password);
63         WC->axlevel = extract_int(&serv_response[4], 1);
64         if (WC->axlevel >= 6) {
65                 WC->is_aide = 1;
66         }
67
68         load_preferences();
69
70         serv_puts("CHEK");
71         serv_getln(buf, sizeof buf);
72         if (buf[0] == '2') {
73                 WC->new_mail = extract_int(&buf[4], 0);
74                 WC->need_regi = extract_int(&buf[4], 1);
75                 WC->need_vali = extract_int(&buf[4], 2);
76                 extract_token(WC->cs_inet_email, &buf[4], 3, '|', sizeof WC->cs_inet_email);
77         }
78 }
79
80
81 void do_login(void)
82 {
83         char buf[SIZ];
84
85         if (!strcasecmp(bstr("action"), "Exit")) {
86                 do_logout();
87                 return;
88         }
89         if (!strcasecmp(bstr("action"), "Login")) {
90                 serv_printf("USER %s", bstr("name"));
91                 serv_getln(buf, sizeof buf);
92                 if (buf[0] == '3') {
93                         serv_printf("PASS %s", bstr("pass"));
94                         serv_getln(buf, sizeof buf);
95                         if (buf[0] == '2') {
96                                 become_logged_in(bstr("name"),
97                                                  bstr("pass"), buf);
98                         } else {
99                                 display_login(&buf[4]);
100                                 return;
101                         }
102                 } else {
103                         display_login(&buf[4]);
104                         return;
105                 }
106         }
107         if (!strcasecmp(bstr("action"), "New User")) {
108                 if (strlen(bstr("pass")) == 0) {
109                         display_login("Blank passwords are not allowed.");
110                         return;
111                 }
112                 serv_printf("NEWU %s", bstr("name"));
113                 serv_getln(buf, sizeof buf);
114                 if (buf[0] == '2') {
115                         become_logged_in(bstr("name"), bstr("pass"), buf);
116                         serv_printf("SETP %s", bstr("pass"));
117                         serv_getln(buf, sizeof buf);
118                 } else {
119                         display_login(&buf[4]);
120                         return;
121                 }
122         }
123         if (WC->logged_in) {
124                 if (WC->need_regi) {
125                         display_reg(1);
126                 } else {
127                         do_welcome();
128                 }
129         } else {
130                 display_login("Your password was not accepted.");
131         }
132
133 }
134
135 void do_welcome(void)
136 {
137         char buf[SIZ];
138 #ifdef XXX_NOT_FINISHED_YET_XXX
139         FILE *fp;
140         int i;
141
142         /*
143          * See if we have to run the first-time setup wizard
144          */
145         if (WC->is_aide) {
146                 if (!setup_wizard) {
147                         sprintf(wizard_filename, "setupwiz.%s.%s",
148                                 ctdlhost, ctdlport);
149                         for (i=0; i<strlen(wizard_filename); ++i) {
150                                 if (    (wizard_filename[i]==' ')
151                                         || (wizard_filename[i] == '/')
152                                 ) {
153                                         wizard_filename[i] = '_';
154                                 }
155                         }
156         
157                         fp = fopen(wizard_filename, "r");
158                         if (fp != NULL) {
159                                 fgets(buf, sizeof buf, fp);
160                                 buf[strlen(buf)-1] = 0;
161                                 fclose(fp);
162                                 if (atoi(buf) == serv_info.serv_rev_level) {
163                                         setup_wizard = 1; /* already run */
164                                 }
165                         }
166                 }
167
168                 if (!setup_wizard) {
169                         http_redirect("/setup_wizard");
170                 }
171         }
172 #endif
173
174         /*
175          * Go to the user's preferred start page
176          */
177         get_preference("startpage", buf, sizeof buf);
178         if (strlen(buf)==0) {
179                 safestrncpy(buf, "/dotskip&room=_BASEROOM_", sizeof buf);
180                 set_preference("startpage", buf, 1);
181         }
182         http_redirect(buf);
183 }
184
185
186 /*
187  * Disconnect from the Citadel server, and end this WebCit session
188  */
189 void end_webcit_session(void) {
190         serv_puts("QUIT");
191         WC->killthis = 1;
192         /* close() of citadel socket will be done by do_housekeeping() */
193 }
194
195
196 void do_logout(void)
197 {
198         char buf[SIZ];
199
200         safestrncpy(WC->wc_username, "", sizeof WC->wc_username);
201         safestrncpy(WC->wc_password, "", sizeof WC->wc_password);
202         safestrncpy(WC->wc_roomname, "", sizeof WC->wc_roomname);
203
204         /* Calling output_headers() this way causes the cookies to be un-set */
205         output_headers(1, 1, 0, 1, 0, 0, 0);
206
207         wprintf("<center>");
208         serv_puts("MESG goodbye");
209         serv_getln(buf, sizeof buf);
210
211         if (WC->serv_sock >= 0) {
212                 if (buf[0] == '1') {
213                         fmout(NULL, "CENTER");
214                 } else {
215                         wprintf("Goodbye\n");
216                 }
217         }
218         else {
219                 wprintf("This program was unable to connect or stay "
220                         "connected to the Citadel server.  Please report "
221                         "this problem to your system administrator."
222                 );
223         }
224
225         wprintf("<hr /><a href=\"/\">Log in again</A>&nbsp;&nbsp;&nbsp;"
226                 "<a href=\"javascript:window.close();\">Close window</A>"
227                 "</center>\n");
228         wDumpContent(2);
229         end_webcit_session();
230 }
231
232
233 /* 
234  * validate new users
235  */
236 void validate(void)
237 {
238         char cmd[SIZ];
239         char user[SIZ];
240         char buf[SIZ];
241         int a;
242
243         output_headers(1, 1, 2, 0, 0, 0, 0);
244         wprintf("<div id=\"banner\">\n"
245                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
246                 "<SPAN CLASS=\"titlebar\">Validate new users</SPAN>"
247                 "</TD></TR></TABLE>\n"
248                 "</div>\n<div id=\"content\">\n"
249         );
250                                                                                                                              
251         safestrncpy(buf, bstr("user"), sizeof buf);
252         if (strlen(buf) > 0)
253                 if (strlen(bstr("axlevel")) > 0) {
254                         serv_printf("VALI %s|%s", buf, bstr("axlevel"));
255                         serv_getln(buf, sizeof buf);
256                         if (buf[0] != '2') {
257                                 wprintf("<b>%s</b><br />\n", &buf[4]);
258                         }
259                 }
260         serv_puts("GNUR");
261         serv_getln(buf, sizeof buf);
262
263         if (buf[0] != '3') {
264                 wprintf("<b>%s</b><br />\n", &buf[4]);
265                 wDumpContent(1);
266                 return;
267         }
268
269         wprintf("<div id=\"fix_scrollbar_bug\">"
270                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
271         wprintf("<center>");
272
273         safestrncpy(user, &buf[4], sizeof user);
274         serv_printf("GREG %s", user);
275         serv_getln(cmd, sizeof cmd);
276         if (cmd[0] == '1') {
277                 a = 0;
278                 do {
279                         serv_getln(buf, sizeof buf);
280                         ++a;
281                         if (a == 1)
282                                 wprintf("User #%s<br /><H1>%s</H1>",
283                                         buf, &cmd[4]);
284                         if (a == 2)
285                                 wprintf("PW: %s<br />\n", buf);
286                         if (a == 3)
287                                 wprintf("%s<br />\n", buf);
288                         if (a == 4)
289                                 wprintf("%s<br />\n", buf);
290                         if (a == 5)
291                                 wprintf("%s, ", buf);
292                         if (a == 6)
293                                 wprintf("%s ", buf);
294                         if (a == 7)
295                                 wprintf("%s<br />\n", buf);
296                         if (a == 8)
297                                 wprintf("%s<br />\n", buf);
298                         if (a == 9)
299                                 wprintf("Current access level: %d (%s)\n",
300                                         atoi(buf), axdefs[atoi(buf)]);
301                 } while (strcmp(buf, "000"));
302         } else {
303                 wprintf("<H1>%s</H1>%s<br />\n", user, &cmd[4]);
304         }
305
306         wprintf("<hr />Select access level for this user:<br />\n");
307         for (a = 0; a <= 6; ++a) {
308                 wprintf("<A HREF=\"/validate&user=");
309                 urlescputs(user);
310                 wprintf("&axlevel=%d\">%s</A>&nbsp;&nbsp;&nbsp;\n",
311                         a, axdefs[a]);
312         }
313         wprintf("<br />\n");
314
315         wprintf("</CENTER>\n");
316         wprintf("</td></tr></table></div>\n");
317         wDumpContent(1);
318 }
319
320
321
322 /* 
323  * Display form for registration.
324  * (Set during_login to 1 if this registration is being performed during
325  * new user login and will require chaining to the proper screen.)
326  */
327 void display_reg(int during_login)
328 {
329         long vcard_msgnum;
330
331         if (goto_config_room() != 0) {
332                 if (during_login) do_welcome();
333                 else display_main_menu();
334                 return;
335         }
336
337         vcard_msgnum = locate_user_vcard(WC->wc_username, -1);
338         if (vcard_msgnum < 0L) {
339                 if (during_login) do_welcome();
340                 else display_main_menu();
341                 return;
342         }
343
344         if (during_login) {
345                 do_edit_vcard(vcard_msgnum, "1", "/do_welcome");
346         }
347         else {
348                 do_edit_vcard(vcard_msgnum, "1", "/display_main_menu");
349         }
350
351 }
352
353
354
355
356 /* 
357  * display form for changing your password
358  */
359 void display_changepw(void)
360 {
361         char buf[SIZ];
362
363         output_headers(1, 1, 2, 0, 0, 0, 0);
364         wprintf("<div id=\"banner\">\n"
365                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
366                 "<SPAN CLASS=\"titlebar\">Change your password</SPAN>"
367                 "</TD></TR></TABLE>\n"
368                 "</div>\n<div id=\"content\">\n"
369         );
370
371         if (strlen(WC->ImportantMessage) > 0) {
372                 do_template("beginbox_nt");
373                 wprintf("<SPAN CLASS=\"errormsg\">"
374                         "%s</SPAN><br />\n", WC->ImportantMessage);
375                 do_template("endbox");
376                 safestrncpy(WC->ImportantMessage, "", sizeof WC->ImportantMessage);
377         }
378
379         wprintf("<div id=\"fix_scrollbar_bug\">"
380                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
381
382         wprintf("<CENTER><br />");
383         serv_puts("MESG changepw");
384         serv_getln(buf, sizeof buf);
385         if (buf[0] == '1') {
386                 fmout(NULL, "CENTER");
387         }
388
389         wprintf("<form name=\"changepwform\" action=\"changepw\" method=\"post\">\n");
390         wprintf("<CENTER>"
391                 "<table border=\"0\" cellspacing=\"5\" cellpadding=\"5\" "
392                 "BGCOLOR=\"#EEEEEE\">"
393                 "<TR><TD>Enter new password:</TD>\n");
394         wprintf("<TD><INPUT TYPE=\"password\" NAME=\"newpass1\" VALUE=\"\" MAXLENGTH=\"20\"></TD></TR>\n");
395         wprintf("<TR><TD>Enter it again to confirm:</TD>\n");
396         wprintf("<TD><INPUT TYPE=\"password\" NAME=\"newpass2\" VALUE=\"\" MAXLENGTH=\"20\"></TD></TR>\n");
397
398         wprintf("</TABLE><br />\n");
399         wprintf("<INPUT type=\"submit\" name=\"action\" value=\"Change\">"
400                 "&nbsp;"
401                 "<INPUT type=\"submit\" name=\"action\" value=\"Cancel\">\n");
402         wprintf("</form></center>\n");
403         wprintf("</td></tr></table></div>\n");
404         wDumpContent(1);
405 }
406
407 /*
408  * change password
409  */
410 void changepw(void)
411 {
412         char buf[SIZ];
413         char newpass1[32], newpass2[32];
414
415         if (strcmp(bstr("action"), "Change")) {
416                 safestrncpy(WC->ImportantMessage, 
417                         "Cancelled.  Password was not changed.",
418                         sizeof WC->ImportantMessage);
419                 display_main_menu();
420                 return;
421         }
422
423         safestrncpy(newpass1, bstr("newpass1"), sizeof newpass1);
424         safestrncpy(newpass2, bstr("newpass2"), sizeof newpass2);
425
426         if (strcasecmp(newpass1, newpass2)) {
427                 safestrncpy(WC->ImportantMessage, 
428                         "They don't match.  Password was not changed.",
429                         sizeof WC->ImportantMessage);
430                 display_changepw();
431                 return;
432         }
433
434         if (strlen(newpass1) == 0) {
435                 safestrncpy(WC->ImportantMessage, 
436                         "Blank passwords are not allowed.",
437                         sizeof WC->ImportantMessage);
438                 display_changepw();
439                 return;
440         }
441
442         serv_printf("SETP %s", newpass1);
443         serv_getln(buf, sizeof buf);
444         sprintf(WC->ImportantMessage, "%s", &buf[4]);
445         if (buf[0] == '2') {
446                 safestrncpy(WC->wc_password, buf, sizeof WC->wc_password);
447                 display_main_menu();
448         }
449         else {
450                 display_changepw();
451         }
452 }