]> andersk Git - moira.git/blob - clients/userreg/userreg.c
have program exit after timeout at first name prompt
[moira.git] / clients / userreg / userreg.c
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
13 static 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
30 struct user     user, db_user;
31 struct alias    alias;
32 char            typed_mit_id[100];
33
34 jmp_buf         redo;
35 int             restart();
36
37 extern int      errno;
38 int             user_is_valid = 0;
39 int             user_has_login = 0;
40 int             already_registered = 0;
41 extern char *disabled();
42
43 fix_display(sig)
44 {
45         signal(sig, SIG_IGN);   /* let us clean up, please */
46         noraw();
47         echo();
48         endwin();
49         exit(1);
50 }
51
52 main(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
197 reset()
198 {
199         reset_display();
200         bzero(&user, sizeof(user));
201         user_is_valid = 0;
202         already_registered = 0;
203         redisp();
204 }
205
206 dolook()
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         case UREG_ENROLLED:
229                 display_text_line("You have been located in the user registration database.");
230                 user_is_valid = 1;
231                 user_has_login = 0;
232                 sleep(1);
233                 return 0;
234         case UREG_NO_PASSWD_YET:
235                 user_is_valid = 1;
236                 user_has_login = 1;
237                 display_text_line ("You have chosen a login name, but you have not yet chosen a password.");
238                 sprintf(line, "Remember: the username you chose was '%s'",
239                         db_user.u_login);
240                 strcpy(user.u_login, db_user.u_login);
241                 display_text_line(line);
242                 redisp();
243                 sleep(5);
244                 return (0);
245                 
246         case UREG_ALREADY_REGISTERED:
247                 already_registered = 1;
248                 /*
249                  * we have to reset this so we dont ask for a
250                  * new username 
251                  */     
252                 user_is_valid = 0;
253                 display_text_line("You are already registered.  An account for you probably already exists");
254                 display_text_line("(if not, it will appear within 12 hours).");
255                 display_text_line("");
256                 display_text_line("Refer to the document 'Getting Started on Athena' for help logging in.");
257                 strcpy(user.u_login, db_user.u_login);
258                 sprintf(line, "Remember, the username you chose was '%s'",
259                         db_user.u_login);
260                 display_text_line(line);
261                 redisp();
262                 wait_for_user();
263                 return (0);
264         case UREG_DELETED:
265                 display_text(DELETED_ACCT);
266                 wait_for_user();
267                 restore_display();
268                 exit(0);
269         case UREG_NOT_ALLOWED:
270         case UREG_ENROLL_NOT_ALLOWED:
271                 display_text(NOT_ALLOWED);
272                 wait_for_user();
273                 restore_display();
274                 exit(0);
275         case UREG_KRB_TAKEN:
276                 display_text(IMPROPER_LOGIN);
277                 wait_for_user();
278                 return(0);
279         case UREG_USER_NOT_FOUND:
280                 return (1);
281
282         case ECONNREFUSED:
283         case ETIMEDOUT:
284         case UREG_MISC_ERROR:
285                 display_text(NETWORK_DOWN);
286                 wait_for_user();
287                 return (0);
288                 
289         default:
290                 display_text_line("An unexpected error occurred while trying to access the database");
291                 display_text_line(error_message(result));
292                 redisp();
293                 wait_for_user();
294                 return(1);
295         }
296 }
297
298 negotiate_login()
299 {
300         register int    result;
301         char            line[100];
302         char            old_login[LOGIN_SIZE+2];
303         char            realm[REALM_SZ];
304         int             i;
305         char *cp;
306         
307         display_text(USERNAME_BLURB);
308         cp = user.u_login;
309         if (isalpha(user.u_first[0]))
310                 *cp++ = user.u_first[0];
311         if (isalpha(user.u_mid_init[0]))
312                 *cp++ = user.u_mid_init[0];
313         
314         for (i = 0; user.u_last[i] && cp - user.u_login < 8; i++) {
315                 if (isalpha(user.u_last[i])) *cp++ = user.u_last[i];
316         }
317
318         for (i=0; user.u_login[i]; i++)
319                 if (isupper(user.u_login[i]))
320                         user.u_login[i]=tolower(user.u_login[i]);
321         
322         strcpy(old_login, user.u_login);
323         sprintf(line, "We suggest the username '%s'.", user.u_login);
324         display_text_line(line);
325         display_text_line(
326                           "If you are sure you would prefer another username, feel free to enter");
327         display_text_line(
328                           "a different one.  Keep in mind that it will remain with you for all the ");
329         display_text_line("time you are at MIT.");
330
331         while (1) {
332                 glogin();
333
334                 display_text_line(0);
335                 display_text_line("Trying to assign that username...  This may take a few minutes.");
336                 timer_off();
337                 /*
338                  * Rather than bother SMS with a bunch of different
339                  * usernames, all in use, we first try and see if this
340                  * guy is known to Kerberos.
341                  */
342                 if ((result = krb_get_lrealm(realm, 1)) != KSUCCESS) {
343                     display_text_line("System error; please try another workstation.");
344                     continue;
345                 }
346                 result = krb_get_pw_in_tkt(user.u_login, "", realm, 
347                                            "krbtgt", realm, 1, "");
348                 timer_on();
349                 if (result != KDC_PR_UNKNOWN) {
350                 in_use:
351                         strcpy(user.u_login, old_login);
352                         redisp();
353                         display_text_line("That username is already taken.  Please try again with a different username");
354                         continue;
355                 }
356
357                 /*
358                  * If he isn't, let's try through SMS.
359                  */
360                 timer_off();
361                 result = grab_login(user.u_first, user.u_last,
362                                     typed_mit_id, user.u_mit_id,
363                                     user.u_login);
364                 wfeep();
365                 timer_on();
366                 if (result != 0) {
367                         char buf[BUFSIZ];
368
369                         if (result == UREG_LOGIN_USED) goto in_use;
370                         display_text(NETWORK_DOWN);
371                         display_text_line(" ");
372                         sprintf(buf, "The specific error was: %s",
373                                 error_message(result));
374                         display_text_line(buf);
375                         wait_for_user();
376                         return (qexit());
377                 } else break;
378         }
379         /* at this point we have successfully negotiated a username */
380
381         sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
382         display_text_line(0);
383         display_text_line(line);
384         redisp();
385         sleep(3);
386         return 0;
387 }
388 negotiate_passwd()
389 {
390         display_text_line(0);
391         display_text(PASSWORD_BLURB);
392
393         gpass();
394         display_text_line("Storing password in the database...  This may take a few minutes.");
395         if (do_replace()) {
396                 return (-1);
397         }
398         display_text_line("done.");
399         return(0);
400 }
401
402 gfirst()
403 {
404         /* input the first name */
405         char            buf[FIRST_NAME_SIZE+2];
406
407         signal(SIGALRM, fix_display);
408         input("Enter first Name:", buf, FIRST_NAME_SIZE+1,
409               FIRSTNAME_TIMEOUT, TRUE);
410         strncpy(user.u_first, buf, FIRST_NAME_SIZE);
411         user.u_first[FIRST_NAME_SIZE - 1] = '\0';
412         canon_name(user.u_first);
413         redisp();
414 }
415
416 glast()
417 {
418         /* input the last name */
419         char            buf[LAST_NAME_SIZE+2];
420
421         signal(SIGALRM, restart);
422         input("Enter family Name:", buf, LAST_NAME_SIZE+1,
423               LASTNAME_TIMEOUT, FALSE);
424         strncpy(user.u_last, buf, LAST_NAME_SIZE);
425         user.u_last[LAST_NAME_SIZE - 1] = '\0';
426         canon_name(user.u_last);
427         redisp();
428 }
429
430 gpass()
431 {
432         /* input password */
433         char            new_password[PASSWORD_SIZE+1];
434         char            new_password_again[PASSWORD_SIZE+1];
435
436 do_input:
437         signal(SIGALRM, restart);
438         input_no_echo("Enter password:", new_password,
439                       PASSWORD_SIZE, NEW_PASSWORD_TIMEOUT);
440         if (strlen(new_password) < 4) {
441                 display_text_line("Please use a password of at least 4 characters.");
442                 goto do_input;
443         }
444         wfeep();
445         signal(SIGALRM, restart);
446         input_no_echo("Enter your password again:", new_password_again,
447                       PASSWORD_SIZE, REENTER_PASSWORD_TIMEOUT);
448         if (strcmp(new_password, new_password_again)) {
449                 display_text_line("Sorry, the two passwords you just typed in don't match.");
450                 display_text_line("Please try again.");
451                 goto do_input;
452         }
453
454         strcpy(user.u_password, new_password);
455         redisp();
456 }
457
458 glogin()
459 {
460         /* get login name */
461         register int    i;
462         char            buf[LOGIN_SIZE+2];
463         register char  *nbuf = buf;
464
465 input_login:
466         i = 0;
467         user.u_login[0] = '\0';
468         nbuf = &buf[0];
469         signal(SIGALRM, restart);
470         input("Enter username:", buf, LOGIN_SIZE, USERNAME_TIMEOUT, FALSE);
471         if (!islower(*nbuf) && !isdigit(*nbuf)) {
472             user.u_login[0] = 0;
473             display_text_line("Your username must start with a lower case letter or number.");
474             goto input_login;
475         }
476         while (*nbuf != '\0') {
477                 if (!islower(*nbuf) && !isdigit(*nbuf)
478                     && (*nbuf != '_')) {
479                         user.u_login[0] = 0;
480                         display_text_line("Your username must be all lowercase letters or numbers.");
481                         goto input_login;
482                 }
483                 user.u_login[i] = *nbuf++;
484                 i++;
485                 if (i > LOGIN_SIZE) {
486                         user.u_login[0] = 0;
487                         display_text_line("Your username must be no more than 8 characters long.");
488                         goto input_login;
489                 }
490         }
491         if (i != 0) {
492                 user.u_login[i] = '\0';
493         }
494         if (strlen(user.u_login) < 3) {
495                 user.u_login[0] = 0;
496                 display_text_line("Your username must be 3 or more characters long.\n");
497                 goto input_login;
498         }
499         redisp();
500 }
501
502 gmitid()
503 {
504         /* get mid id */
505         register int    i;
506         char            buf[15];
507         register char  *nbuf = buf;
508
509 input_mit_id:
510         signal(SIGALRM, restart);
511         input("Enter MIT Id:", buf, 14, MITID_TIMEOUT, FALSE);
512         i = 0;
513         nbuf = &buf[0];
514         while (*nbuf != '\0') {
515                 if (*nbuf == ' ' || *nbuf == '-') {
516                         nbuf++;
517                         continue;
518                 }
519                 if (!isdigit(*nbuf)) {
520                         i = 0;
521                         break;
522                 }
523                 typed_mit_id[i] = *nbuf;
524                 nbuf++;
525                 i++;
526         }
527         if (i != 9) {
528                 display_text_line(
529                                   "Your MIT id must be a nine-digit number.  Please try again.");
530                 goto input_mit_id;
531         }
532         typed_mit_id[9] = '\0';
533         redisp();
534         encrypt_mitid();
535 }
536
537 encrypt_mitid()
538 {
539         char            salt[3];
540
541         make_salt(salt, user.u_first, user.u_last);
542         strcpy(user.u_mit_id, crypt(&typed_mit_id[2], salt));
543 }
544
545
546 #define _tolower(c) ((c)|0x60)
547
548 make_salt(salt, first, last)
549         char           *salt, *first, *last;
550 {
551         salt[0] = _tolower(last[0]);
552         salt[1] = _tolower(first[0]);
553 }
554
555
556 gmi()
557 {
558         /* get middle initial */
559         char            buf[MID_INIT_SIZE+2];
560
561         signal(SIGALRM, restart);
562         input("Enter Middle Initial:", buf, MID_INIT_SIZE+1, MI_TIMEOUT, TRUE);
563         strncpy(user.u_mid_init, buf, MID_INIT_SIZE);
564         user.u_mid_init[MID_INIT_SIZE - 1] = '\0';
565         canon_name(user.u_mid_init);
566         redisp();
567 }
568
569 qexit()
570 {
571         /* exit quickly, not saving anything in the database */
572         bzero(&user, sizeof(user));
573         typed_mit_id[0] = '\0';
574         user_is_valid = 0;
575         already_registered = 0;
576         sleep(2);               /* give the user a chance to see the screen */
577         display_text_line(0);
578         return (EXIT);
579 }
580
581
582 do_replace()
583 {
584         int status;
585         
586         /*
587          * replaces a user in the database. If there is an error, it informs
588          * the user and calls qexit(); It returns only if is is successful 
589          */
590         timer_off();
591         status = set_password(user.u_first, user.u_last, typed_mit_id,
592                               user.u_mit_id, user.u_password);
593         wfeep();
594         timer_on();
595         if (status) {
596                 display_text (NETWORK_DOWN);
597                 return (-1);
598         } else return 0;
599 }
600
601 #define _toupper(c) ((c) & ~0x20)
602
603 lenient_strcmp(string1, string2)
604         register char  *string1, *string2;
605 {
606         /*
607          * a primitive case insensitive string comparison. It returns only 0
608          * if the strings are equal (ignoring case) and 1 if they are
609          * different. Also ignores spaces. 
610          */
611
612         while (1) {
613                 if (*string1 == '\0' && *string2 == '\0') {
614                         return (0);
615                 }
616                 if (*string1 == ' ' || *string1 == '.' || *string1 == '-' || *string1 == '\'') {
617                         string1++;
618                         continue;
619                 }
620                 if (*string2 == ' ' || *string2 == '.' || *string2 == '-' || *string2 == '\'') {
621                         string2++;
622                         continue;
623                 }
624                 if (_toupper(*string1) != _toupper(*string2)) {
625                         return (1);
626                 }
627                 string1++;
628                 string2++;
629         }
630 }
631
632 /*
633  * Input timeout handler.  Loop back to asking for the first name. 
634  */
635
636 restart()
637 /* Go to asking for first name. */
638 {
639         qexit();
640         longjmp(redo);
641 }
642
643 canon_name(cp)
644         register char *cp;
645 {
646         register char *p2 = cp;
647       
648         /* Trim whitespace off both ends. */
649         for (; *p2 && isspace(*p2); p2++) ;
650         if (*p2) {
651                 strcpy(cp, p2);
652                 p2 = cp + strlen(cp);
653                 --p2;
654                 while (p2 >= cp && isspace(*p2)) *(--p2) = '\0';
655         }
656         /* Make it capitalized */
657         for (p2=cp; *p2; p2++) {
658                 if (isupper(*p2)) *p2 = tolower(*p2);
659         }
660         if (islower(*cp)) *cp=toupper(*cp);
661 }
This page took 0.708286 seconds and 5 git commands to generate.