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