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