]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
Kludge for use with SMS>
[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.2  1987-08-22 18:39:45  wesommer
15  *      User registration server.
16  *
17  * Revision 1.1  87/07/31  15:48:13  wesommer
18  * Initial revision
19  * 
20  */
21
22 #ifndef lint
23 static 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"
38 #include "admin_server.h"
39 #include "admin_err.h" 
40 #include <strings.h>
41
42 extern void abort();
43 extern char *strdup();
44 extern char *malloc();
45 extern int krb_err_base;
46 extern char admin_errmsg[];
47
48 long now;
49 #define STAMP { time (&now); printf(ctime(&now)); }
50                        
51 struct msg {
52     u_long version;
53     u_long request;
54     char *first;
55     char *last;
56     char *sealed;
57     int sealed_len;
58 };
59
60 static char retval[BUFSIZ];
61
62 main()
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;
73     extern char *whoami;
74
75     setlinebuf(stderr);
76     whoami = "reg_svr";
77     
78     init_ureg_err_tbl();
79     
80     status = sms_connect();
81     if (status != 0) {
82         com_err("reg_svr", status, " on connect");
83         exit(1);
84     }
85     status = sms_auth();
86     if (status != 0) {
87         com_err("reg_svr", status, " on auth");
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
153 int got_one;
154 int reg_status;
155 char *mit_id;
156 char *reg_misc;
157 int reg_misc_len;
158 int user_id;
159
160 #define min(a,b) ((a)>(b)?(b):(a))
161     
162 int 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;
169     static char decrypt[BUFSIZ];
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;
216     return 0;
217 }
218
219 static int status_in_db;
220
221 vfy_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     
231 #ifdef debug
232     printf("Callback: %s %s %s\n", argv[8], argv[5], argv[4]);
233 #endif debug
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 */
243
244     status_in_db = atoi(argv[7]);
245     reg_status = status_in_db;    
246
247     if (status_in_db != 0) {
248         (void) strcpy(retval, argv[0]);
249     }
250     user_id = atoi(argv[1]);
251     got_one = 1;
252     return 0;
253 }    
254
255 encrypt_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
270 int 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
291     if (reg_status == 1) status = UREG_ALREADY_REGISTERED;
292     if (reg_status == 2) status = UREG_NO_PASSWD_YET;
293     
294 punt:
295     return status;
296 }
297
298 reserve_user(message)
299     struct msg *message;
300 {
301     char *argv[3];
302     int status;
303     int i;
304     char *login;
305     char uid_buf[20];
306     
307     STAMP;
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;
314     
315     status = sms_query_internal(3, argv, vfy_callbk, (char *)message);
316
317     STAMP;
318     
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) {
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;
333         goto punt;
334     }
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 */
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);
369
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;
384     
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     }
391     /* choose post office */
392     STAMP;
393     
394     status = choose_pobox(login);
395     if (status) {
396         com_err("choose_pobox", status, 0);
397         goto punt;
398     }
399     /* set quota entry, create filsys */
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     }
415     /* set filsys and status in SMS database */
416     STAMP;
417     
418     status = set_status_filsys(reg_misc, mit_id);
419     if (status) {
420         com_err("set_filsys", status, 0);
421         goto punt;
422     }
423 punt:
424     dest_tkt();
425     STAMP;
426     printf("reserve_user returning %s\n", error_message(status));
427     return status;
428 }
429
430 set_password(message)
431     struct msg *message;
432 {
433     char *argv[3];
434     int status;
435     
436     printf("set_password\n");
437
438     /* validate that user is who he claims to be */
439
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;
450     
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;
458     }
459
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;
469     }
470     /* send set password request to kerberos admin_server */
471     status = admin_call(ADMIN_SET_KDC_PASSWORD, retval, "", 
472                         reg_misc, "BBBBBBBBBBBBB");
473
474     if (status) goto punt;
475     dest_tkt();
476     
477     status = set_final_status(retval, mit_id);
478
479     /* reflect reply to client */
480 punt:
481     dest_tkt();
482     return status;
483 }
484
485 parse_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
533 format_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
551 store_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
574 set_login(username, idnumber)
575     char *username;
576     char *idnumber;
577 {
578     char *argv[2];
579     int status, i;
580     char *retv[13];
581     
582     argv[0] = "get_user_by_mitid";
583     argv[1] = idnumber;
584
585     for (i=0; i<13; i++) {
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;
594     if (retv[4]) free(retv[4]);
595     retv[4] = "null";           /* No such filesystem */
596     
597     printf("Update_user(%s, %s)\n", retv[0], retv[1]);
598     
599     status = sms_query("update_user", 12, retv, abort, 0);
600     retv[1] = 0;
601     retv[4] = 0;
602     
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
615 set_status_filsys(username, idnumber)
616     char *username;
617     char *idnumber;
618 {
619     char *argv[2];
620     int status, i;
621     char *retv[13];
622     
623     argv[0] = "get_user_by_mitid";
624     argv[1] = idnumber;
625
626     for (i=0; i<13; i++) {
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 }    
652 /*
653  * Set the status and filsys of user with username "uname" and filesys filsys.
654  */
655
656 set_final_status(username, idnumber)
657     char *username;
658     char *idnumber;
659 {
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;
669     }
670
671     status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
672     if (status) return status;
673
674     retv[0] = retv[1];
675
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
690 create_group(login)
691     char *login;
692 {
693     int status;
694     static char *cr[] = {
695         "add_user_group",
696         0,
697     };
698     
699     cr[1] = login;
700     
701     return sms_query_internal(2, cr, abort, 0);
702 }    
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  */
713 char *get_krbhst(a1, a2)
714         char *a1;
715         char *a2;
716 {
717         strcpy(a1, "ICARUS.MIT.EDU");
718         return 0;
719 }
720
721 char *get_krbrlm(a1)
722         char *a1;
723 {
724         strcpy(a1, "ATHENA.MIT.EDU");
725         return 0;
726 }
727
This page took 0.101345 seconds and 5 git commands to generate.