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