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