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