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;
46 int user_is_valid = 0;
47 int user_has_login = 0;
48 int already_registered = 0;
50 extern char *disabled();
51 char typed_mit_id[100];
57 sigemptyset(&act.sa_mask);
59 act.sa_handler = SIG_IGN;
60 sigaction(sig, &act, NULL);
67 int main(int argc, char **argv)
70 register int reencrypt;
71 char line[100], *when, *msg;
73 char tmpfirst[100], tmplast[100], tmpmid[100];
79 com_err(argv[0], status, "while trying to initialize");
83 if (when = disabled(&msg))
85 printf("We're sorry, the registration service is unavailable right now\n");
87 printf("because %s\n", msg);
88 printf("You should be able to register after %s", when);
89 printf("\nPress ENTER or RETURN to continue ");
95 /* stash the realm for later use */
96 if ((status = krb_get_lrealm(realm, 1)) != KSUCCESS)
98 printf("System error; please try another workstation.");
104 sigemptyset(&act.sa_mask);
106 act.sa_handler = (void (*)()) fix_display;
107 sigaction(SIGINT, &act, NULL);
108 sigaction(SIGQUIT, &act, NULL);
109 sigaction(SIGHUP, &act, NULL);
117 display_text(WELCOME, "");
122 strcpy(tmpfirst, user.u_first);
123 strcpy(tmplast, user.u_last);
124 FixName(tmplast, tmpfirst, user.u_last, user.u_first, tmpmid);
134 display_text_line(0);
135 display_text_line("Sorry, you still cannot be found in the database.");
136 display_text_line(" ");
137 display_text_line("Please call an accounts consultant at x3-1325 for help.");
141 display_text_line(0); /* clear the window */
142 display_text_line("You could not be found in the database.");
143 display_text_line("Do you want to change some input "
144 "(for example, the spelling");
145 display_text_line("of part of your name) and try again?");
146 if (askyn("Do you want to try again ? ") == YES)
149 display_text_line(0);
150 sprintf(line, "You entered your first name as \"%s\"",
152 display_text_line(line);
153 if (askyn("Do you want to change it? ") == YES)
156 strcpy(tmpfirst, user.u_first);
157 strcpy(tmplast, user.u_last);
158 FixName(tmplast, tmpfirst, user.u_last, user.u_first,
163 display_text_line(0);
164 sprintf(line, "You entered your middle initial as \"%s\"",
166 display_text_line(line);
167 if (askyn("Do you want to change it? ") == YES)
169 display_text_line(0);
170 sprintf(line, "You entered your family name as \"%s\"",
172 display_text_line(line);
173 if (askyn("Do you want to change it? ") == YES)
176 strcpy(tmpfirst, user.u_first);
177 strcpy(tmplast, user.u_last);
178 FixName(tmplast, tmpfirst, user.u_last, user.u_first,
183 display_text_line(0);
184 sprintf(line, "You entered your MIT id number as \"%s\"",
186 display_text_line(line);
187 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);
201 if (!user_is_valid || already_registered)
209 if (negotiate_login() == -1)
215 if (negotiate_passwd() == -1)
222 display_text(FINISHED, user.u_login);
225 display_text(FINISHEDE, user.u_login);
226 if (askyn("Do you wish to set your mailbox now? (Yes or No) "))
232 kinit(user.u_login, user.u_password);
233 system(NAMESPACE_PROG);
250 memset(&user, 0, sizeof(user));
252 already_registered = 0;
259 /* do the database lookup */
269 display_text_line(0);
270 display_text_line("Looking you up in the database.... "
271 "This may take from a few seconds to a few");
272 display_text_line("minutes, depending on how busy the system is "
276 result = verify_user(user.u_first, user.u_last, typed_mit_id,
277 user.u_mit_id, db_user.u_login);
279 display_text_line(0);
285 display_text_line("You have been located in the user registration database.");
290 case UREG_HALF_ENROLLED:
292 /* fall through to: */
293 case UREG_NO_PASSWD_YET:
296 display_text_line ("You have chosen a login name, but you have not yet chosen a password.");
297 sprintf(line, "Remember: the username you chose was '%s'",
299 strcpy(user.u_login, db_user.u_login);
300 display_text_line(line);
305 case UREG_ALREADY_REGISTERED:
306 already_registered = 1;
308 * we have to reset this so we dont ask for a
312 display_text_line("You are already registered. "
313 "An account for you probably already exists");
314 display_text_line("(if not, it will appear within 24 hours).");
315 display_text_line("");
316 display_text_line("Refer to the document 'Working on Athena' "
317 "for help logging in.");
318 strcpy(user.u_login, db_user.u_login);
319 sprintf(line, "Remember, the username you chose was '%s'",
321 display_text_line(line);
326 display_text(DELETED_ACCT, db_user.u_login);
330 case UREG_NOT_ALLOWED:
331 display_text(OFFER_ENROLL, db_user.u_login);
333 if (!askyn("Continue choosing a name and password (Y/N)? "))
335 already_registered = 1;
342 case UREG_ENROLL_NOT_ALLOWED:
343 display_text(NOT_ALLOWED, db_user.u_login);
348 display_text(IMPROPER_LOGIN, db_user.u_login);
351 case UREG_USER_NOT_FOUND:
356 case UREG_MISC_ERROR:
357 display_text(NETWORK_DOWN, db_user.u_login);
358 display_text_line(" ");
359 sprintf(line, "The specific error was: %s", error_message(result));
360 display_text_line(line);
365 display_text_line("An unexpected error occurred while trying to "
366 "access the database");
367 display_text_line(error_message(result));
375 /* Get a login name from the user and register it. There are several steps
376 * to this: display help message, get name, check name, display confirmation
377 * message, get confirmation, register name.
380 int negotiate_login(void)
383 char line[100], old_login[LOGIN_SIZE + 2];
386 /* build suggested username */
388 if (isalpha(user.u_first[0]))
389 *cp++ = user.u_first[0];
390 if (isalpha(user.u_mid_init[0]))
391 *cp++ = user.u_mid_init[0];
392 for (i = 0; user.u_last[i] && cp - user.u_login < 8; i++)
394 if (isalpha(user.u_last[i]))
395 *cp++ = user.u_last[i];
397 for (i = 0; user.u_login[i]; i++)
399 if (isupper(user.u_login[i]))
400 user.u_login[i] = tolower(user.u_login[i]);
402 strcpy(old_login, user.u_login);
405 display_text(USERNAME_BLURB, user.u_login);
408 /* get name from user */
411 display_text_line(0);
412 display_text_line("Testing that username...");
414 if (strlen(user.u_login) < 3)
415 error = "Your username must be at least 3 characters long.";
416 else if (strlen(user.u_login) > 8)
417 error = "Your username cannot be longer than 8 characters.";
418 else if (!isalpha(user.u_login[0]) || !islower(user.u_login[0]))
419 error = "Your username must start with a lowercase letter.";
421 for (i = 1; i < strlen(user.u_login); i++)
423 if (!islower(user.u_login[i]) &&
424 !isdigit(user.u_login[i]) &&
425 user.u_login[i] != '_')
426 error = "Your username must contain only lower case letters, "
427 "numbers, and underscore";
430 result = krb_get_pw_in_tkt(user.u_login, "", realm, "krbtgt", realm, 1, "");
432 if (*error == 0 && result != KDC_PR_UNKNOWN)
433 error = "That username is already taken.";
435 /* if it's bad, get another name from user */
438 strcpy(user.u_login, old_login);
440 display_text_line(error);
441 display_text_line("Please choose another username.");
445 /* name is OK, make sure */
446 display_text(USERNAME_BLURB2, user.u_login);
447 if (!askyn("Do you want to register this username? (Yes or No) "))
450 display_text_line(0);
451 display_text_line("Trying to assign that username... "
452 "This may take a few minutes.");
458 result = grab_login(user.u_first, user.u_last, typed_mit_id,
459 user.u_mit_id, user.u_login);
463 result = enroll_login(user.u_first, user.u_last, typed_mit_id,
464 user.u_mit_id, user.u_login);
472 if (result == UREG_LOGIN_USED)
474 /* name was in moira but not kerberos */
475 error = "Sorry, that username really was in use after all.";
476 strcpy(user.u_login, old_login);
478 display_text_line(error);
479 display_text_line("Please choose another username.");
483 display_text(NETWORK_DOWN, "");
484 display_text_line(" ");
485 sprintf(buf, "The specific error was: %s", error_message(result));
486 display_text_line(buf);
491 /* at this point we have successfully negotiated a username */
492 sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
493 display_text_line(0);
494 display_text_line(line);
501 int negotiate_passwd(void)
503 char *passwd, *error;
504 char old_passwd[256], fullname[256], tktstring[256], inst[INST_SZ];
505 char login[ANAME_SZ], lpassword[PASSWORD_SIZE];
511 display_text(PASSWORD_BLURB, "");
514 /* validate password */
516 passwd = user.u_password;
517 sprintf(fullname, "%s%s", user.u_first, user.u_last);
518 if (strlen(passwd) < 6)
519 error = "Please choose a longer password.";
520 if (!strpasscmp(passwd, user.u_first) ||
521 !strpasscmp(passwd, user.u_last) ||
522 !strpasscmp(passwd, user.u_login) ||
523 !strpasscmp(passwd, fullname) ||
524 !strpasscmp(passwd, typed_mit_id))
525 error = "Please do not use your name or ID number for your password.";
528 in = fopen(LOGIN_INFO, "r");
531 fgets(login, sizeof(login), in);
532 /* trim trailing newline */
534 login[strlen(login) - 1] = '\0';
535 fgets(lpassword, sizeof(lpassword), in);
536 /* trim trailing newline */
537 if (strlen(lpassword))
538 lpassword[strlen(lpassword) - 1] = '\0';
543 strcpy(login, "moira");
544 strcpy(lpassword, "moira");
547 sprintf(tktstring, "/tmp/tkt_cpw_%d", getpid());
548 krb_set_tkt_string(tktstring);
549 des_string_to_key(passwd, key);
552 result = krb_get_pw_in_tkt(login, inst, realm, PWSERV_NAME,
553 KADM_SINST, 1, lpassword);
554 if (result == KSUCCESS)
555 result = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm);
556 if (result == KSUCCESS)
557 result = kadm_check_pw(key, passwd, &error);
559 if (result == KADM_INSECURE_PW)
561 error = "You have chosen a passsword that is in the dictionary "
562 "of commonly\nselected user passwords. You will have to choose "
563 "a better password.";
565 else if (result != KSUCCESS)
567 display_text(NETWORK_DOWN);
568 display_text_line(" ");
569 sprintf(fullname, "%s while verifying password",
570 error_message(result));
571 display_text_line(fullname);
579 display_text_line(0);
580 display_text_line(error);
585 display_text(PASSWORD_BLURB2, "");
586 strcpy(old_passwd, user.u_password);
588 if (strcmp(old_passwd, user.u_password))
590 display_text_line(0);
591 display_text_line("What you just typed did not match the password "
592 "you gave the first time.");
597 display_text_line("Storing password in the database... This may take "
601 display_text_line("done.");
607 /* input the first name */
608 char buf[FIRST_NAME_SIZE + 2];
609 struct sigaction act;
611 sigemptyset(&act.sa_mask);
613 act.sa_handler = (void (*)()) fix_display;
614 sigaction(SIGALRM, &act, NULL);
615 input("Enter first Name:", buf, FIRST_NAME_SIZE + 1,
616 FIRSTNAME_TIMEOUT, TRUE);
617 strncpy(user.u_first, buf, FIRST_NAME_SIZE);
618 user.u_first[FIRST_NAME_SIZE - 1] = '\0';
619 canon_name(user.u_first);
625 /* input the last name */
626 char buf[LAST_NAME_SIZE + 2];
627 struct sigaction act;
629 sigemptyset(&act.sa_mask);
631 act.sa_handler = (void (*)()) fix_display;
632 sigaction(SIGALRM, &act, NULL);
633 input("Enter family Name:", buf, LAST_NAME_SIZE + 1,
634 LASTNAME_TIMEOUT, FALSE);
635 strncpy(user.u_last, buf, LAST_NAME_SIZE);
636 user.u_last[LAST_NAME_SIZE - 1] = '\0';
637 canon_name(user.u_last);
644 char new_password[PASSWORD_SIZE + 1];
645 struct sigaction act;
647 sigemptyset(&act.sa_mask);
649 act.sa_handler = (void (*)()) fix_display;
650 sigaction(SIGALRM, &act, NULL);
651 input_no_echo("Enter password:", new_password,
652 PASSWORD_SIZE, NEW_PASSWORD_TIMEOUT);
653 strcpy(user.u_password, new_password);
662 char buf[LOGIN_SIZE + 2];
663 struct sigaction act;
665 sigemptyset(&act.sa_mask);
667 act.sa_handler = (void (*)()) fix_display;
668 sigaction(SIGALRM, &act, NULL);
669 user.u_login[0] = '\0';
670 input("Enter username:", buf, LOGIN_SIZE, USERNAME_TIMEOUT, FALSE);
671 strcpy(user.u_login, buf);
680 register char *nbuf = buf;
681 struct sigaction act;
684 sigemptyset(&act.sa_mask);
686 act.sa_handler = (void (*)()) fix_display;
687 sigaction(SIGALRM, &act, NULL);
688 input("Enter MIT Id:", buf, 14, MITID_TIMEOUT, FALSE);
693 if (*nbuf == ' ' || *nbuf == '-')
703 typed_mit_id[i] = *nbuf;
709 display_text_line("Your MIT id must be a nine-digit number. "
710 "Please try again.");
713 typed_mit_id[9] = '\0';
715 EncryptID(user.u_mit_id, typed_mit_id, user.u_first, user.u_last);
720 /* get middle initial */
721 char buf[MID_INIT_SIZE + 2];
722 struct sigaction act;
724 sigemptyset(&act.sa_mask);
726 act.sa_handler = (void (*)()) fix_display;
727 sigaction(SIGALRM, &act, NULL);
728 input("Enter Middle Initial:", buf, MID_INIT_SIZE + 1, MI_TIMEOUT, TRUE);
729 strncpy(user.u_mid_init, buf, MID_INIT_SIZE);
730 user.u_mid_init[MID_INIT_SIZE - 1] = '\0';
731 canon_name(user.u_mid_init);
737 /* exit quickly, not saving anything in the database */
738 memset(&user, 0, sizeof(user));
739 typed_mit_id[0] = '\0';
741 already_registered = 0;
743 sleep(2); /* give the user a chance to see the screen */
744 display_text_line(0);
755 * replaces a user in the database. If there is an error, it informs
756 * the user and calls qexit(); It returns only if is is successful
761 status = set_password(user.u_first, user.u_last, typed_mit_id,
762 user.u_mit_id, user.u_password);
766 status = get_krb(user.u_first, user.u_last, typed_mit_id,
767 user.u_mit_id, user.u_password);
773 display_text(NETWORK_DOWN);
774 display_text_line(" ");
775 sprintf(buf, "The specific error was: %s", error_message(status));
776 display_text_line(buf);
785 int kinit(char *user, char *passwd)
791 status = krb_get_pw_in_tkt(user, inst, realm, "krbtgt",
792 realm, DEFAULT_TKT_LIFE, 0);
798 #define _toupper(c) ((c) & ~0x20)
801 int lenient_strcmp(register char *string1, register char *string2)
804 * a primitive case insensitive string comparison. It returns only 0
805 * if the strings are equal (ignoring case) and 1 if they are
806 * different. Also ignores spaces.
811 if (*string1 == '\0' && *string2 == '\0')
813 if (*string1 == ' ' || *string1 == '.' || *string1 == '-' ||
814 *string1 == '\'' || *string1 == '_')
819 if (*string2 == ' ' || *string2 == '.' || *string2 == '-' ||
820 *string2 == '\'' || *string2 == '_')
825 if (_toupper(*string1) != _toupper(*string2))
833 /* See if the strings match in forward & reverse direction, ignoring
834 * case and spaces/punctuation.
837 int strpasscmp(char *s1, char *s2)
839 char buf[256], *from, *to;
841 if (!lenient_strcmp(s1, s2))
843 /* if s2 is empty, say OK */
847 from = &s2[strlen(s2)];
849 for (to = &buf[0]; from >= s2; from--)
852 return lenient_strcmp(s1, buf);
857 * Input timeout handler. Loop back to asking for the first name.
860 /* Go to asking for first name. */
867 canon_name(register char *cp)
869 register char *p2 = cp;
871 /* Trim whitespace off both ends. */
872 for (; *p2 && isspace(*p2); p2++)
877 p2 = cp + strlen(cp);
879 while (p2 >= cp && isspace(*p2))
882 /* Make it capitalized */