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