]> andersk Git - moira.git/blame - clients/userreg/userreg.c
Allow numbers, '_' and '.' in usernames.
[moira.git] / clients / userreg / userreg.c
CommitLineData
989a2c2c 1/*
569ee3f8 2 * $Source$
3 * $Author$
4 * $Locker$
5 * $Header$
989a2c2c 6 */
7
8#ifndef lint
569ee3f8 9static char *rcsid_userreg_c = "$Header$";
989a2c2c 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>
6f742fd0 17#include <ctype.h>
18#include "ureg_err.h"
19#include <krb.h>
20#include <errno.h>
989a2c2c 21#define EXIT -1
22
23
569ee3f8 24struct user user, db_user;
25struct alias alias;
26char typed_mit_id[100];
989a2c2c 27
569ee3f8 28jmp_buf redo;
29int restart();
989a2c2c 30
569ee3f8 31extern int errno;
32int user_is_valid = 0;
6f742fd0 33int user_has_login = 0;
569ee3f8 34int already_registered = 0;
989a2c2c 35
569ee3f8 36fix_display(sig)
989a2c2c 37{
569ee3f8 38 signal(sig, SIG_IGN); /* let us clean up, please */
989a2c2c 39 noraw();
40 echo();
41 endwin();
569ee3f8 42 exit(1);
989a2c2c 43}
44
569ee3f8 45main(argc, argv)
46 int argc;
47 char **argv;
989a2c2c 48{
569ee3f8 49 register int ntimes;
50 register int reencrypt;
51 char line[100];
6f742fd0 52 int status;
c16914a2 53 char tmpfirst[100], tmplast[100], tmpmid[100];
6f742fd0 54
55 status = ureg_init();
56 if (status) {
57 com_err(argv[0], status, "while trying to initialize");
58 exit(1);
59 }
569ee3f8 60
61 setup_display();
62
63 signal(SIGINT, fix_display);
64 signal(SIGQUIT, fix_display);
65 signal(SIGHUP, fix_display);
66
67 do {
c16914a2 68
569ee3f8 69 setjmp(redo);
70 reset();
71 ntimes = 0;
72
73 display_text(WELCOME);
74
75 gfirst();
76 gmi();
77 glast();
c16914a2 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
569ee3f8 83 gmitid();
c16914a2 84
569ee3f8 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();
c16914a2 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();
569ee3f8 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();
c16914a2 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();
569ee3f8 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();
6f742fd0 149 if (!user_has_login) {
150 if (negotiate_login() == -1) {
151 qexit();
152 continue;
153 }
154 }
155 if (negotiate_passwd() == -1) {
569ee3f8 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.");
c16914a2 166 display_text_line("");
167 display_text_line("Your account should be created within about 12 hours\n");
168
569ee3f8 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);
989a2c2c 176}
177
569ee3f8 178reset()
179{
180 reset_display();
181 bzero(&user, sizeof(user));
182 user_is_valid = 0;
183 already_registered = 0;
184 redisp();
989a2c2c 185}
186
569ee3f8 187dolook()
188{
189 /* do the database lookup */
989a2c2c 190
569ee3f8 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.");
6f742fd0 200
c16914a2 201 timer_off();
6f742fd0 202 result = verify_user(user.u_first, user.u_last,
203 typed_mit_id, user.u_mit_id, db_user.u_login);
c16914a2 204 timer_on();
6f742fd0 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);
c16914a2 244
6f742fd0 245 case ECONNREFUSED:
c16914a2 246 case ETIMEDOUT:
569ee3f8 247 display_text(NETWORK_DOWN);
6f742fd0 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();
569ee3f8 254 sleep(5);
6f742fd0 255 return(1);
989a2c2c 256 }
989a2c2c 257}
258
6f742fd0 259negotiate_login()
569ee3f8 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];
6f742fd0 266 int i;
c16914a2 267 char *cp;
6f742fd0 268
569ee3f8 269 display_text(USERNAME_BLURB);
c16914a2 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
6f742fd0 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
569ee3f8 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(
6f742fd0 290 "a different one, but remember that it will remain with you for all the ");
291 display_text_line("time you are at MIT.");
569ee3f8 292
569ee3f8 293 while (1) {
294 glogin();
6f742fd0 295
569ee3f8 296 display_text_line(0);
297 display_text_line("Looking up that username in the database... This may take a few minutes.");
c16914a2 298 timer_off();
6f742fd0 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", "");
c16914a2 305 timer_on();
6f742fd0 306 if (result != KDC_PR_UNKNOWN) {
307 in_use:
569ee3f8 308 strcpy(user.u_login, old_login);
309 redisp();
6f742fd0 310 display_text_line("I'm sorry, but that username is already taken. Please try again with a different username");
569ee3f8 311 continue;
569ee3f8 312 }
c16914a2 313
6f742fd0 314 /*
315 * If he isn't, let's try through SMS.
316 */
c16914a2 317 timer_off();
6f742fd0 318 result = grab_login(user.u_first, user.u_last,
319 typed_mit_id, user.u_mit_id,
320 user.u_login);
c16914a2 321 timer_on();
6f742fd0 322 if (result != 0) {
323 if (result == UREG_LOGIN_USED) goto in_use;
324 display_text(NETWORK_DOWN);
325 return (qexit());
326 } else break;
569ee3f8 327 }
569ee3f8 328 /* at this point we have successfully negotiated a username */
329
6f742fd0 330 sprintf(line, "O.K. your username will be \"%s\".", user.u_login);
569ee3f8 331 display_text_line(0);
332 display_text_line(line);
333 redisp();
334 sleep(3);
6f742fd0 335 return 0;
336}
337negotiate_passwd()
338{
569ee3f8 339 display_text_line(0);
340 display_text(PASSWORD_BLURB);
6f742fd0 341
569ee3f8 342 gpass();
6f742fd0 343 display_text_line("Storing password in the database... This may take a few minutes.");
569ee3f8 344 if (do_replace()) {
345 return (-1);
346 }
347 display_text_line("done.");
6f742fd0 348
989a2c2c 349}
350
569ee3f8 351gfirst()
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';
6f742fd0 360 canon_name(user.u_first);
569ee3f8 361 redisp();
362}
989a2c2c 363
569ee3f8 364glast()
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';
6f742fd0 373 canon_name(user.u_last);
569ee3f8 374 redisp();
989a2c2c 375}
376
569ee3f8 377gpass()
378{
379 /* input password */
380 char old_password[PASSWORD_SIZE];
381 char new_password[PASSWORD_SIZE];
382 char new_password_again[PASSWORD_SIZE];
383
569ee3f8 384do_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 }
569ee3f8 400
6f742fd0 401 strcpy(user.u_password, new_password);
569ee3f8 402 redisp();
989a2c2c 403}
404
569ee3f8 405glogin()
406{
407 /* get login name */
408 register int i;
409 char buf[100];
410 register char *nbuf = buf;
411
412input_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') {
22c45376 419 if (!islower(*nbuf) && !isdigit(*nbuf)
420 && (*nbuf != '_') && (*nbuf != '.')) {
569ee3f8 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 }
c16914a2 434 if (strlen(user.u_login) < 3) {
435 display_text_line("Your username must be 3 or more characters long.\n");
569ee3f8 436 goto input_login;
437 }
569ee3f8 438 redisp();
989a2c2c 439}
440
569ee3f8 441gmitid()
442{
443 /* get mid id */
444 register int i;
445 char buf[100];
446 register char *nbuf = buf;
447
448input_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();
989a2c2c 474}
475
569ee3f8 476encrypt_mitid()
477{
478 char salt[3];
989a2c2c 479
569ee3f8 480 make_salt(salt, user.u_first, user.u_last);
481 strcpy(user.u_mit_id, crypt(&typed_mit_id[2], salt));
989a2c2c 482}
483
484
485#define _tolower(c) ((c)|0x60)
486
569ee3f8 487make_salt(salt, first, last)
488 char *salt, *first, *last;
989a2c2c 489{
569ee3f8 490 salt[0] = _tolower(last[0]);
491 salt[1] = _tolower(first[0]);
989a2c2c 492}
493
494
569ee3f8 495gmi()
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';
6f742fd0 504 canon_name(user.u_mid_init);
569ee3f8 505 redisp();
989a2c2c 506}
507
569ee3f8 508qexit()
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);
989a2c2c 518}
519
520
569ee3f8 521do_replace()
522{
6f742fd0 523 int status;
524
569ee3f8 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 */
c16914a2 529 timer_off();
6f742fd0 530 status = set_password(user.u_first, user.u_last, typed_mit_id,
c16914a2 531 user.u_mit_id, user.u_password);
532 timer_on();
6f742fd0 533 if (status) {
534 display_text (NETWORK_DOWN);
569ee3f8 535 return (-1);
6f742fd0 536 } else return 0;
989a2c2c 537}
538
539#define _toupper(c) ((c) & ~0x20)
540
569ee3f8 541lenient_strcmp(string1, string2)
542 register char *string1, *string2;
989a2c2c 543{
569ee3f8 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 }
989a2c2c 568}
569
569ee3f8 570/*
571 * Input timeout handler. Loop back to asking for the first name.
989a2c2c 572 */
573
574restart()
575/* Go to asking for first name. */
576{
569ee3f8 577 qexit();
578 longjmp(redo);
989a2c2c 579}
6f742fd0 580
581canon_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.144591 seconds and 5 git commands to generate.