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