7 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
8 * For copying and distribution information, please see the file
13 static char *rcsid_userreg_c = "$Header$";
16 #include <mit-copyright.h>
31 /* 7.2 release compatibility */
32 #ifndef KADM_INSECURE_PW
33 #define KADM_INSECURE_PW (-1783126240L)
39 struct user user, db_user;
41 char typed_mit_id[100];
47 int user_is_valid = 0;
48 int user_has_login = 0;
49 int already_registered = 0;
51 extern char *disabled();
58 sigemptyset(&act.sa_mask);
60 act.sa_handler= (void (*)()) SIG_IGN;
61 sigaction(sig, &act, NULL);
63 signal(sig, SIG_IGN); /* let us clean up, please */
76 register int reencrypt;
77 char line[100], *when, *msg;
79 char tmpfirst[100], tmplast[100], tmpmid[100];
86 com_err(argv[0], status, "while trying to initialize");
90 if (when = disabled(&msg)) {
91 printf("We're sorry, the registration service is unavailable right now\n");
93 printf("because %s\n", msg);
94 printf("You should be able to register after %s", when);
95 printf("\nPress ENTER or RETURN to continue ");
101 /* stash the realm for later use */
102 if ((status = krb_get_lrealm(realm, 1)) != KSUCCESS) {
103 printf("System error; please try another workstation.");
110 sigemptyset(&act.sa_mask);
112 act.sa_handler= (void (*)()) fix_display;
113 sigaction(SIGINT, &act, NULL);
114 sigaction(SIGQUIT, &act, NULL);
115 sigaction(SIGHUP, &act, NULL);
117 signal(SIGINT, fix_display);
118 signal(SIGQUIT, fix_display);
119 signal(SIGHUP, fix_display);
127 display_text(WELCOME, "");
132 strcpy(tmpfirst, user.u_first);
133 strcpy(tmplast, user.u_last);
134 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
142 display_text_line(0);
143 display_text_line("Sorry, you still cannot be found in the database.");
144 display_text_line(" ");
145 display_text_line("Please call an accounts consultant at x3-1325 for help.");
149 display_text_line(0); /* clear the window */
150 display_text_line("You could not be found in the database.");
151 display_text_line("Do you want to change some input (for example, the spelling");
152 display_text_line("of part of your name) and try again?");
153 if (askyn("Do you want to try again ? ") == YES) {
155 display_text_line(0);
157 "You entered your first name as \"%s\"", user.u_first);
158 display_text_line(line);
159 if (askyn("Do you want to change it? ") == YES) {
161 strcpy(tmpfirst, user.u_first);
162 strcpy(tmplast, user.u_last);
163 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
167 display_text_line(0);
169 "You entered your middle initial as \"%s\"", user.u_mid_init);
170 display_text_line(line);
171 if (askyn("Do you want to change it? ") == YES)
173 display_text_line(0);
175 "You entered your family name as \"%s\"", user.u_last);
176 display_text_line(line);
177 if (askyn("Do you want to change it? ") == YES) {
179 strcpy(tmpfirst, user.u_first);
180 strcpy(tmplast, user.u_last);
181 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
185 display_text_line(0);
187 "You entered your MIT id number as \"%s\"", typed_mit_id);
188 display_text_line(line);
189 if (askyn("Do you want to change it? ") == YES) {
194 EncryptID(user.u_mit_id, typed_mit_id,
195 user.u_first, user.u_last);
200 if (!user_is_valid || already_registered) {
205 if (!user_has_login) {
206 if (negotiate_login() == -1) {
211 if (negotiate_passwd() == -1) {
217 display_text(FINISHED, user.u_login);
219 display_text(FINISHEDE, user.u_login);
220 if (askyn("Do you wish to set your mailbox now? (Yes or No) ")) {
225 kinit(user.u_login, user.u_password);
226 system(NAMESPACE_PROG);
243 memset(&user, 0, sizeof(user));
245 already_registered = 0;
252 /* do the database lookup */
260 display_text_line(0);
261 display_text_line("Looking you up in the database.... This may take from 30 seconds to 10");
262 display_text_line("minutes, depending on how busy the system is at the moment.");
265 result = verify_user(user.u_first, user.u_last,
266 typed_mit_id, user.u_mit_id, db_user.u_login);
268 display_text_line(0);
273 display_text_line("You have been located in the user registration database.");
278 case UREG_HALF_ENROLLED:
280 /* fall through to: */
281 case UREG_NO_PASSWD_YET:
284 display_text_line ("You have chosen a login name, but you have not yet chosen a password.");
285 sprintf(line, "Remember: the username you chose was '%s'",
287 strcpy(user.u_login, db_user.u_login);
288 display_text_line(line);
293 case UREG_ALREADY_REGISTERED:
294 already_registered = 1;
296 * we have to reset this so we dont ask for a
300 display_text_line("You are already registered. An account for you probably already exists");
301 display_text_line("(if not, it will appear within 12 hours).");
302 display_text_line("");
303 display_text_line("Refer to the document 'Getting Started on Athena' for help logging in.");
304 strcpy(user.u_login, db_user.u_login);
305 sprintf(line, "Remember, the username you chose was '%s'",
307 display_text_line(line);
312 display_text(DELETED_ACCT, db_user.u_login);
316 case UREG_NOT_ALLOWED:
317 display_text(OFFER_ENROLL, db_user.u_login);
319 if (!askyn("Continue choosing a name and password (Y/N)? ")) {
320 already_registered = 1;
327 case UREG_ENROLL_NOT_ALLOWED:
328 display_text(NOT_ALLOWED, db_user.u_login);
333 display_text(IMPROPER_LOGIN, db_user.u_login);
336 case UREG_USER_NOT_FOUND:
341 case UREG_MISC_ERROR:
342 display_text(NETWORK_DOWN, db_user.u_login);
343 display_text_line(" ");
344 sprintf(line, "The specific error was: %s",
345 error_message(result));
346 display_text_line(line);
351 display_text_line("An unexpected error occurred while trying to access the database");
352 display_text_line(error_message(result));
360 /* Get a login name from the user and register it. There are several steps
361 * to this: display help message, get name, check name, display confirmation
362 * message, get confirmation, register name.
368 char line[100], old_login[LOGIN_SIZE+2];
371 /* build suggested username */
373 if (isalpha(user.u_first[0]))
374 *cp++ = user.u_first[0];
375 if (isalpha(user.u_mid_init[0]))
376 *cp++ = user.u_mid_init[0];
377 for (i = 0; user.u_last[i] && cp - user.u_login < 8; i++)
378 if (isalpha(user.u_last[i]))
379 *cp++ = user.u_last[i];
380 for (i=0; user.u_login[i]; i++)
381 if (isupper(user.u_login[i]))
382 user.u_login[i]=tolower(user.u_login[i]);
383 strcpy(old_login, user.u_login);
386 display_text(USERNAME_BLURB, user.u_login);
389 /* get name from user */
392 display_text_line(0);
393 display_text_line("Testing that username...");
395 if (strlen(user.u_login) < 3)
396 error = "Your username must be at least 3 characters long.";
397 else if (strlen(user.u_login) > 8)
398 error = "Your username cannot be longer than 8 characters.";
399 else if (!isalpha(user.u_login[0]) || !islower(user.u_login[0]))
400 error = "Your username must start with a lowercase letter.";
401 else for (i = 1; i < strlen(user.u_login); i++)
402 if (!islower(user.u_login[i]) &&
403 !isdigit(user.u_login[i]) &&
404 user.u_login[i] != '_')
405 error = "Your username must contain only lower case letters, numbers, and underscore";
407 result = krb_get_pw_in_tkt(user.u_login, "", realm,
408 "krbtgt", realm, 1, "");
410 if (*error == 0 && result != KDC_PR_UNKNOWN)
411 error = "That username is already taken.";
413 /* if it's bad, get another name from user */
415 strcpy(user.u_login, old_login);
417 display_text_line(error);
418 display_text_line("Please choose another username.");
422 /* name is OK, make sure */
423 display_text(USERNAME_BLURB2, user.u_login);
424 if (!askyn("Do you want to register this username? (Yes or No) "))
427 display_text_line(0);
428 display_text_line("Trying to assign that username... This may take a few minutes.");
433 result = grab_login(user.u_first, user.u_last,
434 typed_mit_id, user.u_mit_id,
437 result = enroll_login(user.u_first, user.u_last,
438 typed_mit_id, user.u_mit_id,
445 if (result == UREG_LOGIN_USED) {
446 /* name was in moira but not kerberos */
447 error = "Sorry, that username really was in use after all.";
448 strcpy(user.u_login, old_login);
450 display_text_line(error);
451 display_text_line("Please choose another username.");
455 display_text(NETWORK_DOWN, "");
456 display_text_line(" ");
457 sprintf(buf, "The specific error was: %s", error_message(result));
458 display_text_line(buf);
463 /* at this point we have successfully negotiated a username */
464 sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
465 display_text_line(0);
466 display_text_line(line);
475 char *passwd, *error;
476 char old_passwd[256], fullname[256], tktstring[256], inst[INST_SZ];
477 char login[ANAME_SZ], lpassword[PASSWORD_SIZE];
483 display_text(PASSWORD_BLURB, "");
486 /* validate password */
488 passwd = user.u_password;
489 sprintf(fullname, "%s%s", user.u_first, user.u_last);
490 if (strlen(passwd) < 6)
491 error = "Please choose a longer password.";
492 if (!strpasscmp(passwd, user.u_first) ||
493 !strpasscmp(passwd, user.u_last) ||
494 !strpasscmp(passwd, user.u_login) ||
495 !strpasscmp(passwd, fullname) ||
496 !strpasscmp(passwd, typed_mit_id))
497 error = "Please do not use your name or ID number for your password.";
499 in = fopen(LOGIN_INFO, "r");
501 fgets(login, sizeof(login), in);
502 /* trim trailing newline */
504 login[strlen(login) - 1] = 0;
505 fgets(lpassword, sizeof(lpassword), in);
506 /* trim trailing newline */
507 if (strlen(lpassword))
508 lpassword[strlen(lpassword) - 1] = 0;
511 strcpy(login, "moira");
512 strcpy(lpassword, "moira");
515 sprintf(tktstring, "/tmp/tkt_cpw_%d", getpid());
516 krb_set_tkt_string(tktstring);
517 des_string_to_key(passwd, key);
520 result = krb_get_pw_in_tkt(login, inst, realm, PWSERV_NAME,
521 KADM_SINST, 1, lpassword);
522 if (result == KSUCCESS)
523 result = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm);
524 if (result == KSUCCESS)
525 result = kadm_check_pw(key, passwd, &error);
527 if (result == KADM_INSECURE_PW) {
528 error = "You have chosen a passsword that is in the dictionary of commonly\nselected user passwords. You will have to choose a better password.";
529 } else if (result != KSUCCESS) {
530 display_text(NETWORK_DOWN);
531 display_text_line(" ");
532 sprintf(fullname, "%s while verifying password",
533 error_message(result));
534 display_text_line(fullname);
541 display_text_line(0);
542 display_text_line(error);
547 display_text(PASSWORD_BLURB2, "");
548 strcpy(old_passwd, user.u_password);
550 if (strcmp(old_passwd, user.u_password)) {
551 display_text_line(0);
552 display_text_line("What you just typed did not match the password you gave the first time.");
557 display_text_line("Storing password in the database... This may take a few minutes.");
561 display_text_line("done.");
567 /* input the first name */
568 char buf[FIRST_NAME_SIZE+2];
570 struct sigaction act;
572 sigemptyset(&act.sa_mask);
574 act.sa_handler= (void (*)()) fix_display;
575 sigaction(SIGALRM, &act, NULL);
577 signal(SIGALRM, fix_display);
579 input("Enter first Name:", buf, FIRST_NAME_SIZE+1,
580 FIRSTNAME_TIMEOUT, TRUE);
581 strncpy(user.u_first, buf, FIRST_NAME_SIZE);
582 user.u_first[FIRST_NAME_SIZE - 1] = '\0';
583 canon_name(user.u_first);
589 /* input the last name */
590 char buf[LAST_NAME_SIZE+2];
592 struct sigaction act;
594 sigemptyset(&act.sa_mask);
596 act.sa_handler= (void (*)()) fix_display;
597 sigaction(SIGALRM, &act, NULL);
599 signal(SIGALRM, restart);
601 input("Enter family Name:", buf, LAST_NAME_SIZE+1,
602 LASTNAME_TIMEOUT, FALSE);
603 strncpy(user.u_last, buf, LAST_NAME_SIZE);
604 user.u_last[LAST_NAME_SIZE - 1] = '\0';
605 canon_name(user.u_last);
612 char new_password[PASSWORD_SIZE + 1];
614 struct sigaction act;
616 sigemptyset(&act.sa_mask);
618 act.sa_handler= (void (*)()) fix_display;
619 sigaction(SIGALRM, &act, NULL);
621 signal(SIGALRM, restart);
623 input_no_echo("Enter password:", new_password,
624 PASSWORD_SIZE, NEW_PASSWORD_TIMEOUT);
625 strcpy(user.u_password, new_password);
634 char buf[LOGIN_SIZE+2];
636 struct sigaction act;
638 sigemptyset(&act.sa_mask);
640 act.sa_handler= (void (*)()) fix_display;
641 sigaction(SIGALRM, &act, NULL);
643 signal(SIGALRM, restart);
645 user.u_login[0] = '\0';
646 input("Enter username:", buf, LOGIN_SIZE, USERNAME_TIMEOUT, FALSE);
647 strcpy(user.u_login, buf);
656 register char *nbuf = buf;
658 struct sigaction act;
664 sigemptyset(&act.sa_mask);
666 act.sa_handler= (void (*)()) fix_display;
667 sigaction(SIGALRM, &act, NULL);
669 signal(SIGALRM, restart);
671 input("Enter MIT Id:", buf, 14, MITID_TIMEOUT, FALSE);
674 while (*nbuf != '\0') {
675 if (*nbuf == ' ' || *nbuf == '-') {
679 if (!isdigit(*nbuf)) {
683 typed_mit_id[i] = *nbuf;
689 "Your MIT id must be a nine-digit number. Please try again.");
692 typed_mit_id[9] = '\0';
694 EncryptID(user.u_mit_id, typed_mit_id, user.u_first, user.u_last);
699 /* get middle initial */
700 char buf[MID_INIT_SIZE+2];
702 struct sigaction act;
704 sigemptyset(&act.sa_mask);
706 act.sa_handler= (void (*)()) fix_display;
707 sigaction(SIGALRM, &act, NULL);
709 signal(SIGALRM, restart);
711 input("Enter Middle Initial:", buf, MID_INIT_SIZE+1, MI_TIMEOUT, TRUE);
712 strncpy(user.u_mid_init, buf, MID_INIT_SIZE);
713 user.u_mid_init[MID_INIT_SIZE - 1] = '\0';
714 canon_name(user.u_mid_init);
720 /* exit quickly, not saving anything in the database */
721 memset(&user, 0, sizeof(user));
722 typed_mit_id[0] = '\0';
724 already_registered = 0;
726 sleep(2); /* give the user a chance to see the screen */
727 display_text_line(0);
738 * replaces a user in the database. If there is an error, it informs
739 * the user and calls qexit(); It returns only if is is successful
743 status = set_password(user.u_first, user.u_last, typed_mit_id,
744 user.u_mit_id, user.u_password);
746 status = get_krb(user.u_first, user.u_last, typed_mit_id,
747 user.u_mit_id, user.u_password);
751 display_text (NETWORK_DOWN);
752 display_text_line(" ");
753 sprintf(buf, "The specific error was: %s",
754 error_message(status));
755 display_text_line(buf);
769 status = krb_get_pw_in_tkt(user, inst, realm, "krbtgt",
770 realm, DEFAULT_TKT_LIFE, 0);
776 #define _toupper(c) ((c) & ~0x20)
779 lenient_strcmp(string1, string2)
780 register char *string1, *string2;
783 * a primitive case insensitive string comparison. It returns only 0
784 * if the strings are equal (ignoring case) and 1 if they are
785 * different. Also ignores spaces.
789 if (*string1 == '\0' && *string2 == '\0') {
792 if (*string1 == ' ' || *string1 == '.' || *string1 == '-' ||
793 *string1 == '\'' || *string1 == '_') {
797 if (*string2 == ' ' || *string2 == '.' || *string2 == '-' ||
798 *string2 == '\'' || *string2 == '_') {
802 if (_toupper(*string1) != _toupper(*string2)) {
811 /* See if the strings match in forward & reverse direction, ignoring
812 * case and spaces/punctuation.
818 char buf[256], *from, *to;
820 if (!lenient_strcmp(s1, s2))
822 /* if s2 is empty, say OK */
826 from = &s2[strlen(s2)];
828 for (to = &buf[0]; from >= s2; from--)
831 return(lenient_strcmp(s1, buf));
836 * Input timeout handler. Loop back to asking for the first name.
840 /* Go to asking for first name. */
849 register char *p2 = cp;
851 /* Trim whitespace off both ends. */
852 for (; *p2 && isspace(*p2); p2++) ;
855 p2 = cp + strlen(cp);
857 while (p2 >= cp && isspace(*p2)) *(--p2) = '\0';
859 /* Make it capitalized */