indent -kr -i8 -brf -bbb -fnc -l132 -nce on all of webcit-classic
[citadel.git] / webcit / auth.c
1
2 /*
3  * These functions handle authentication of users to a Citadel server.
4  *
5  * Copyright (c) 1996-2021 by the citadel.org team
6  *
7  * This program is open source software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License, version 3.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include "webcit.h"
17 #include "webserver.h"
18 #include <ctype.h>
19
20 extern uint32_t hashlittle(const void *key, size_t length, uint32_t initval);
21
22 /*
23  * Access level definitions.  This is initialized from a function rather than a
24  * static array so that the strings may be localized.
25  */
26 char *axdefs[7];
27
28 void initialize_axdefs(void) {
29
30         /* an erased user */
31         axdefs[0] = _("Deleted");
32
33         /* a new user */
34         axdefs[1] = _("New User");
35
36         /* a trouble maker */
37         axdefs[2] = _("Problem User");
38
39         /* user with normal privileges */
40         axdefs[3] = _("Local User");
41
42         /* a user that may access network resources */
43         axdefs[4] = _("Network User");
44
45         /* a moderator */
46         axdefs[5] = _("Preferred User");
47
48         /* chief */
49         axdefs[6] = _("Admin");
50 }
51
52
53
54 /* 
55  * Display the login screen
56  * mesg = the error message if last attempt failed.
57  */
58 void display_login(void) {
59         begin_burst();
60         output_headers(1, 0, 0, 0, 1, 0);
61         do_template("login");
62         end_burst();
63 }
64
65
66
67
68
69 /* Initialize the session
70  *
71  * This function needs to get called whenever the session changes from
72  * not-logged-in to logged-in, either by an explicit login by the user or
73  * by a timed-out session automatically re-establishing with a little help
74  * from the browser cookie.  Either way, we need to load access controls and
75  * preferences from the server.
76  *
77  * user                 the username
78  * pass                 his password
79  * serv_response        The parameters returned from a Citadel USER or NEWU command
80  */
81 void become_logged_in(const StrBuf * user, const StrBuf * pass, StrBuf * serv_response) {
82         wcsession *WCC = WC;
83         StrBuf *Buf;
84         StrBuf *FloorDiv;
85
86         WCC->logged_in = 1;
87
88         if (WCC->wc_fullname == NULL)
89                 WCC->wc_fullname = NewStrBufPlain(NULL, StrLength(serv_response));
90         StrBufExtract_token(WCC->wc_fullname, serv_response, 0, '|');
91         StrBufCutLeft(WCC->wc_fullname, 4);
92
93         if (WCC->wc_username == NULL)
94                 WCC->wc_username = NewStrBufDup(user);
95         else {
96                 FlushStrBuf(WCC->wc_username);
97                 StrBufAppendBuf(WCC->wc_username, user, 0);
98         }
99
100         if (WCC->wc_password == NULL)
101                 WCC->wc_password = NewStrBufDup(pass);
102         else {
103                 FlushStrBuf(WCC->wc_password);
104                 StrBufAppendBuf(WCC->wc_password, pass, 0);
105         }
106
107         WCC->axlevel = StrBufExtract_int(serv_response, 1, '|');
108         if (WCC->axlevel >= 6) {
109                 WCC->is_aide = 1;
110         }
111
112         load_preferences();
113
114         Buf = NewStrBuf();
115         serv_puts("CHEK");
116         StrBuf_ServGetln(Buf);
117         if (GetServerStatus(Buf, NULL) == 2) {
118                 const char *pch;
119
120                 pch = ChrPtr(Buf) + 4;
121                 /*WCC->new_mail  = */ StrBufExtractNext_long(Buf, &pch, '|');
122                 WCC->need_regi = StrBufExtractNext_long(Buf, &pch, '|');
123                 WCC->need_vali = StrBufExtractNext_long(Buf, &pch, '|');
124                 if (WCC->cs_inet_email == NULL)
125                         WCC->cs_inet_email = NewStrBuf();
126                 StrBufExtract_NextToken(WCC->cs_inet_email, Buf, &pch, '|');
127         }
128         get_preference("floordiv_expanded", &FloorDiv);
129         WCC->floordiv_expanded = FloorDiv;
130         FreeStrBuf(&Buf);
131         FlushRoomlist();
132 }
133
134
135 /* 
136  * modal/ajax version of 'login' (username and password)
137  */
138 void ajax_login_username_password(void) {
139         StrBuf *Buf = NewStrBuf();
140
141         serv_printf("USER %s", bstr("name"));
142         StrBuf_ServGetln(Buf);
143         if (GetServerStatus(Buf, NULL) == 3) {
144                 serv_printf("PASS %s", bstr("pass"));
145                 StrBuf_ServGetln(Buf);
146                 if (GetServerStatus(Buf, NULL) == 2) {
147                         become_logged_in(sbstr("name"), sbstr("pass"), Buf);
148                 }
149         }
150
151         /* The client is expecting to read back a citadel protocol response */
152         wc_printf("%s", ChrPtr(Buf));
153         FreeStrBuf(&Buf);
154 }
155
156
157
158 /* 
159  * modal/ajax version of 'new user' (username and password)
160  */
161 void ajax_login_newuser(void) {
162         StrBuf *NBuf = NewStrBuf();
163         StrBuf *SBuf = NewStrBuf();
164
165         serv_printf("NEWU %s", bstr("name"));
166         StrBuf_ServGetln(NBuf);
167         if (GetServerStatus(NBuf, NULL) == 2) {
168                 become_logged_in(sbstr("name"), sbstr("pass"), NBuf);
169                 serv_printf("SETP %s", bstr("pass"));
170                 StrBuf_ServGetln(SBuf);
171         }
172
173         /* The client is expecting to read back a citadel protocol response */
174         wc_printf("%s", ChrPtr(NBuf));
175         FreeStrBuf(&NBuf);
176         FreeStrBuf(&SBuf);
177 }
178
179
180
181 /* 
182  * Try to create an account manually after an OpenID was verified
183  */
184 void openid_manual_create(void) {
185         StrBuf *Buf;
186
187         /* Did the user change his mind?  Pack up and go home. */
188         if (havebstr("exit_action")) {
189                 begin_burst();
190                 output_headers(1, 0, 0, 0, 1, 0);
191                 do_template("authpopup_finished");
192                 end_burst();
193                 return;
194         }
195
196
197         /* Ok, let's give this a try.  Can we create the new user? */
198
199         Buf = NewStrBuf();
200         serv_printf("OIDC %s", bstr("name"));
201         StrBuf_ServGetln(Buf);
202         if (GetServerStatus(Buf, NULL) == 2) {
203                 StrBuf *gpass;
204
205                 gpass = NewStrBuf();
206                 serv_puts("SETP GENERATE_RANDOM_PASSWORD");
207                 StrBuf_ServGetln(gpass);
208                 StrBufCutLeft(gpass, 4);
209                 become_logged_in(sbstr("name"), gpass, Buf);
210                 FreeStrBuf(&gpass);
211         }
212         FreeStrBuf(&Buf);
213
214         /* Did we manage to log in?  If so, continue with the normal flow... */
215         if (WC->logged_in) {
216                 if (WC->logged_in) {
217                         begin_burst();
218                         output_headers(1, 0, 0, 0, 1, 0);
219                         do_template("authpopup_finished");
220                         end_burst();
221                 }
222         }
223         else {
224                 /* Still no good!  Go back to teh dialog to select a username */
225                 const StrBuf *Buf;
226                 putbstr("__claimed_id", NewStrBufDup(sbstr("openid_url")));
227                 Buf = sbstr("name");
228                 if (StrLength(Buf) > 0)
229                         putbstr("__username", NewStrBufDup(Buf));
230                 begin_burst();
231                 output_headers(1, 0, 0, 0, 1, 0);
232                 wc_printf("<html><body>");
233                 do_template("openid_manual_create");
234                 wc_printf("</body></html>");
235                 end_burst();
236         }
237
238 }
239
240
241 /* 
242  * Perform authentication using OpenID
243  * assemble the checkid_setup request and then redirect to the user's identity provider
244  */
245 void do_openid_login(void) {
246         char buf[4096];
247
248         snprintf(buf, sizeof buf,
249                  "OIDS %s|%s/finalize_openid_login|%s", bstr("openid_url"), ChrPtr(site_prefix), ChrPtr(site_prefix)
250             );
251
252         serv_puts(buf);
253         serv_getln(buf, sizeof buf);
254         if (buf[0] == '2') {
255                 syslog(LOG_DEBUG, "OpenID server contacted; redirecting to %s\n", &buf[4]);
256                 http_redirect(&buf[4]);
257                 return;
258         }
259
260         begin_burst();
261         output_headers(1, 0, 0, 0, 1, 0);
262         wc_printf("<html><body>");
263         escputs(&buf[4]);
264         wc_printf("</body></html>");
265         end_burst();
266 }
267
268
269 /* 
270  * Complete the authentication using OpenID
271  * This function handles the positive or negative assertion from the user's Identity Provider
272  */
273 void finalize_openid_login(void) {
274         StrBuf *Buf;
275         wcsession *WCC = WC;
276         int linecount = 0;
277         StrBuf *result = NULL;
278         StrBuf *username = NULL;
279         StrBuf *password = NULL;
280         StrBuf *logged_in_response = NULL;
281         StrBuf *claimed_id = NULL;
282
283         if (havebstr("openid.mode")) {
284                 if (!strcasecmp(bstr("openid.mode"), "id_res")) {
285                         Buf = NewStrBuf();
286                         serv_puts("OIDF");
287                         StrBuf_ServGetln(Buf);
288                         if (GetServerStatus(Buf, NULL) == 8) {
289                                 urlcontent *u;
290                                 void *U;
291                                 long HKLen;
292                                 const char *HKey;
293                                 HashPos *Cursor;
294                                 int len;
295
296                                 Cursor = GetNewHashPos(WCC->Hdr->urlstrings, 0);
297                                 while (GetNextHashPos(WCC->Hdr->urlstrings, Cursor, &HKLen, &HKey, &U)) {
298                                         u = (urlcontent *) U;
299                                         if (!strncasecmp(u->url_key, "openid.", 7)) {
300                                                 serv_printf("%s|%s", &u->url_key[7], ChrPtr(u->url_data));
301                                         }
302                                 }
303
304                                 serv_puts("000");
305
306                                 linecount = 0;
307                                 while (len = StrBuf_ServGetln(Buf), ((len >= 0) && ((len != 3) || strcmp(ChrPtr(Buf), "000")))) {
308                                         if (linecount == 0)
309                                                 result = NewStrBufDup(Buf);
310                                         if (!strcasecmp(ChrPtr(result), "authenticate")) {
311                                                 if (linecount == 1) {
312                                                         username = NewStrBufDup(Buf);
313                                                 }
314                                                 else if (linecount == 2) {
315                                                         password = NewStrBufDup(Buf);
316                                                 }
317                                                 else if (linecount == 3) {
318                                                         logged_in_response = NewStrBufDup(Buf);
319                                                 }
320                                         }
321                                         else if (!strcasecmp(ChrPtr(result), "verify_only")) {
322                                                 if (linecount == 1) {
323                                                         claimed_id = NewStrBufDup(Buf);
324                                                 }
325                                                 if (linecount == 2) {
326                                                         username = NewStrBufDup(Buf);
327                                                 }
328                                         }
329                                         ++linecount;
330                                 }
331                         }
332                         FreeStrBuf(&Buf);
333                 }
334         }
335
336         /*
337          * Is this an attempt to associate a new OpenID with an account that is already logged in?
338          */
339         if ((WCC->logged_in) && (havebstr("attach_existing"))) {
340                 display_openids();
341         }
342
343         /* If this operation logged us in, either by connecting with an existing account or by
344          * auto-creating one using Simple Registration Extension, we're already on our way.
345          */
346         else if (!strcasecmp(ChrPtr(result), "authenticate")) {
347                 become_logged_in(username, password, logged_in_response);
348
349                 /* Did we manage to log in?  If so, continue with the normal flow... */
350                 if (WC->logged_in) {
351                         begin_burst();
352                         output_headers(1, 0, 0, 0, 1, 0);
353                         do_template("authpopup_finished");
354                         end_burst();
355                 }
356                 else {
357                         begin_burst();
358                         output_headers(1, 0, 0, 0, 1, 0);
359                         wc_printf("<html><body>");
360                         wc_printf(_("An error has occurred."));
361                         wc_printf("</body></html>");
362                         end_burst();
363                 }
364         }
365
366         /* The specified OpenID was verified but the desired user name was either not specified via SRE
367          * or conflicts with an existing user.  Either way the user will need to specify a new name.
368          */
369         else if (!strcasecmp(ChrPtr(result), "verify_only")) {
370                 putbstr("__claimed_id", claimed_id);
371                 claimed_id = NULL;
372                 if (StrLength(username) > 0) {
373                         putbstr("__username", username);
374                         username = NULL;
375                 }
376                 begin_burst();
377                 output_headers(1, 0, 0, 0, 1, 0);
378                 wc_printf("<html><body>");
379                 do_template("openid_manual_create");
380                 wc_printf("</body></html>");
381                 end_burst();
382         }
383
384         /* Something went VERY wrong if we get to this point */
385         else {
386                 syslog(LOG_DEBUG, "finalize_openid_login() failed to do anything.  This is a code problem.\n");
387                 begin_burst();
388                 output_headers(1, 0, 0, 0, 1, 0);
389                 wc_printf("<html><body>");
390                 wc_printf(_("An error has occurred."));
391                 wc_printf("</body></html>");
392                 end_burst();
393         }
394
395         FreeStrBuf(&result);
396         FreeStrBuf(&username);
397         FreeStrBuf(&password);
398         FreeStrBuf(&claimed_id);
399         FreeStrBuf(&logged_in_response);
400 }
401
402
403 /*
404  * Display a welcome screen to the user.
405  */
406 void do_welcome(void) {
407         StrBuf *Buf;
408         /*
409          * Go to the user's preferred start page
410          */
411         if (!get_preference("startpage", &Buf)) {
412                 Buf = NewStrBuf();
413                 StrBufPrintf(Buf, "dotskip?room=_BASEROOM_");
414                 set_preference("startpage", Buf, 1);
415         }
416         if (ChrPtr(Buf)[0] == '/') {
417                 StrBufCutLeft(Buf, 1);
418         }
419         if (StrLength(Buf) == 0) {
420                 StrBufAppendBufPlain(Buf, "dotgoto?room=_BASEROOM_", -1, 0);
421         }
422         syslog(LOG_DEBUG, "Redirecting to user's start page: %s\n", ChrPtr(Buf));
423         http_redirect(ChrPtr(Buf));
424 }
425
426
427 /*
428  * Disconnect from the Citadel server, and end this WebCit session
429  */
430 void end_webcit_session(void) {
431         serv_puts("QUIT");
432         WC->killthis = 1;
433         /* close() of citadel socket will be done by do_housekeeping() */
434 }
435
436
437 /* 
438  * Log out the session with the Citadel server
439  */
440 void do_logout(void) {
441         wcsession *WCC = WC;
442         char buf[SIZ];
443
444         FlushStrBuf(WCC->wc_username);
445         FlushStrBuf(WCC->wc_password);
446         FlushStrBuf(WCC->wc_fullname);
447         FlushRoomlist();
448
449         serv_puts("LOUT");
450         serv_getln(buf, sizeof buf);
451         WCC->logged_in = 0;
452
453         FlushStrBuf(WCC->CurRoom.name);
454
455         /* Calling output_headers() this way causes the cookies to be un-set */
456         output_headers(1, 1, 0, 1, 0, 0);
457         do_template("logout");
458         if ((WCC->serv_info != NULL) && WCC->serv_info->serv_supports_guest) {
459                 display_default_landing_page();
460                 return;
461         }
462
463         wDumpContent(2);
464         end_webcit_session();
465 }
466
467
468 /* 
469  * Special page for monitoring scripts etc
470  */
471 void monitor(void) {
472         output_headers(0, 0, 0, 0, 0, 0);
473
474         hprintf("Content-type: text/plain\r\n" "Server: " PACKAGE_STRING "\r\n" "Connection: close\r\n");
475         begin_burst();
476
477         wc_printf("Connection to Citadel server in %s : %s\r\n", ctdl_dir, (WC->connected ? "SUCCESS" : "FAIL")
478             );
479
480         wDumpContent(0);
481 }
482
483
484 /*
485  * validate new users
486  */
487 void validate(void) {
488         char cmd[SIZ];
489         char user[SIZ];
490         char buf[SIZ];
491         int a;
492
493         output_headers(1, 1, 1, 0, 0, 0);
494
495         do_template("box_begin_1");
496         StrBufAppendBufPlain(WC->WBuf, _("Validate new users"), -1, 0);
497         do_template("box_begin_2");
498
499         /* If the user just submitted a validation, process it... */
500         safestrncpy(buf, bstr("user"), sizeof buf);
501         if (!IsEmptyStr(buf)) {
502                 if (havebstr("axlevel")) {
503                         serv_printf("VALI %s|%s", buf, bstr("axlevel"));
504                         serv_getln(buf, sizeof buf);
505                         if (buf[0] != '2') {
506                                 wc_printf("<b>%s</b><br>\n", &buf[4]);
507                         }
508                 }
509         }
510
511         /* Now see if any more users require validation. */
512         serv_puts("GNUR");
513         serv_getln(buf, sizeof buf);
514         if (buf[0] == '2') {
515                 wc_printf("<b>");
516                 wc_printf(_("No users require validation at this time."));
517                 wc_printf("</b><br>\n");
518                 wDumpContent(1);
519                 return;
520         }
521         if (buf[0] != '3') {
522                 wc_printf("<b>%s</b><br>\n", &buf[4]);
523                 wDumpContent(1);
524                 return;
525         }
526
527         wc_printf("<table class=\"auth_validate\"><tr><td>\n");
528         wc_printf("<div id=\"validate\">");
529
530         safestrncpy(user, &buf[4], sizeof user);
531         serv_printf("GREG %s", user);
532         serv_getln(cmd, sizeof cmd);
533         if (cmd[0] == '1') {
534                 a = 0;
535                 do {
536                         serv_getln(buf, sizeof buf);
537                         ++a;
538                         if (a == 1)
539                                 wc_printf("#%s<br><H1>%s</H1>", buf, &cmd[4]);
540                         if (a == 2) {
541                                 char *pch;
542                                 int haveChar = 0;
543                                 int haveNum = 0;
544                                 int haveOther = 0;
545                                 int haveLong = 0;
546                                 pch = buf;
547                                 while (!IsEmptyStr(pch)) {
548                                         if (isdigit(*pch))
549                                                 haveNum = 1;
550                                         else if (isalpha(*pch))
551                                                 haveChar = 1;
552                                         else
553                                                 haveOther = 1;
554                                         pch++;
555                                 }
556                                 if (pch - buf > 7)
557                                         haveLong = 1;
558                                 switch (haveLong + haveChar + haveNum + haveOther) {
559                                 case 0:
560                                         pch = _("very weak");
561                                         break;
562                                 case 1:
563                                         pch = _("weak");
564                                         break;
565                                 case 2:
566                                         pch = _("ok");
567                                         break;
568                                 case 3:
569                                 default:
570                                         pch = _("strong");
571                                 }
572
573                                 wc_printf("PW: %s<br>\n", pch);
574                         }
575                         if (a == 3)
576                                 wc_printf("%s<br>\n", buf);
577                         if (a == 4)
578                                 wc_printf("%s<br>\n", buf);
579                         if (a == 5)
580                                 wc_printf("%s, ", buf);
581                         if (a == 6)
582                                 wc_printf("%s ", buf);
583                         if (a == 7)
584                                 wc_printf("%s<br>\n", buf);
585                         if (a == 8)
586                                 wc_printf("%s<br>\n", buf);
587                         if (a == 9)
588                                 wc_printf(_("Current access level: %d (%s)\n"), atoi(buf), axdefs[atoi(buf)]);
589                 } while (strcmp(buf, "000"));
590         }
591         else {
592                 wc_printf("<H1>%s</H1>%s<br>\n", user, &cmd[4]);
593         }
594
595         wc_printf("<hr />");
596         wc_printf(_("Select access level for this user:"));
597         wc_printf("<br>\n");
598         for (a = 0; a <= 6; ++a) {
599                 wc_printf("<a href=\"validate?nonce=%d?user=", WC->nonce);
600                 urlescputs(user);
601                 wc_printf("&axlevel=%d\">%s</A>&nbsp;&nbsp;&nbsp;\n", a, axdefs[a]);
602         }
603         wc_printf("<br>\n");
604
605         wc_printf("</div>\n");
606         wc_printf("</td></tr></table>\n");
607         do_template("box_end");
608         wDumpContent(1);
609 }
610
611
612 /*
613  * Display form for registration.
614  *
615  * (Set during_login to 1 if this registration is being performed during
616  * new user login and will require chaining to the proper screen.)
617  */
618 void display_reg(int during_login) {
619         folder Room;
620         StrBuf *Buf;
621         message_summary *VCMsg = NULL;
622         wc_mime_attachment *VCAtt = NULL;
623         long vcard_msgnum;
624
625         Buf = NewStrBuf();
626         memset(&Room, 0, sizeof(folder));
627         if (goto_config_room(Buf, &Room) != 0) {
628                 syslog(LOG_WARNING, "display_reg() exiting because goto_config_room() failed\n");
629                 if (during_login) {
630                         pop_destination();
631                 }
632                 else {
633                         display_main_menu();
634                 }
635                 FreeStrBuf(&Buf);
636                 FlushFolder(&Room);
637                 return;
638         }
639         FlushFolder(&Room);
640
641         FreeStrBuf(&Buf);
642         vcard_msgnum = locate_user_vcard_in_this_room(&VCMsg, &VCAtt);
643         if (vcard_msgnum < 0L) {
644                 syslog(LOG_WARNING, "display_reg() exiting because locate_user_vcard_in_this_room() failed\n");
645                 if (during_login) {
646                         pop_destination();
647                 }
648                 else {
649                         display_main_menu();
650                 }
651                 return;
652         }
653
654         if (during_login) {
655                 do_edit_vcard(vcard_msgnum, "1", VCMsg, VCAtt, "pop", USERCONFIGROOM);
656         }
657         else {
658                 StrBuf *ReturnTo;
659                 ReturnTo = NewStrBufPlain(HKEY("display_main_menu?go="));
660                 StrBufAppendBuf(ReturnTo, WC->CurRoom.name, 0);
661                 do_edit_vcard(vcard_msgnum, "1", VCMsg, VCAtt, ChrPtr(ReturnTo), USERCONFIGROOM);
662                 FreeStrBuf(&ReturnTo);
663         }
664
665 }
666
667 /*
668  * change password
669  * if passwords match, propagate it to citserver.
670  */
671 void changepw(void) {
672         StrBuf *Line;
673         char newpass1[32], newpass2[32];
674
675         if (!havebstr("change_action")) {
676                 AppendImportantMessage(_("Cancelled.  Password was not changed."), -1);
677                 display_main_menu();
678                 return;
679         }
680
681         safestrncpy(newpass1, bstr("newpass1"), sizeof newpass1);
682         safestrncpy(newpass2, bstr("newpass2"), sizeof newpass2);
683
684         if (strcasecmp(newpass1, newpass2)) {
685                 AppendImportantMessage(_("They don't match.  Password was not changed."), -1);
686                 do_template("menu_change_pw");
687                 return;
688         }
689
690         if (IsEmptyStr(newpass1)) {
691                 AppendImportantMessage(_("Blank passwords are not allowed."), -1);
692                 do_template("menu_change_pw");
693                 return;
694         }
695
696         Line = NewStrBuf();
697         serv_printf("SETP %s", newpass1);
698         StrBuf_ServGetln(Line);
699         if (GetServerStatusMsg(Line, NULL, 1, 0) == 2) {
700                 if (WC->wc_password == NULL)
701                         WC->wc_password = NewStrBufPlain(ChrPtr(Line) + 4, StrLength(Line) - 4);
702                 else {
703                         FlushStrBuf(WC->wc_password);
704                         StrBufAppendBufPlain(WC->wc_password, ChrPtr(Line) + 4, StrLength(Line) - 4, 0);
705                 }
706                 display_main_menu();
707         }
708         else {
709                 do_template("menu_change_pw");
710         }
711         FreeStrBuf(&Line);
712 }
713
714
715 int ConditionalHaveAccessCreateRoom(StrBuf * Target, WCTemplputParams * TP) {
716         StrBuf *Buf;
717
718         Buf = NewStrBuf();
719         serv_puts("CRE8 0");
720         StrBuf_ServGetln(Buf);
721
722         if (GetServerStatus(Buf, NULL) == 2) {
723                 StrBufCutLeft(Buf, 4);
724                 AppendImportantMessage(SKEY(Buf));
725                 FreeStrBuf(&Buf);
726                 return 0;
727         }
728         FreeStrBuf(&Buf);
729         return 1;
730 }
731
732
733 int ConditionalAide(StrBuf * Target, WCTemplputParams * TP) {
734         wcsession *WCC = WC;
735         return (WCC != NULL) ? ((WCC->logged_in == 0) || (WC->is_aide == 0)) : 0;
736 }
737
738
739 int ConditionalIsLoggedIn(StrBuf * Target, WCTemplputParams * TP) {
740         wcsession *WCC = WC;
741         return (WCC != NULL) ? (WCC->logged_in == 0) : 0;
742
743 }
744
745
746 /* 
747  * toggle the session over to a different language
748  */
749 void switch_language(void) {
750         set_selected_language(bstr("lang"));
751         pop_destination();
752 }
753
754
755 void _display_reg(void) {
756         display_reg(0);
757 }
758
759
760 void Header_HandleAuth(StrBuf * Line, ParsedHttpHdrs * hdr) {
761         if (hdr->HR.got_auth == NO_AUTH) {      /* don't override cookie auth... */
762                 if (strncasecmp(ChrPtr(Line), "Basic", 5) == 0) {
763                         StrBufCutLeft(Line, 6);
764                         StrBufDecodeBase64(Line);
765                         hdr->HR.plainauth = Line;
766                         hdr->HR.got_auth = AUTH_BASIC;
767                 }
768                 else
769                         syslog(LOG_WARNING, "Authentication scheme not supported! [%s]\n", ChrPtr(Line));
770         }
771 }
772
773
774 void CheckAuthBasic(ParsedHttpHdrs * hdr) {
775
776 /*
777   todo: enable this if we can have other sessions than authenticated ones.
778         if (hdr->DontNeedAuth)
779                 return;
780 */
781         StrBufAppendBufPlain(hdr->HR.plainauth, HKEY(":"), 0);
782         StrBufAppendBuf(hdr->HR.plainauth, hdr->HR.user_agent, 0);
783 }
784
785
786 void GetAuthBasic(ParsedHttpHdrs * hdr) {
787         const char *Pos = NULL;
788         if (hdr->c_username == NULL)
789                 hdr->c_username = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER));
790         if (hdr->c_password == NULL)
791                 hdr->c_password = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS));
792         StrBufExtract_NextToken(hdr->c_username, hdr->HR.plainauth, &Pos, ':');
793         StrBufExtract_NextToken(hdr->c_password, hdr->HR.plainauth, &Pos, ':');
794 }
795
796
797 void Header_HandleCookie(StrBuf * Line, ParsedHttpHdrs * hdr) {
798         const char *pch;
799
800 /*
801   todo: enable this if we can have other sessions than authenticated ones.
802         if (hdr->DontNeedAuth)
803                 return;
804 */
805         pch = strstr(ChrPtr(Line), "webcit=");
806         if (pch == NULL) {
807                 return;
808         }
809
810         hdr->HR.RawCookie = Line;
811         StrBufCutLeft(hdr->HR.RawCookie, (pch - ChrPtr(hdr->HR.RawCookie)) + 7);
812         StrBufDecodeHex(hdr->HR.RawCookie);
813
814         cookie_to_stuff(Line, &hdr->HR.desired_session, hdr->c_username, hdr->c_password, hdr->c_roomname, hdr->c_language);
815         hdr->HR.got_auth = AUTH_COOKIE;
816 }
817
818
819 void HttpNewModule_AUTH(ParsedHttpHdrs * httpreq) {
820         httpreq->c_username = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER));
821         httpreq->c_password = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS));
822         httpreq->c_roomname = NewStrBuf();
823         httpreq->c_language = NewStrBuf();
824 }
825
826
827 void HttpDetachModule_AUTH(ParsedHttpHdrs * httpreq) {
828         FLUSHStrBuf(httpreq->c_username);
829         FLUSHStrBuf(httpreq->c_password);
830         FLUSHStrBuf(httpreq->c_roomname);
831         FLUSHStrBuf(httpreq->c_language);
832 }
833
834
835 void HttpDestroyModule_AUTH(ParsedHttpHdrs * httpreq) {
836         FreeStrBuf(&httpreq->c_username);
837         FreeStrBuf(&httpreq->c_password);
838         FreeStrBuf(&httpreq->c_roomname);
839         FreeStrBuf(&httpreq->c_language);
840 }
841
842
843 void InitModule_AUTH(void) {
844         initialize_axdefs();
845         RegisterHeaderHandler(HKEY("COOKIE"), Header_HandleCookie);
846         RegisterHeaderHandler(HKEY("AUTHORIZATION"), Header_HandleAuth);
847
848         /* no url pattern at all? Show login. */
849         WebcitAddUrlHandler(HKEY(""), "", 0, do_welcome, ANONYMOUS | COOKIEUNNEEDED);
850
851         WebcitAddUrlHandler(HKEY("do_welcome"), "", 0, do_welcome, ANONYMOUS | COOKIEUNNEEDED);
852         WebcitAddUrlHandler(HKEY("openid_login"), "", 0, do_openid_login, ANONYMOUS);
853         WebcitAddUrlHandler(HKEY("finalize_openid_login"), "", 0, finalize_openid_login, ANONYMOUS);
854         WebcitAddUrlHandler(HKEY("openid_manual_create"), "", 0, openid_manual_create, ANONYMOUS);
855         WebcitAddUrlHandler(HKEY("validate"), "", 0, validate, 0);
856         WebcitAddUrlHandler(HKEY("do_welcome"), "", 0, do_welcome, 0);
857         WebcitAddUrlHandler(HKEY("display_reg"), "", 0, _display_reg, 0);
858         WebcitAddUrlHandler(HKEY("changepw"), "", 0, changepw, 0);
859         WebcitAddUrlHandler(HKEY("termquit"), "", 0, do_logout, 0);
860         WebcitAddUrlHandler(HKEY("do_logout"), "", 0, do_logout, ANONYMOUS | COOKIEUNNEEDED | FORCE_SESSIONCLOSE);
861         WebcitAddUrlHandler(HKEY("monitor"), "", 0, monitor, ANONYMOUS | COOKIEUNNEEDED | FORCE_SESSIONCLOSE);
862         WebcitAddUrlHandler(HKEY("ajax_login_username_password"), "", 0, ajax_login_username_password, AJAX | ANONYMOUS);
863         WebcitAddUrlHandler(HKEY("ajax_login_newuser"), "", 0, ajax_login_newuser, AJAX | ANONYMOUS);
864         WebcitAddUrlHandler(HKEY("switch_language"), "", 0, switch_language, ANONYMOUS);
865         RegisterConditional("COND:AIDE", 2, ConditionalAide, CTX_NONE);
866         RegisterConditional("COND:LOGGEDIN", 2, ConditionalIsLoggedIn, CTX_NONE);
867         RegisterConditional("COND:MAY_CREATE_ROOM", 2, ConditionalHaveAccessCreateRoom, CTX_NONE);
868         return;
869 }
870
871
872 void SessionDestroyModule_AUTH(wcsession * sess) {
873         FreeStrBuf(&sess->wc_username);
874         FreeStrBuf(&sess->wc_fullname);
875         FreeStrBuf(&sess->wc_password);
876         FreeStrBuf(&sess->httpauth_pass);
877         FreeStrBuf(&sess->cs_inet_email);
878 }