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