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