]> andersk Git - moira.git/blob - clients/userreg/userreg.c
added some new files
[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 <des.h>
24 #include <kadm.h>
25 #include <kadm_err.h>
26 #include <errno.h>
27 #include "userreg.h"
28 #include "ureg_err.h"
29
30 /* 7.2 release compatibility */
31 #ifndef KADM_INSECURE_PW
32 #define KADM_INSECURE_PW        (-1783126240L)
33 #endif
34
35 #define EXIT -1
36
37
38 struct user     user, db_user;
39 struct alias    alias;
40 char            typed_mit_id[100];
41 char            realm[REALM_SZ];
42 jmp_buf         redo;
43 int             restart();
44
45 extern int      errno;
46 int             user_is_valid = 0;
47 int             user_has_login = 0;
48 int             already_registered = 0;
49 int             enrollment = 0;
50 extern char *disabled();
51
52 fix_display(sig)
53 {
54         signal(sig, SIG_IGN);   /* let us clean up, please */
55         noraw();
56         echo();
57         endwin();
58         exit(1);
59 }
60
61 main(argc, argv)
62         int             argc;
63         char          **argv;
64 {
65         register int    ntimes;
66         register int    reencrypt;
67         char            line[100], *when, *msg;
68         int status;
69         char tmpfirst[100], tmplast[100], tmpmid[100];
70         
71         status = ureg_init();
72         if (status) {
73                 com_err(argv[0], status, "while trying to initialize");
74                 exit(1);
75         }
76
77         if (when = disabled(&msg)) {
78             printf("We're sorry, the registration service is unavailable right now\n");
79             if (msg)
80               printf("because %s\n", msg);
81             printf("You should be able to register after %s", when);
82             printf("\nPress ENTER or RETURN to continue ");
83             fflush(stdout);
84             getchar();
85             exit(0);
86         }
87
88         /* stash the realm for later use */
89         if ((status = krb_get_lrealm(realm, 1)) != KSUCCESS) {
90             printf("System error; please try another workstation.");
91             exit(1);
92         }
93
94         setup_display();
95
96         signal(SIGINT, fix_display);
97         signal(SIGQUIT, fix_display);
98         signal(SIGHUP, fix_display);
99
100         while (1) {
101                 setjmp(redo);
102                 reset();
103                 ntimes = 0;
104
105                 display_text(WELCOME, "");
106
107                 gfirst();
108                 gmi();
109                 glast();
110                 strcpy(tmpfirst, user.u_first);
111                 strcpy(tmplast, user.u_last);
112                 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
113                 redisp();
114                 
115                 gmitid();
116                 
117                 while (dolook()) {
118                         ntimes++;
119                         if (ntimes > 3) {
120                                 display_text_line(0);
121                                 display_text_line("Sorry, you still cannot be found in the database.");
122                                 display_text_line(" ");
123                                 display_text_line("Please call the account administrator at x3-1325 for help.");
124                                 wait_for_user();
125                                 break;
126                         }
127                         display_text_line(0);   /* clear the window */
128                         display_text_line("You could not be found in the database.");
129                         display_text_line("Do you want to change some input (for example, the spelling");
130                         display_text_line("of part of your name) and try again?");
131                         if (askyn("Do you want to try again ? ") == YES) {
132                                 reencrypt = 0;
133                                 display_text_line(0);
134                                 sprintf(line,
135                                         "You entered your first name as \"%s\"", user.u_first);
136                                 display_text_line(line);
137                                 if (askyn("Do you want to change it? ") == YES) {
138                                         gfirst();
139                                         strcpy(tmpfirst, user.u_first);
140                                         strcpy(tmplast, user.u_last);
141                                         FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
142                                         redisp();
143                                         reencrypt = 1;
144                                 }
145                                 display_text_line(0);
146                                 sprintf(line,
147                                         "You entered your middle initial as \"%s\"", user.u_mid_init);
148                                 display_text_line(line);
149                                 if (askyn("Do you want to change it? ") == YES)
150                                         gmi();
151                                 display_text_line(0);
152                                 sprintf(line,
153                                         "You entered your family name as \"%s\"", user.u_last);
154                                 display_text_line(line);
155                                 if (askyn("Do you want to change it? ") == YES) {
156                                         glast();
157                                         strcpy(tmpfirst, user.u_first);
158                                         strcpy(tmplast, user.u_last);
159                                         FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
160                                         redisp();
161                                         reencrypt = 1;
162                                 }
163                                 display_text_line(0);
164                                 sprintf(line,
165                                         "You entered your MIT id number as \"%s\"", typed_mit_id);
166                                 display_text_line(line);
167                                 if (askyn("Do you want to change it? ") == YES) {
168                                         gmitid();
169                                         reencrypt = 0;
170                                 }
171                                 if (reencrypt) {
172                                     EncryptID(user.u_mit_id, typed_mit_id,
173                                               user.u_first, user.u_last);
174                                 }
175                         } else
176                                 break;
177                 }
178                 if (!user_is_valid || already_registered) {
179                         qexit();
180                         continue;
181                 }
182                 redisp();
183                 if (!user_has_login) {
184                         if (negotiate_login() == -1) {
185                                 qexit();
186                                 continue;
187                         }
188                 }
189                 if (negotiate_passwd() == -1) {
190                         qexit();
191                         continue;
192                 }
193                 sleep(1);
194                 if (!enrollment)
195                   display_text(FINISHED, user.u_login);
196                 else {
197                     display_text(FINISHEDE, user.u_login);
198                     if (askyn("Do you wish to set your mailbox now? (Yes or No) ")) {
199                         clear();
200                         refresh();
201                         noraw();
202                         echo();
203                         kinit(user.u_login, user.u_password);
204                         system(NAMESPACE_PROG);
205                         dest_tkt();
206                         qexit();
207                         exit(0);
208                     }
209                 }
210                 wait_for_user();
211                 qexit();
212                 break;
213         }
214         restore_display();
215         exit(0);
216 }
217
218 reset()
219 {
220         reset_display();
221         bzero(&user, sizeof(user));
222         user_is_valid = 0;
223         already_registered = 0;
224         enrollment = 0;
225         redisp();
226 }
227
228 dolook()
229 {
230         /* do the database lookup */
231
232         char            line[100];
233         register int    result;
234         if (user_is_valid) {
235                 /* !! */
236                 return (0);
237         }
238         display_text_line(0);
239         display_text_line("Looking you up in the database.... This may take from 30 seconds to 10");
240         display_text_line("minutes, depending on how busy the system is at the moment.");
241
242         timer_off();
243         result = verify_user(user.u_first, user.u_last,
244                              typed_mit_id, user.u_mit_id, db_user.u_login);
245         wfeep();
246         display_text_line(0);
247         timer_on();
248         switch(result) {
249         case 0:
250         case UREG_ENROLLED:
251                 display_text_line("You have been located in the user registration database.");
252                 user_is_valid = 1;
253                 user_has_login = 0;
254                 sleep(1);
255                 return 0;
256         case UREG_HALF_ENROLLED:
257                 enrollment = 1;
258                 /* fall through to: */
259         case UREG_NO_PASSWD_YET:
260                 user_is_valid = 1;
261                 user_has_login = 1;
262                 display_text_line ("You have chosen a login name, but you have not yet chosen a password.");
263                 sprintf(line, "Remember: the username you chose was '%s'",
264                         db_user.u_login);
265                 strcpy(user.u_login, db_user.u_login);
266                 display_text_line(line);
267                 redisp();
268                 sleep(5);
269                 return (0);
270                 
271         case UREG_ALREADY_REGISTERED:
272                 already_registered = 1;
273                 /*
274                  * we have to reset this so we dont ask for a
275                  * new username 
276                  */     
277                 user_is_valid = 0;
278                 display_text_line("You are already registered.  An account for you probably already exists");
279                 display_text_line("(if not, it will appear within 12 hours).");
280                 display_text_line("");
281                 display_text_line("Refer to the document 'Getting Started on Athena' for help logging in.");
282                 strcpy(user.u_login, db_user.u_login);
283                 sprintf(line, "Remember, the username you chose was '%s'",
284                         db_user.u_login);
285                 display_text_line(line);
286                 redisp();
287                 wait_for_user();
288                 return (0);
289         case UREG_DELETED:
290                 display_text(DELETED_ACCT, db_user.u_login);
291                 wait_for_user();
292                 restore_display();
293                 exit(0);
294         case UREG_NOT_ALLOWED:
295                 display_text(OFFER_ENROLL, db_user.u_login);
296                 redisp();
297                 if (!askyn("Continue choosing a name and password (Y/N)? ")) {
298                     already_registered = 1;
299                     return(0);
300                 }
301                 user_has_login = 0;
302                 user_is_valid = 1;
303                 enrollment = 1;
304                 return(0);
305         case UREG_ENROLL_NOT_ALLOWED:
306                 display_text(NOT_ALLOWED, db_user.u_login);
307                 wait_for_user();
308                 restore_display();
309                 exit(0);
310         case UREG_KRB_TAKEN:
311                 display_text(IMPROPER_LOGIN, db_user.u_login);
312                 wait_for_user();
313                 return(0);
314         case UREG_USER_NOT_FOUND:
315                 return (1);
316
317         case ECONNREFUSED:
318         case ETIMEDOUT:
319         case UREG_MISC_ERROR:
320                 display_text(NETWORK_DOWN, db_user.u_login);
321                 display_text_line(" ");
322                 sprintf(line, "The specific error was: %s",
323                         error_message(result));
324                 display_text_line(line);
325                 wait_for_user();
326                 return (0);
327                 
328         default:
329                 display_text_line("An unexpected error occurred while trying to access the database");
330                 display_text_line(error_message(result));
331                 redisp();
332                 wait_for_user();
333                 return(1);
334         }
335 }
336
337
338 /* Get a login name from the user and register it.  There are several steps
339  * to this: display help message, get name, check name, display confirmation
340  * message, get confirmation, register name.
341  */
342
343 negotiate_login()
344 {
345     int result, i;
346     char line[100], old_login[LOGIN_SIZE+2];
347     char *error, *cp;
348         
349     /* build suggested username */
350     cp = user.u_login;
351     if (isalpha(user.u_first[0]))
352       *cp++ = user.u_first[0];
353     if (isalpha(user.u_mid_init[0]))
354       *cp++ = user.u_mid_init[0];
355     for (i = 0; user.u_last[i] && cp - user.u_login < 8; i++)
356       if (isalpha(user.u_last[i]))
357         *cp++ = user.u_last[i];
358     for (i=0; user.u_login[i]; i++)
359       if (isupper(user.u_login[i]))
360         user.u_login[i]=tolower(user.u_login[i]);
361     strcpy(old_login, user.u_login);
362         
363     /* print message */
364     display_text(USERNAME_BLURB, user.u_login);
365
366  again:
367     /* get name from user */
368     glogin();
369
370     display_text_line(0);
371     display_text_line("Testing that username...");
372     error = "";
373     if (strlen(user.u_login) < 3)
374       error = "Your username must be at least 3 characters long.";
375     else if (strlen(user.u_login) > 8)
376       error = "Your username cannot be longer than 8 characters.";
377     else if (!isalpha(user.u_login[0]) || !islower(user.u_login[0]))
378       error = "Your username must start with a lowercase letter.";
379     else for (i = 1; i < strlen(user.u_login); i++)
380       if (!islower(user.u_login[i]) &&
381           !isdigit(user.u_login[i]) &&
382           user.u_login[i] != '_')
383         error = "Your username must contain only lower case letters, numbers, and underscore";
384     timer_off();
385     result = krb_get_pw_in_tkt(user.u_login, "", realm, 
386                                "krbtgt", realm, 1, "");
387     timer_on();
388     if (*error == 0 && result != KDC_PR_UNKNOWN)
389       error = "That username is already taken.";
390
391     /* if it's bad, get another name from user */
392     if (*error) {
393         strcpy(user.u_login, old_login);
394         redisp();
395         display_text_line(error);
396         display_text_line("Please choose another username.");
397         goto again;
398     }
399
400     /* name is OK, make sure */
401     display_text(USERNAME_BLURB2, user.u_login);
402     if (!askyn("Do you want to register this username? (Yes or No) "))
403       goto again;
404
405     display_text_line(0);
406     display_text_line("Trying to assign that username...  This may take a few minutes.");
407
408     /* Do It! */
409     timer_off();
410     if (!enrollment)
411       result = grab_login(user.u_first, user.u_last,
412                           typed_mit_id, user.u_mit_id,
413                           user.u_login);
414     else
415       result = enroll_login(user.u_first, user.u_last,
416                             typed_mit_id, user.u_mit_id,
417                             user.u_login);
418     wfeep();
419     timer_on();
420     if (result != 0) {
421         char buf[BUFSIZ];
422
423         if (result == UREG_LOGIN_USED) {
424             /* name was in moira but not kerberos */
425             error = "Sorry, that username really was in use after all.";
426             strcpy(user.u_login, old_login);
427             redisp();
428             display_text_line(error);
429             display_text_line("Please choose another username.");
430             goto again;
431         }
432
433         display_text(NETWORK_DOWN, "");
434         display_text_line(" ");
435         sprintf(buf, "The specific error was: %s", error_message(result));
436         display_text_line(buf);
437         wait_for_user();
438         return (qexit());
439     }
440
441     /* at this point we have successfully negotiated a username */
442     sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
443     display_text_line(0);
444     display_text_line(line);
445     redisp();
446     sleep(3);
447     return 0;
448 }
449
450
451 negotiate_passwd()
452 {
453     char *passwd, *error;
454     char old_passwd[256], fullname[256], tktstring[256], inst[INST_SZ];
455     char login[ANAME_SZ], lpassword[PASSWORD_SIZE];
456     int result;
457     des_cblock key;
458     FILE *in;
459
460  again:
461     display_text(PASSWORD_BLURB, "");
462     gpass();
463
464     /* validate password */
465     error = NULL;
466     passwd = user.u_password;
467     sprintf(fullname, "%s%s", user.u_first, user.u_last);
468     if (strlen(passwd) < 6)
469       error = "Please choose a longer password.";
470     if (!strpasscmp(passwd, user.u_first) ||
471         !strpasscmp(passwd, user.u_last) ||
472         !strpasscmp(passwd, user.u_login) ||
473         !strpasscmp(passwd, fullname) ||
474         !strpasscmp(passwd, typed_mit_id))
475       error = "Please do not use your name or ID number for your password.";
476     if (!error) {
477         in = fopen(LOGIN_INFO, "r");
478         if (in != NULL) {
479             fgets(login, sizeof(login), in);
480             /* trim trailing newline */
481             if (strlen(login))
482               login[strlen(login) - 1] = 0;
483             fgets(lpassword, sizeof(lpassword), in);
484             /* trim trailing newline */
485             if (strlen(lpassword))
486               lpassword[strlen(lpassword) - 1] = 0;
487             fclose(in);
488         } else {
489             strcpy(login, "moira");
490             strcpy(lpassword, "moira");
491         }
492
493         sprintf(tktstring, "/tmp/tkt_cpw_%d", getpid());
494         krb_set_tkt_string(tktstring);  
495         des_string_to_key(passwd, key);
496         inst[0] = 0;
497
498         result = krb_get_pw_in_tkt(login, inst, realm, PWSERV_NAME,
499                                    KADM_SINST, 1, lpassword);
500         if (result == KSUCCESS)
501           result = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm);
502         if (result == KSUCCESS)
503           result = kadm_check_pw(key, passwd, &error);
504         dest_tkt();
505         if (result != KSUCCESS && result != KADM_INSECURE_PW) {
506             display_text(NETWORK_DOWN);
507             display_text_line(" ");
508             sprintf(fullname, "%s while verifying password",
509                     error_message(result));
510             display_text_line(fullname);
511             wait_for_user();
512             return(-1);
513         }
514     }
515
516     if (error) {
517         display_text_line(0);
518         display_text_line(error);
519         wait_for_user();
520         goto again;
521     }
522
523     display_text(PASSWORD_BLURB2, "");
524     strcpy(old_passwd, user.u_password);
525     gpass();
526     if (strcmp(old_passwd, user.u_password)) {
527         display_text_line(0);
528         display_text_line("What you just typed did not match the password you gave the first time.");
529         sleep(8);
530         goto again;
531     }
532
533     display_text_line("Storing password in the database...  This may take a few minutes.");
534     if (do_replace()) {
535         return (-1);
536     }
537     display_text_line("done.");
538     return(0);
539 }
540
541 gfirst()
542 {
543         /* input the first name */
544         char            buf[FIRST_NAME_SIZE+2];
545
546         signal(SIGALRM, fix_display);
547         input("Enter first Name:", buf, FIRST_NAME_SIZE+1,
548               FIRSTNAME_TIMEOUT, TRUE);
549         strncpy(user.u_first, buf, FIRST_NAME_SIZE);
550         user.u_first[FIRST_NAME_SIZE - 1] = '\0';
551         canon_name(user.u_first);
552         redisp();
553 }
554
555 glast()
556 {
557         /* input the last name */
558         char            buf[LAST_NAME_SIZE+2];
559
560         signal(SIGALRM, restart);
561         input("Enter family Name:", buf, LAST_NAME_SIZE+1,
562               LASTNAME_TIMEOUT, FALSE);
563         strncpy(user.u_last, buf, LAST_NAME_SIZE);
564         user.u_last[LAST_NAME_SIZE - 1] = '\0';
565         canon_name(user.u_last);
566         redisp();
567 }
568
569 gpass()
570 {
571         /* input password */
572         char            new_password[PASSWORD_SIZE + 1];
573
574         signal(SIGALRM, restart);
575         input_no_echo("Enter password:", new_password,
576                       PASSWORD_SIZE, NEW_PASSWORD_TIMEOUT);
577         strcpy(user.u_password, new_password);
578         redisp();
579 }
580
581
582 /* get login name */
583
584 glogin()
585 {
586         char buf[LOGIN_SIZE+2];
587
588         user.u_login[0] = '\0';
589         signal(SIGALRM, restart);
590         input("Enter username:", buf, LOGIN_SIZE, USERNAME_TIMEOUT, FALSE);
591         strcpy(user.u_login, buf);
592         redisp();
593 }
594
595 gmitid()
596 {
597         /* get mid id */
598         register int    i;
599         char            buf[15];
600         register char  *nbuf = buf;
601
602 input_mit_id:
603         signal(SIGALRM, restart);
604         input("Enter MIT Id:", buf, 14, MITID_TIMEOUT, FALSE);
605         i = 0;
606         nbuf = &buf[0];
607         while (*nbuf != '\0') {
608                 if (*nbuf == ' ' || *nbuf == '-') {
609                         nbuf++;
610                         continue;
611                 }
612                 if (!isdigit(*nbuf)) {
613                         i = 0;
614                         break;
615                 }
616                 typed_mit_id[i] = *nbuf;
617                 nbuf++;
618                 i++;
619         }
620         if (i != 9) {
621                 display_text_line(
622                                   "Your MIT id must be a nine-digit number.  Please try again.");
623                 goto input_mit_id;
624         }
625         typed_mit_id[9] = '\0';
626         redisp();
627         EncryptID(user.u_mit_id, typed_mit_id, user.u_first, user.u_last);
628 }
629
630 gmi()
631 {
632         /* get middle initial */
633         char            buf[MID_INIT_SIZE+2];
634
635         signal(SIGALRM, restart);
636         input("Enter Middle Initial:", buf, MID_INIT_SIZE+1, MI_TIMEOUT, TRUE);
637         strncpy(user.u_mid_init, buf, MID_INIT_SIZE);
638         user.u_mid_init[MID_INIT_SIZE - 1] = '\0';
639         canon_name(user.u_mid_init);
640         redisp();
641 }
642
643 qexit()
644 {
645         /* exit quickly, not saving anything in the database */
646         bzero(&user, sizeof(user));
647         typed_mit_id[0] = '\0';
648         user_is_valid = 0;
649         already_registered = 0;
650         enrollment = 0;
651         sleep(2);               /* give the user a chance to see the screen */
652         display_text_line(0);
653         return (EXIT);
654 }
655
656
657 do_replace()
658 {
659         int status;
660         char buf[100];
661         
662         /*
663          * replaces a user in the database. If there is an error, it informs
664          * the user and calls qexit(); It returns only if is is successful 
665          */
666         timer_off();
667         if (!enrollment)
668           status = set_password(user.u_first, user.u_last, typed_mit_id,
669                                 user.u_mit_id, user.u_password);
670         else
671           status = get_krb(user.u_first, user.u_last, typed_mit_id,
672                                 user.u_mit_id, user.u_password);
673         wfeep();
674         timer_on();
675         if (status) {
676                 display_text (NETWORK_DOWN);
677                 display_text_line(" ");
678                 sprintf(buf, "The specific error was: %s",
679                         error_message(status));
680                 display_text_line(buf);
681                 wait_for_user();
682                 return (-1);
683         } else return 0;
684 }
685
686
687 kinit(user, passwd)
688 char *user, *passwd;
689 {
690     int status;
691     char inst[INST_SZ];
692
693     inst[0] = 0;
694     status = krb_get_pw_in_tkt(user, inst, realm, "krbtgt",
695                                realm, DEFAULT_TKT_LIFE, 0);
696     return(status);
697 }
698
699
700 #ifndef _toupper
701 #define _toupper(c) ((c) & ~0x20)
702 #endif
703
704 lenient_strcmp(string1, string2)
705         register char  *string1, *string2;
706 {
707         /*
708          * a primitive case insensitive string comparison. It returns only 0
709          * if the strings are equal (ignoring case) and 1 if they are
710          * different. Also ignores spaces. 
711          */
712
713         while (1) {
714                 if (*string1 == '\0' && *string2 == '\0') {
715                         return (0);
716                 }
717                 if (*string1 == ' ' || *string1 == '.' || *string1 == '-' ||
718                     *string1 == '\'' || *string1 == '_') {
719                         string1++;
720                         continue;
721                 }
722                 if (*string2 == ' ' || *string2 == '.' || *string2 == '-' ||
723                     *string2 == '\'' || *string2 == '_') {
724                         string2++;
725                         continue;
726                 }
727                 if (_toupper(*string1) != _toupper(*string2)) {
728                         return (1);
729                 }
730                 string1++;
731                 string2++;
732         }
733 }
734
735
736 /* See if the strings match in forward & reverse direction, ignoring
737  * case and spaces/punctuation.
738  */
739
740 strpasscmp(s1, s2)
741 char *s1, *s2;
742 {
743     char buf[256], *from, *to;
744
745     if (!lenient_strcmp(s1, s2))
746       return(0);
747     /* if s2 is empty, say OK */
748     if (!*s2)
749       return(1);
750
751     from = &s2[strlen(s2)];
752     from--;
753     for (to = &buf[0]; from >= s2; from--)
754       *to++ = *from;
755
756     return(lenient_strcmp(s1, buf));
757 }
758
759
760 /*
761  * Input timeout handler.  Loop back to asking for the first name. 
762  */
763
764 restart()
765 /* Go to asking for first name. */
766 {
767         qexit();
768         longjmp(redo, 1);
769 }
770
771 canon_name(cp)
772         register char *cp;
773 {
774         register char *p2 = cp;
775       
776         /* Trim whitespace off both ends. */
777         for (; *p2 && isspace(*p2); p2++) ;
778         if (*p2) {
779                 strcpy(cp, p2);
780                 p2 = cp + strlen(cp);
781                 --p2;
782                 while (p2 >= cp && isspace(*p2)) *(--p2) = '\0';
783         }
784         /* Make it capitalized */
785         FixCase(cp);
786 }
This page took 0.247922 seconds and 5 git commands to generate.