]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
Allow numbers, _, and . as legal characters in the username.
[moira.git] / reg_svr / reg_svr.c
CommitLineData
47baf534 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
8 * Server for user registration with SMS and Kerberos.
9 *
10 * This program is a client of the SMS server and the Kerberos
11 * admin_server, and is a server for the userreg program.
12 *
13 * $Log$
daa8729d 14 * Revision 1.6 1987-09-21 15:19:11 wesommer
15 * Allow numbers, _, and . as legal characters in the username.
47baf534 16 *
daa8729d 17 * Revision 1.5 87/09/10 22:18:32 wesommer
18 * Clean up output format.
19 *
cf78096b 20 * Revision 1.4 87/09/04 23:33:19 wesommer
21 * Deleted test scaffolding (second oops.)
22 *
234087b5 23 * Revision 1.3 87/09/03 03:05:18 wesommer
24 * Version used for userreg tests.
25 *
78eff417 26 * Revision 1.2 87/08/22 18:39:45 wesommer
27 * User registration server.
28 *
f46fccfa 29 * Revision 1.1 87/07/31 15:48:13 wesommer
30 * Initial revision
31 *
47baf534 32 */
33
34#ifndef lint
35static char *rcsid_reg_svr_c = "$Header$";
36#endif lint
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <sys/file.h>
41#include <sys/socket.h>
42#include <netinet/in.h>
43#include <netdb.h>
44#include <des.h>
45#include <errno.h>
46#include <ctype.h>
47#include "ureg_err.h"
48#include "ureg_proto.h"
49#include "../../include/sms.h"
f46fccfa 50#include "admin_server.h"
51#include "admin_err.h"
47baf534 52#include <strings.h>
53
54extern void abort();
f46fccfa 55extern char *strdup();
56extern char *malloc();
57extern int krb_err_base;
58extern char admin_errmsg[];
47baf534 59
f46fccfa 60long now;
f46fccfa 61
47baf534 62struct msg {
63 u_long version;
64 u_long request;
65 char *first;
66 char *last;
67 char *sealed;
68 int sealed_len;
69};
70
71static char retval[BUFSIZ];
72
47baf534 73main()
74{
75 struct sockaddr_in sin;
76 struct servent *sp;
77 int s;
78 int status;
79 int addrlen, len;
80 char buf[BUFSIZ];
81 extern int errno;
82 u_long seqno;
83 struct msg message;
f46fccfa 84 extern char *whoami;
78eff417 85 int i;
86
f46fccfa 87 setlinebuf(stderr);
88 whoami = "reg_svr";
47baf534 89
90 init_ureg_err_tbl();
78eff417 91
47baf534 92 sp = getservbyname("sms_ureg", "udp");
93 if (sp == NULL) {
94 fprintf(stderr, "Unknown service sms_ureg/udp\n");
95 exit(1);
96 }
97 s = socket(AF_INET, SOCK_DGRAM, 0);
98 if (s < 0) {
99 perror("socket");
100 exit(1);
101 }
102 bzero((char *)&sin, sizeof(sin));
103
104 sin.sin_family = AF_INET;
105 sin.sin_port = sp->s_port;
106 sin.sin_addr.s_addr = INADDR_ANY;
107
108 if (bind(s, &sin, sizeof(sin)) < 0) {
109 perror("bind");
110 exit(1);
111 }
78eff417 112
113 status = sms_connect();
114 if (status != 0) {
115 com_err("reg_svr", status, " on connect");
116 exit(1);
117 }
118 status = sms_auth();
119 if (status != 0) {
120 com_err("reg_svr", status, " on auth");
121 exit(1);
122 }
47baf534 123
124 for (;;) {
cf78096b 125 com_err("reg_svr", 0, "Ready for next request");
47baf534 126 addrlen = sizeof(sin);
127 bzero(retval, BUFSIZ);
128 len = recvfrom(s, buf, BUFSIZ, 0, &sin, &addrlen);
129 if (len < 0) {
130 perror("recvfrom");
131 if (errno == EINTR) continue;
132
133 exit(1);
134 }
135 /* Parse a request packet */
136 status = parse_pkt(buf, len, &seqno, &message);
137 if (status != 0) {
138 len = BUFSIZ;
139 format_pkt(buf, &len, seqno, status, (char *)NULL);
140 (void) sendto(s, buf, len, 0, &sin, addrlen);
141 continue;
142 }
143 /* do action */
144 switch((int)message.request) {
145 case UREG_VERIFY_USER:
146 status = verify_user(&message);
147 break;
148 case UREG_RESERVE_LOGIN:
149 status = reserve_user(&message);
150 break;
151 case UREG_SET_PASSWORD:
152 status = set_password(&message);
153 break;
154
155 default:
156 status = UREG_UNKNOWN_REQUEST;
157 break;
158 }
159 len = BUFSIZ;
160 format_pkt(buf, &len, seqno, status, retval);
161
162 sendto(s, buf, len, 0, &sin, addrlen);
163 }
164}
165
47baf534 166int got_one;
167int reg_status;
168char *mit_id;
169char *reg_misc;
170int reg_misc_len;
f46fccfa 171int user_id;
172
47baf534 173#define min(a,b) ((a)>(b)?(b):(a))
174
175int validate_idno(message, db_mit_id, first, last)
176 struct msg *message;
177 char *db_mit_id;
178 char *first, *last;
179{
180 C_Block key;
181 Key_schedule sched;
f46fccfa 182 static char decrypt[BUFSIZ];
47baf534 183 char recrypt[14];
184 static char hashid[14];
185 char idnumber[BUFSIZ];
186 char *temp;
187 int len;
188
189 int i;
47baf534 190 mit_id = 0;
191
192 string_to_key(db_mit_id, key);
193 key_sched(key, sched);
194 pcbc_encrypt(message->sealed, decrypt, message->sealed_len, sched, key, 0);
195
47baf534 196 (void) strncpy(idnumber, decrypt, message->sealed_len);
197 temp = decrypt + strlen(idnumber) + 1;
198 len = message->sealed_len - (temp - decrypt);
199
200 (void) strncpy(hashid, temp, min(len, 14));
201 temp += strlen(hashid) + 1;
202 len = message->sealed_len - (temp - decrypt);
203
204 if (strcmp(hashid, db_mit_id)) return 1;
205 encrypt_mitid(recrypt, idnumber, first, last);
206 if (strcmp(recrypt, db_mit_id)) return 1;
207
208 reg_misc = temp;
209 reg_misc_len = len;
210 mit_id = hashid;
47baf534 211 return 0;
212}
213
f46fccfa 214static int status_in_db;
215
47baf534 216vfy_callbk(argc, argv, p_message)
217 int argc; /* Should sanity check this.. */
218 char **argv;
219 char *p_message;
220{
221 struct msg *message = (struct msg *)p_message;
222 char *db_mit_id;
223 char *firstname, *lastname;
224 int status;
225
47baf534 226 if (got_one) return 0;
227 reg_status = 0;
228
229 db_mit_id = argv[8];
230 firstname = argv[5];
231 lastname = argv[4];
232
233 status = validate_idno(message, db_mit_id, firstname, lastname);
234 if (status) return 0; /* Nope; decryption failed */
f46fccfa 235
236 status_in_db = atoi(argv[7]);
237 reg_status = status_in_db;
238
239 if (status_in_db != 0) {
47baf534 240 (void) strcpy(retval, argv[0]);
241 }
f46fccfa 242 user_id = atoi(argv[1]);
47baf534 243 got_one = 1;
244 return 0;
245}
246
247encrypt_mitid(buf, idnumber, first, last)
248 char *buf, *idnumber, *first, *last;
249{
250 char salt[3];
251 extern char *crypt();
252
253#define _tolower(c) ((c)|0x60)
254
255 salt[0] = _tolower(last[0]);
256 salt[1] = _tolower(first[0]);
257 salt[2] = 0;
258
259 (void) strcpy(buf, crypt(&idnumber[2], salt));
260}
261
262int verify_user(message)
263 struct msg *message;
264
265{
266 char *argv[3];
267 int status;
268
cf78096b 269 com_err("reg_svr", 0, " verify_user %s %s\n",
270 message->first, message->last);
47baf534 271 argv[0] = "get_user_by_first_and_last";
272 argv[1] = message->first;
273 argv[2] = message->last;
274 got_one = 0;
275
276 status = sms_query_internal(3, argv, vfy_callbk, (char *)message);
277
278 if (status == SMS_NO_MATCH) status = UREG_USER_NOT_FOUND;
279 if (!got_one && !status)
280 status = UREG_USER_NOT_FOUND;
281
282 if (status != 0) goto punt;
283
f46fccfa 284 if (reg_status == 1) status = UREG_ALREADY_REGISTERED;
285 if (reg_status == 2) status = UREG_NO_PASSWD_YET;
47baf534 286
287punt:
288 return status;
289}
290
291reserve_user(message)
292 struct msg *message;
293{
294 char *argv[3];
295 int status;
296 int i;
297 char *login;
f46fccfa 298 char uid_buf[20];
47baf534 299
cf78096b 300 com_err("reg_svr", 0, " reserve_user %s %s\n",
301 message->first, message->last);
47baf534 302
303 argv[0] = "gufl"; /* get_user_by_first_and_last */
304 argv[1] = message->first;
305 argv[2] = message->last;
306 got_one = 0;
f46fccfa 307
47baf534 308 status = sms_query_internal(3, argv, vfy_callbk, (char *)message);
309
310 if (status == SMS_NO_MATCH) status = UREG_USER_NOT_FOUND;
311 if (!got_one && !status)
312 status = UREG_USER_NOT_FOUND;
313
314 if (status != 0) goto punt;
315 if (reg_status != 0) {
f46fccfa 316 status = UREG_ALREADY_REGISTERED;
317 goto punt;
318 }
319 /*
320 * He's made it past this phase already.
321 */
322 if (status_in_db == 2) {
323 status = 0;
47baf534 324 goto punt;
325 }
47baf534 326
327 for (i = 0; i < reg_misc_len && reg_misc[i]; i++) {
daa8729d 328 if (!islower(reg_misc[i]) && !isdigit(reg_misc[i]) &&
329 reg_misc[i] != '_' && reg_misc[i] != '.') {
47baf534 330 status = UREG_INVALID_UNAME;
331 goto punt;
332 }
333 }
334 if (i < 3 || i > 8) {
335 status = UREG_INVALID_UNAME;
336 goto punt;
337 }
338 login = reg_misc;
339
340 /* Send request to kerberos admin_server for login name */
f46fccfa 341 /* get keys */
cf78096b 342 status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
f46fccfa 343 "changepw", "kerberos",
344 1, "/etc/srvtab");
345 if (status) {
346 status += krb_err_base;
347 goto punt;
348 }
f46fccfa 349
f46fccfa 350 /* send set password request to kerberos admin_server */
351 (void) sprintf(uid_buf, "%013d", user_id); /* 13 chars of placebo */
352 /* for backwards-compat. */
353
354 status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, login, "",
355 "", uid_buf);
47baf534 356
f46fccfa 357 if (status) {
358 if (status == ADMIN_SERVER_ERROR) {
359 printf("Server error: %s\n", admin_errmsg);
360
361 if (strcmp(admin_errmsg,
362 "Principal already in kerberos database.") ==0)
363 status = UREG_LOGIN_USED;
364 }
365 goto punt;
366 }
367
368 dest_tkt();
369 /* If valid: */
47baf534 370
f46fccfa 371 /* Set login name */
372 status = set_login(login, mit_id);
78eff417 373
374
f46fccfa 375 if (status) {
376 com_err("set_login", status, 0);
377 goto punt;
378 }
47baf534 379 /* choose post office */
f46fccfa 380
381 status = choose_pobox(login);
382 if (status) {
383 com_err("choose_pobox", status, 0);
384 goto punt;
385 }
78eff417 386 /* create group */
f46fccfa 387
78eff417 388 status = create_group(login);
389 if (status == SMS_LIST) status = UREG_LOGIN_USED;
390
f46fccfa 391 if (status) {
78eff417 392 com_err("create_group", status, 0);
f46fccfa 393 goto punt;
394 }
78eff417 395 /* set quota entry, create filsys */
f46fccfa 396
78eff417 397 status = alloc_filsys(login, SMS_FS_STUDENT, 0, 0);
398 if (status == SMS_FILESYS_EXISTS) status = UREG_LOGIN_USED;
f46fccfa 399 if (status) {
78eff417 400 com_err("alloc_filsys", status, 0);
f46fccfa 401 goto punt;
402 }
47baf534 403 /* set filsys and status in SMS database */
47baf534 404
f46fccfa 405 status = set_status_filsys(reg_misc, mit_id);
406 if (status) {
407 com_err("set_filsys", status, 0);
408 goto punt;
409 }
47baf534 410punt:
f46fccfa 411 dest_tkt();
cf78096b 412
413 com_err("reg_svr", status, " returned from reserve_user");
47baf534 414 return status;
415}
416
f46fccfa 417set_password(message)
418 struct msg *message;
47baf534 419{
f46fccfa 420 char *argv[3];
421 int status;
cf78096b 422 char uid_buf[10];
f46fccfa 423
cf78096b 424 com_err("reg_svr", 0, " set_password %s %s\n",
425 message->first, message->last);
47baf534 426
f46fccfa 427 /* validate that user is who he claims to be */
47baf534 428
f46fccfa 429 argv[0] = "get_user_by_first_and_last";
430 argv[1] = message->first;
431 argv[2] = message->last;
432 got_one = 0;
433
434 status = sms_query_internal(3, argv, vfy_callbk, (char *)message);
435
436 if (status == SMS_NO_MATCH) status = UREG_USER_NOT_FOUND;
437 if (!got_one && !status)
438 status = UREG_USER_NOT_FOUND;
47baf534 439
f46fccfa 440 if (status != 0) goto punt;
441
442 /* validate that state is equal to '2' (login, but no password) */
443
444 if (reg_status != 2) {
445 status = UREG_NO_LOGIN_YET;
446 goto punt;
47baf534 447 }
47baf534 448
f46fccfa 449 /* get keys */
cf78096b 450 status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
f46fccfa 451 "changepw", "kerberos",
452 1, "/etc/srvtab");
453 if (status) {
454 status += krb_err_base;
455 goto punt;
47baf534 456 }
cf78096b 457
458 (void) sprintf(uid_buf, "%013d", user_id); /* 13 chars of placebo */
459 /* for backwards-compat. */
f46fccfa 460 /* send set password request to kerberos admin_server */
cf78096b 461 status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, retval, "",
462 reg_misc, uid_buf);
47baf534 463
f46fccfa 464 if (status) goto punt;
465 dest_tkt();
47baf534 466
f46fccfa 467 status = set_final_status(retval, mit_id);
468
469 /* reflect reply to client */
470punt:
471 dest_tkt();
47baf534 472 return status;
473}
474
47baf534 475parse_pkt(buf, len, seqnop, messagep)
476 char *buf;
477 int len;
478 u_long *seqnop;
479 struct msg *messagep;
480{
481 if (len < 4) return UREG_BROKEN_PACKET;
482 bcopy(buf, (char *)&messagep->version, sizeof(long));
483 messagep->version = ntohl(messagep->version);
484 if (messagep->version != 1) return UREG_WRONG_VERSION;
485
486 buf += 4;
487 len -= 4;
488
489 if (len < 4) return UREG_BROKEN_PACKET;
490 bcopy(buf, (char *)seqnop, sizeof(long));
491
492 buf += 4;
493 len -= 4;
494
495 if (len < 4) return UREG_BROKEN_PACKET;
496 bcopy(buf, (char *)(&messagep->request), sizeof(long));
497 messagep->request = ntohl(messagep->request);
498 buf += 4;
499 len -= 4;
500
501 messagep->first = buf;
502
503 for (; *buf && len > 0; --len, ++buf) continue;
504 if (len <= 0) return UREG_BROKEN_PACKET;
505
506 buf++, len--;
507
508 messagep->last = buf;
509
510 for (; *buf && len > 0; --len, ++buf) continue;
511 if (len <= 0) return UREG_BROKEN_PACKET;
512
513 buf++, len--;
514
515 if (len <= 0) return UREG_BROKEN_PACKET;
516
517 messagep->sealed = buf;
518 messagep->sealed_len = len;
519
520 return 0;
521}
522
523format_pkt(buf, lenp, seqno, status, message)
524 char *buf;
525 int *lenp;
526 u_long seqno;
527 int status;
528 char *message;
529{
530 u_long vers = htonl((u_long)1);
531 status = htonl((u_long)status);
532
533 bcopy((char *)&vers, buf, sizeof(long));
534 bcopy((char *)&seqno, buf+sizeof(long), sizeof(long));
535 bcopy((char *)&status, buf+ 2*sizeof(long), sizeof(long));
536 *lenp = sizeof(long) * 3;
537 (void) strcpy(buf+3*sizeof(long), message);
538 (*lenp) += strlen(message);
539}
540
541store_user(argc, argv, argp)
542 int argc;
543 char **argv;
544 char *argp;
545{
546 char **retv = (char **) argp;
547 int i;
548
549 for (i = 0; i < argc; i++) {
550 if (retv[i]) {
551 free(retv[i]);
552 retv[i]=0;
553 }
554 retv[i] = strdup(argv[i]);
555 }
556 return 0;
557}
558
559
560/*
561 * Set login name of user with "idnumber" to be "username"
562 */
563
564set_login(username, idnumber)
565 char *username;
566 char *idnumber;
567{
568 char *argv[2];
569 int status, i;
f46fccfa 570 char *retv[13];
47baf534 571
572 argv[0] = "get_user_by_mitid";
573 argv[1] = idnumber;
574
f46fccfa 575 for (i=0; i<13; i++) {
47baf534 576 retv[i] = 0;
577 }
578
579 status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
580 if (status) return status;
581
582 retv[0] = retv[1];
583 retv[1] = username;
f46fccfa 584 if (retv[4]) free(retv[4]);
585 retv[4] = "null"; /* No such filesystem */
47baf534 586
587 printf("Update_user(%s, %s)\n", retv[0], retv[1]);
588
589 status = sms_query("update_user", 12, retv, abort, 0);
f46fccfa 590 retv[1] = 0;
591 retv[4] = 0;
592
47baf534 593 for (i=1; i<12; i++) {
594 if (retv[i]) free(retv[i]);
595 retv[i] = 0;
596 }
597
598 return status;
599}
600
601/*
602 * Set the status and filsys of user with username "uname" and filesys filsys.
603 */
604
605set_status_filsys(username, idnumber)
606 char *username;
607 char *idnumber;
608{
609 char *argv[2];
610 int status, i;
f46fccfa 611 char *retv[13];
47baf534 612
613 argv[0] = "get_user_by_mitid";
614 argv[1] = idnumber;
615
f46fccfa 616 for (i=0; i<13; i++) {
47baf534 617 retv[i] = 0;
618 }
619
620 status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
621 if (status) return status;
622
623 retv[0] = retv[1];
624
625 free(retv[4]);
626 retv[4] = username;
627
628 free(retv[8]);
629 retv[8] = "2";
630
631 printf("Update_user(%s, %s)\n", retv[0], retv[1]);
632
633 status = sms_query("update_user", 12, retv, abort, 0);
634 retv[4] = 0;
635 retv[8] = 0;
636 for (i=1; i<12; i++) {
637 if (retv[i]) free(retv[i]);
638 retv[i] = 0;
639 }
640 return status;
641}
f46fccfa 642/*
643 * Set the status and filsys of user with username "uname" and filesys filsys.
644 */
47baf534 645
f46fccfa 646set_final_status(username, idnumber)
647 char *username;
648 char *idnumber;
47baf534 649{
f46fccfa 650 char *argv[2];
651 int status, i;
652 char *retv[13];
653
654 argv[0] = "get_user_by_mitid";
655 argv[1] = idnumber;
656
657 for (i=0; i<13; i++) {
658 retv[i] = 0;
47baf534 659 }
47baf534 660
f46fccfa 661 status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
662 if (status) return status;
663
664 retv[0] = retv[1];
47baf534 665
f46fccfa 666 free(retv[8]);
667 retv[8] = "1";
668
669 printf("Update_user(%s, %s)\n", retv[0], retv[1]);
670
671 status = sms_query("update_user", 12, retv, abort, 0);
672 retv[8] = 0;
673 for (i=1; i<12; i++) {
674 if (retv[i]) free(retv[i]);
675 retv[i] = 0;
676 }
677 return status;
678}
679
680create_group(login)
47baf534 681 char *login;
682{
47baf534 683 int status;
f46fccfa 684 static char *cr[] = {
685 "add_user_group",
686 0,
687 };
47baf534 688
f46fccfa 689 cr[1] = login;
47baf534 690
f46fccfa 691 return sms_query_internal(2, cr, abort, 0);
692}
47baf534 693/*
694 * Local Variables:
695 * mode: c
696 * c-indent-level: 4
697 * c-continued-statement-offset: 4
698 * c-brace-offset: -4
699 * c-argdecl-indent: 4
700 * c-label-offset: -4
701 * End:
702 */
f46fccfa 703
This page took 0.278496 seconds and 5 git commands to generate.