]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
66c74caa6a8543d85fc9d140b59421733716f2d4
[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.5  1987-09-10 22:18:32  wesommer
15  *      Clean up output format.
16  *
17  * Revision 1.4  87/09/04  23:33:19  wesommer
18  * Deleted test scaffolding (second oops.)
19  * 
20  * Revision 1.3  87/09/03  03:05:18  wesommer
21  * Version used for userreg tests.
22  * 
23  * Revision 1.2  87/08/22  18:39:45  wesommer
24  * User registration server.
25  * 
26  * Revision 1.1  87/07/31  15:48:13  wesommer
27  * Initial revision
28  * 
29  */
30
31 #ifndef lint
32 static 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"
47 #include "admin_server.h"
48 #include "admin_err.h" 
49 #include <strings.h>
50
51 extern void abort();
52 extern char *strdup();
53 extern char *malloc();
54 extern int krb_err_base;
55 extern char admin_errmsg[];
56
57 long now;
58                        
59 struct msg {
60     u_long version;
61     u_long request;
62     char *first;
63     char *last;
64     char *sealed;
65     int sealed_len;
66 };
67
68 static char retval[BUFSIZ];
69
70 main()
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;
81     extern char *whoami;
82     int i;
83     
84     setlinebuf(stderr);
85     whoami = "reg_svr";
86     
87     init_ureg_err_tbl();
88
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     }
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     }
120     
121     for (;;) {
122         com_err("reg_svr", 0, "Ready for next request");
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
163 int got_one;
164 int reg_status;
165 char *mit_id;
166 char *reg_misc;
167 int reg_misc_len;
168 int user_id;
169
170 #define min(a,b) ((a)>(b)?(b):(a))
171     
172 int 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;
179     static char decrypt[BUFSIZ];
180     char recrypt[14];
181     static char hashid[14];
182     char idnumber[BUFSIZ];
183     char *temp;
184     int len;
185
186     int i;
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
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;
208     return 0;
209 }
210
211 static int status_in_db;
212
213 vfy_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     
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 */
232
233     status_in_db = atoi(argv[7]);
234     reg_status = status_in_db;    
235
236     if (status_in_db != 0) {
237         (void) strcpy(retval, argv[0]);
238     }
239     user_id = atoi(argv[1]);
240     got_one = 1;
241     return 0;
242 }    
243
244 encrypt_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
259 int verify_user(message)
260     struct msg *message;
261
262 {
263     char *argv[3];
264     int status;
265     
266     com_err("reg_svr", 0, " verify_user %s %s\n",
267             message->first, message->last);
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
281     if (reg_status == 1) status = UREG_ALREADY_REGISTERED;
282     if (reg_status == 2) status = UREG_NO_PASSWD_YET;
283     
284 punt:
285     return status;
286 }
287
288 reserve_user(message)
289     struct msg *message;
290 {
291     char *argv[3];
292     int status;
293     int i;
294     char *login;
295     char uid_buf[20];
296     
297     com_err("reg_svr", 0, " reserve_user %s %s\n",
298             message->first, message->last);
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;
304     
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) {
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;
321         goto punt;
322     }
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 */
337     /* get keys */
338     status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
339                             "changepw", "kerberos",
340                             1, "/etc/srvtab");
341     if (status) {
342             status += krb_err_base;
343             goto punt;
344     }
345     
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);
352
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: */
366     
367     /* Set login name */
368     status = set_login(login, mit_id);
369
370     
371     if (status) {
372         com_err("set_login", status, 0);
373         goto punt;
374     }
375     /* choose post office */
376     
377     status = choose_pobox(login);
378     if (status) {
379         com_err("choose_pobox", status, 0);
380         goto punt;
381     }
382     /* create group */
383     
384     status = create_group(login);
385     if (status == SMS_LIST) status = UREG_LOGIN_USED;
386     
387     if (status) {
388         com_err("create_group", status, 0);
389         goto punt;
390     }
391     /* set quota entry, create filsys */
392     
393     status = alloc_filsys(login, SMS_FS_STUDENT, 0, 0);
394     if (status == SMS_FILESYS_EXISTS) status = UREG_LOGIN_USED;
395     if (status) {
396         com_err("alloc_filsys", status, 0);
397         goto punt;
398     }
399     /* set filsys and status in SMS database */
400     
401     status = set_status_filsys(reg_misc, mit_id);
402     if (status) {
403         com_err("set_filsys", status, 0);
404         goto punt;
405     }
406 punt:
407     dest_tkt();
408
409     com_err("reg_svr", status, " returned from reserve_user");
410     return status;
411 }
412
413 set_password(message)
414     struct msg *message;
415 {
416     char *argv[3];
417     int status;
418     char uid_buf[10];
419     
420     com_err("reg_svr", 0, " set_password %s %s\n",
421             message->first, message->last);
422
423     /* validate that user is who he claims to be */
424
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;
435     
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;
443     }
444
445     /* get keys */
446     status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
447                             "changepw", "kerberos",
448                             1, "/etc/srvtab");
449     if (status) {
450             status += krb_err_base;
451             goto punt;
452     }
453
454     (void) sprintf(uid_buf, "%013d", user_id); /* 13 chars of placebo */
455                                                /* for backwards-compat. */
456     /* send set password request to kerberos admin_server */
457     status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, retval, "", 
458                         reg_misc, uid_buf);
459
460     if (status) goto punt;
461     dest_tkt();
462     
463     status = set_final_status(retval, mit_id);
464
465     /* reflect reply to client */
466 punt:
467     dest_tkt();
468     return status;
469 }
470
471 parse_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
519 format_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
537 store_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
560 set_login(username, idnumber)
561     char *username;
562     char *idnumber;
563 {
564     char *argv[2];
565     int status, i;
566     char *retv[13];
567     
568     argv[0] = "get_user_by_mitid";
569     argv[1] = idnumber;
570
571     for (i=0; i<13; i++) {
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;
580     if (retv[4]) free(retv[4]);
581     retv[4] = "null";           /* No such filesystem */
582     
583     printf("Update_user(%s, %s)\n", retv[0], retv[1]);
584     
585     status = sms_query("update_user", 12, retv, abort, 0);
586     retv[1] = 0;
587     retv[4] = 0;
588     
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
601 set_status_filsys(username, idnumber)
602     char *username;
603     char *idnumber;
604 {
605     char *argv[2];
606     int status, i;
607     char *retv[13];
608     
609     argv[0] = "get_user_by_mitid";
610     argv[1] = idnumber;
611
612     for (i=0; i<13; i++) {
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 }    
638 /*
639  * Set the status and filsys of user with username "uname" and filesys filsys.
640  */
641
642 set_final_status(username, idnumber)
643     char *username;
644     char *idnumber;
645 {
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;
655     }
656
657     status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
658     if (status) return status;
659
660     retv[0] = retv[1];
661
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
676 create_group(login)
677     char *login;
678 {
679     int status;
680     static char *cr[] = {
681         "add_user_group",
682         0,
683     };
684     
685     cr[1] = login;
686     
687     return sms_query_internal(2, cr, abort, 0);
688 }    
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  */
699
This page took 0.076848 seconds and 3 git commands to generate.