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