]> andersk Git - moira.git/blame_incremental - clients/userreg/userreg.c
characters -> letters & numbers
[moira.git] / clients / userreg / userreg.c
... / ...
CommitLineData
1/*
2 * $Source$
3 * $Author$
4 * $Locker$
5 * $Header$
6 *
7 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
8 * For copying and distribution information, please see the file
9 * <mit-copyright.h>.
10 */
11
12#ifndef lint
13static char *rcsid_userreg_c = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include <curses.h>
18#include <signal.h>
19#include <sys/time.h>
20#include <setjmp.h>
21#include <ctype.h>
22#include <krb.h>
23#include <errno.h>
24#include "userreg.h"
25#include "ureg_err.h"
26
27#define EXIT -1
28
29
30struct user user, db_user;
31struct alias alias;
32char typed_mit_id[100];
33
34jmp_buf redo;
35int restart();
36
37extern int errno;
38int user_is_valid = 0;
39int user_has_login = 0;
40int already_registered = 0;
41extern char *disabled();
42
43fix_display(sig)
44{
45 signal(sig, SIG_IGN); /* let us clean up, please */
46 noraw();
47 echo();
48 endwin();
49 exit(1);
50}
51
52main(argc, argv)
53 int argc;
54 char **argv;
55{
56 register int ntimes;
57 register int reencrypt;
58 char line[100], *when, *msg;
59 int status;
60 char tmpfirst[100], tmplast[100], tmpmid[100];
61
62 status = ureg_init();
63 if (status) {
64 com_err(argv[0], status, "while trying to initialize");
65 exit(1);
66 }
67
68 if (when = disabled(&msg)) {
69 printf("We're sorry, the registration service is unavailable right now\n");
70 if (msg)
71 printf("because %s\n", msg);
72 printf("You should be able to register after %s", when);
73 printf("\nPress ENTER or RETURN to continue ");
74 fflush(stdout);
75 getchar();
76 exit(0);
77 }
78
79 setup_display();
80
81 signal(SIGINT, fix_display);
82 signal(SIGQUIT, fix_display);
83 signal(SIGHUP, fix_display);
84
85 do {
86
87 setjmp(redo);
88 reset();
89 ntimes = 0;
90
91 display_text(WELCOME);
92
93 gfirst();
94 gmi();
95 glast();
96 strcpy(tmpfirst, user.u_first);
97 strcpy(tmplast, user.u_last);
98 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
99 redisp();
100
101 gmitid();
102
103 while (dolook()) {
104 ntimes++;
105 if (ntimes > 3) {
106 display_text_line(0);
107 display_text_line("Sorry, you still cannot be found in the database.");
108 display_text_line(" ");
109 display_text_line("Please call the account administrator at x3-1325 for help.");
110 wait_for_user();
111 break;
112 }
113 display_text_line(0); /* clear the window */
114 display_text_line("You could not be found in the database.");
115 display_text_line("Do you want to change some input (for example, the spelling");
116 display_text_line("of part of your name) and try again?");
117 if (askyn("Do you want to try again ? ") == YES) {
118 reencrypt = 0;
119 display_text_line(0);
120 sprintf(line,
121 "You entered your first name as \"%s\"", user.u_first);
122 display_text_line(line);
123 if (askyn("Do you want to change it? ") == YES) {
124 gfirst();
125 strcpy(tmpfirst, user.u_first);
126 strcpy(tmplast, user.u_last);
127 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
128 redisp();
129 reencrypt = 1;
130 }
131 display_text_line(0);
132 sprintf(line,
133 "You entered your middle initial as \"%s\"", user.u_mid_init);
134 display_text_line(line);
135 if (askyn("Do you want to change it? ") == YES)
136 gmi();
137 display_text_line(0);
138 sprintf(line,
139 "You entered your family name as \"%s\"", user.u_last);
140 display_text_line(line);
141 if (askyn("Do you want to change it? ") == YES) {
142 glast();
143 strcpy(tmpfirst, user.u_first);
144 strcpy(tmplast, user.u_last);
145 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
146 redisp();
147 reencrypt = 1;
148 }
149 display_text_line(0);
150 sprintf(line,
151 "You entered your MIT id number as \"%s\"", typed_mit_id);
152 display_text_line(line);
153 if (askyn("Do you want to change it? ") == YES) {
154 gmitid();
155 reencrypt = 0;
156 }
157 if (reencrypt) {
158 encrypt_mitid();
159 }
160 } else
161 break;
162 }
163 if (!user_is_valid || already_registered) {
164 qexit();
165 continue;
166 }
167 redisp();
168 if (!user_has_login) {
169 if (negotiate_login() == -1) {
170 qexit();
171 continue;
172 }
173 }
174 if (negotiate_passwd() == -1) {
175 qexit();
176 continue;
177 }
178 sleep(1);
179 display_text_line(0);
180 display_text_line("You are now registered to get an Athena account.");
181 sprintf(line, "Please remember your username of \"%s\" and the password",
182 user.u_login);
183 display_text_line(line);
184 display_text_line("you typed in earlier.");
185 display_text_line("");
186 display_text_line("Your account should be created by tomorrow\n");
187
188 display_text_line("");
189 display_text_line("You are now finished. Thank you!");
190 wait_for_user();
191 qexit();
192 } while (getuid() == 0);/* Loop forever if we're root */
193 restore_display();
194 exit(0);
195}
196
197reset()
198{
199 reset_display();
200 bzero(&user, sizeof(user));
201 user_is_valid = 0;
202 already_registered = 0;
203 redisp();
204}
205
206dolook()
207{
208 /* do the database lookup */
209
210 char line[100];
211 register int result;
212 if (user_is_valid) {
213 /* !! */
214 return (0);
215 }
216 display_text_line(0);
217 display_text_line("Looking you up in the database.... This may take from 30 seconds to 10");
218 display_text_line("minutes, depending on how busy the system is at the moment.");
219
220 timer_off();
221 result = verify_user(user.u_first, user.u_last,
222 typed_mit_id, user.u_mit_id, db_user.u_login);
223 wfeep();
224 display_text_line(0);
225 timer_on();
226 switch(result) {
227 case 0:
228 display_text_line("You have been located in the user registration database.");
229 user_is_valid = 1;
230 user_has_login = 0;
231 sleep(1);
232 return 0;
233 case UREG_NO_PASSWD_YET:
234 user_is_valid = 1;
235 user_has_login = 1;
236 display_text_line ("You have chosen a login name, but you have not yet chosen a password.");
237 sprintf(line, "Remember: the username you chose was '%s'",
238 db_user.u_login);
239 strcpy(user.u_login, db_user.u_login);
240 display_text_line(line);
241 redisp();
242 sleep(5);
243 return (0);
244
245 case UREG_ALREADY_REGISTERED:
246 already_registered = 1;
247 /*
248 * we have to reset this so we dont ask for a
249 * new username
250 */
251 user_is_valid = 0;
252 display_text_line("You are already registered. An account for you probably already exists");
253 display_text_line("(if not, it will appear within 12 hours).");
254 display_text_line("");
255 display_text_line("Refer to the documents 'Essential Athena' and 'Essential Unix'");
256 strcpy(user.u_login, db_user.u_login);
257 sprintf(line, "for help logging in. Remember, the username you chose was '%s'",
258 db_user.u_login);
259 display_text_line(line);
260 redisp();
261 wait_for_user();
262 return (0);
263 case UREG_DELETED:
264 display_text(DELETED_ACCT);
265 wait_for_user();
266 restore_display();
267 exit(0);
268 case UREG_NOT_ALLOWED:
269 display_text(NOT_ALLOWED);
270 wait_for_user();
271 restore_display();
272 exit(0);
273 case UREG_KRB_TAKEN:
274 display_text(IMPROPER_LOGIN);
275 wait_for_user();
276 return(0);
277 case UREG_USER_NOT_FOUND:
278 return (1);
279
280 case ECONNREFUSED:
281 case ETIMEDOUT:
282 case UREG_MISC_ERROR:
283 display_text(NETWORK_DOWN);
284 wait_for_user();
285 return (0);
286
287 default:
288 display_text_line("An unexpected error occurred while trying to access the database");
289 display_text_line(error_message(result));
290 redisp();
291 wait_for_user();
292 return(1);
293 }
294}
295
296negotiate_login()
297{
298 register int result;
299 char line[100];
300 char old_login[LOGIN_SIZE];
301 char realm[REALM_SZ];
302 int i;
303 char *cp;
304
305 display_text(USERNAME_BLURB);
306 cp = user.u_login;
307 if (isalpha(user.u_first[0]))
308 *cp++ = user.u_first[0];
309 if (isalpha(user.u_mid_init[0]))
310 *cp++ = user.u_mid_init[0];
311
312 for (i = 0; user.u_last[i] && cp - user.u_login < 8; i++) {
313 if (isalpha(user.u_last[i])) *cp++ = user.u_last[i];
314 }
315
316 for (i=0; user.u_login[i]; i++)
317 if (isupper(user.u_login[i]))
318 user.u_login[i]=tolower(user.u_login[i]);
319
320 strcpy(old_login, user.u_login);
321 sprintf(line, "We suggest the username '%s'.", user.u_login);
322 display_text_line(line);
323 display_text_line(
324 "If you are sure you would prefer another username, feel free to enter");
325 display_text_line(
326 "a different one, but keep in mind that it will remain with you for all the ");
327 display_text_line("time you are at MIT.");
328
329 while (1) {
330 glogin();
331
332 display_text_line(0);
333 display_text_line("Trying to assign that username... This may take a few minutes.");
334 timer_off();
335 /*
336 * Rather than bother SMS with a bunch of different
337 * usernames, all in use, we first try and see if this
338 * guy is known to Kerberos.
339 */
340 if ((result = krb_get_lrealm(realm, 1)) != KSUCCESS) {
341 display_text_line("System error; please try another workstation.");
342 continue;
343 }
344 result = krb_get_pw_in_tkt(user.u_login, "", realm,
345 "krbtgt", realm, 1, "");
346 timer_on();
347 if (result != KDC_PR_UNKNOWN) {
348 in_use:
349 strcpy(user.u_login, old_login);
350 redisp();
351 display_text_line("That username is already taken. Please try again with a different username");
352 continue;
353 }
354
355 /*
356 * If he isn't, let's try through SMS.
357 */
358 timer_off();
359 result = grab_login(user.u_first, user.u_last,
360 typed_mit_id, user.u_mit_id,
361 user.u_login);
362 wfeep();
363 timer_on();
364 if (result != 0) {
365 char buf[BUFSIZ];
366
367 if (result == UREG_LOGIN_USED) goto in_use;
368 display_text(NETWORK_DOWN);
369 display_text_line(" ");
370 sprintf(buf, "The specific error was: %s",
371 error_message(result));
372 display_text_line(buf);
373 wait_for_user();
374 return (qexit());
375 } else break;
376 }
377 /* at this point we have successfully negotiated a username */
378
379 sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
380 display_text_line(0);
381 display_text_line(line);
382 redisp();
383 sleep(3);
384 return 0;
385}
386negotiate_passwd()
387{
388 display_text_line(0);
389 display_text(PASSWORD_BLURB);
390
391 gpass();
392 display_text_line("Storing password in the database... This may take a few minutes.");
393 if (do_replace()) {
394 return (-1);
395 }
396 display_text_line("done.");
397 return(0);
398}
399
400gfirst()
401{
402 /* input the first name */
403 char buf[FIRST_NAME_SIZE+2];
404
405 signal(SIGALRM, restart);
406 input("Enter first Name:", buf, FIRST_NAME_SIZE+1,
407 FIRSTNAME_TIMEOUT, TRUE);
408 strncpy(user.u_first, buf, FIRST_NAME_SIZE);
409 user.u_first[FIRST_NAME_SIZE - 1] = '\0';
410 canon_name(user.u_first);
411 redisp();
412}
413
414glast()
415{
416 /* input the last name */
417 char buf[LAST_NAME_SIZE+2];
418
419 signal(SIGALRM, restart);
420 input("Enter family Name:", buf, LAST_NAME_SIZE+1,
421 LASTNAME_TIMEOUT, FALSE);
422 strncpy(user.u_last, buf, LAST_NAME_SIZE);
423 user.u_last[LAST_NAME_SIZE - 1] = '\0';
424 canon_name(user.u_last);
425 redisp();
426}
427
428gpass()
429{
430 /* input password */
431 char new_password[PASSWORD_SIZE];
432 char new_password_again[PASSWORD_SIZE];
433
434do_input:
435 signal(SIGALRM, restart);
436 input_no_echo("Enter password:", new_password,
437 PASSWORD_SIZE, NEW_PASSWORD_TIMEOUT);
438 if (strlen(new_password) < 4) {
439 display_text_line("Please use a password of at least 4 characters.");
440 goto do_input;
441 }
442 signal(SIGALRM, restart);
443 input_no_echo("Enter password again:", new_password_again,
444 PASSWORD_SIZE, REENTER_PASSWORD_TIMEOUT);
445 if (strcmp(new_password, new_password_again)) {
446 display_text_line("Sorry, the two passwords you just typed in don't match.");
447 display_text_line("Please try again.");
448 goto do_input;
449 }
450
451 strcpy(user.u_password, new_password);
452 redisp();
453}
454
455glogin()
456{
457 /* get login name */
458 register int i;
459 char buf[LOGIN_SIZE+2];
460 register char *nbuf = buf;
461
462input_login:
463 i = 0;
464 user.u_login[0] = '\0';
465 nbuf = &buf[0];
466 signal(SIGALRM, restart);
467 input("Enter username:", buf, LOGIN_SIZE+1, USERNAME_TIMEOUT, FALSE);
468 if (!islower(*nbuf) && !isdigit(*nbuf)) {
469 display_text_line("Your username must start with a letter or number.");
470 goto input_login;
471 }
472 while (*nbuf != '\0') {
473 if (!islower(*nbuf) && !isdigit(*nbuf)
474 && (*nbuf != '_') && (*nbuf != '.')) {
475 display_text_line("Your username must be all lowercase alphabetic characters.");
476 goto input_login;
477 }
478 user.u_login[i] = *nbuf++;
479 i++;
480 if (i > LOGIN_SIZE - 1) {
481 display_text_line("Your username must be no more than 8 characters long.");
482 goto input_login;
483 }
484 }
485 if (i != 0) {
486 user.u_login[i] = '\0';
487 }
488 if (strlen(user.u_login) < 3) {
489 display_text_line("Your username must be 3 or more characters long.\n");
490 goto input_login;
491 }
492 redisp();
493}
494
495gmitid()
496{
497 /* get mid id */
498 register int i;
499 char buf[15];
500 register char *nbuf = buf;
501
502input_mit_id:
503 signal(SIGALRM, restart);
504 input("Enter MIT Id:", buf, 14, MITID_TIMEOUT, FALSE);
505 i = 0;
506 nbuf = &buf[0];
507 while (*nbuf != '\0') {
508 if (*nbuf == ' ' || *nbuf == '-') {
509 nbuf++;
510 continue;
511 }
512 if (!isdigit(*nbuf)) {
513 i = 0;
514 break;
515 }
516 typed_mit_id[i] = *nbuf;
517 nbuf++;
518 i++;
519 }
520 if (i != 9) {
521 display_text_line(
522 "Your MIT id must be a nine-digit number. Please try again.");
523 goto input_mit_id;
524 }
525 typed_mit_id[9] = '\0';
526 redisp();
527 encrypt_mitid();
528}
529
530encrypt_mitid()
531{
532 char salt[3];
533
534 make_salt(salt, user.u_first, user.u_last);
535 strcpy(user.u_mit_id, crypt(&typed_mit_id[2], salt));
536}
537
538
539#define _tolower(c) ((c)|0x60)
540
541make_salt(salt, first, last)
542 char *salt, *first, *last;
543{
544 salt[0] = _tolower(last[0]);
545 salt[1] = _tolower(first[0]);
546}
547
548
549gmi()
550{
551 /* get middle initial */
552 char buf[MID_INIT_SIZE+2];
553
554 signal(SIGALRM, restart);
555 input("Enter Middle Initial:", buf, MID_INIT_SIZE+1, MI_TIMEOUT, TRUE);
556 strncpy(user.u_mid_init, buf, MID_INIT_SIZE);
557 user.u_mid_init[MID_INIT_SIZE - 1] = '\0';
558 canon_name(user.u_mid_init);
559 redisp();
560}
561
562qexit()
563{
564 /* exit quickly, not saving anything in the database */
565 bzero(&user, sizeof(user));
566 typed_mit_id[0] = '\0';
567 user_is_valid = 0;
568 already_registered = 0;
569 sleep(2); /* give the user a chance to see the screen */
570 display_text_line(0);
571 return (EXIT);
572}
573
574
575do_replace()
576{
577 int status;
578
579 /*
580 * replaces a user in the database. If there is an error, it informs
581 * the user and calls qexit(); It returns only if is is successful
582 */
583 timer_off();
584 status = set_password(user.u_first, user.u_last, typed_mit_id,
585 user.u_mit_id, user.u_password);
586 wfeep();
587 timer_on();
588 if (status) {
589 display_text (NETWORK_DOWN);
590 return (-1);
591 } else return 0;
592}
593
594#define _toupper(c) ((c) & ~0x20)
595
596lenient_strcmp(string1, string2)
597 register char *string1, *string2;
598{
599 /*
600 * a primitive case insensitive string comparison. It returns only 0
601 * if the strings are equal (ignoring case) and 1 if they are
602 * different. Also ignores spaces.
603 */
604
605 while (1) {
606 if (*string1 == '\0' && *string2 == '\0') {
607 return (0);
608 }
609 if (*string1 == ' ' || *string1 == '.' || *string1 == '-' || *string1 == '\'') {
610 string1++;
611 continue;
612 }
613 if (*string2 == ' ' || *string2 == '.' || *string2 == '-' || *string2 == '\'') {
614 string2++;
615 continue;
616 }
617 if (_toupper(*string1) != _toupper(*string2)) {
618 return (1);
619 }
620 string1++;
621 string2++;
622 }
623}
624
625/*
626 * Input timeout handler. Loop back to asking for the first name.
627 */
628
629restart()
630/* Go to asking for first name. */
631{
632 qexit();
633 longjmp(redo);
634}
635
636canon_name(cp)
637 register char *cp;
638{
639 register char *p2 = cp;
640
641 /* Trim whitespace off both ends. */
642 for (; *p2 && isspace(*p2); p2++) ;
643 if (*p2) {
644 strcpy(cp, p2);
645 p2 = cp + strlen(cp);
646 --p2;
647 while (p2 >= cp && isspace(*p2)) *(--p2) = '\0';
648 }
649 /* Make it capitalized */
650 for (p2=cp; *p2; p2++) {
651 if (isupper(*p2)) *p2 = tolower(*p2);
652 }
653 if (islower(*cp)) *cp=toupper(*cp);
654}
This page took 0.040535 seconds and 5 git commands to generate.