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