]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
Moved header file locations
[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.7  1988-02-08 15:08:15  mar
15  *      Moved header file locations
16  *
17  * Revision 1.6  87/09/21  15:19:11  wesommer
18  * Allow numbers, _, and . as legal characters in the username.
19  * 
20  * Revision 1.5  87/09/10  22:18:32  wesommer
21  * Clean up output format.
22  * 
23  * Revision 1.4  87/09/04  23:33:19  wesommer
24  * Deleted test scaffolding (second oops.)
25  * 
26  * Revision 1.3  87/09/03  03:05:18  wesommer
27  * Version used for userreg tests.
28  * 
29  * Revision 1.2  87/08/22  18:39:45  wesommer
30  * User registration server.
31  * 
32  * Revision 1.1  87/07/31  15:48:13  wesommer
33  * Initial revision
34  * 
35  */
36
37 #ifndef lint
38 static 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"
52 #include "sms.h"
53 #include "admin_server.h"
54 #include "admin_err.h"
55 #include <strings.h>
56
57 extern void abort();
58 extern char *strdup();
59 extern char *malloc();
60 extern int krb_err_base;
61 extern char admin_errmsg[];
62
63 long now;
64                        
65 struct msg {
66     u_long version;
67     u_long request;
68     char *first;
69     char *last;
70     char *sealed;
71     int sealed_len;
72 };
73
74 static char retval[BUFSIZ];
75
76 main()
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;
87     extern char *whoami;
88     int i;
89     
90     setlinebuf(stderr);
91     whoami = "reg_svr";
92     
93     init_ureg_err_tbl();
94
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     }
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     }
126     
127     for (;;) {
128         com_err("reg_svr", 0, "Ready for next request");
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
169 int got_one;
170 int reg_status;
171 char *mit_id;
172 char *reg_misc;
173 int reg_misc_len;
174 int user_id;
175
176 #define min(a,b) ((a)>(b)?(b):(a))
177     
178 int 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;
185     static char decrypt[BUFSIZ];
186     char recrypt[14];
187     static char hashid[14];
188     char idnumber[BUFSIZ];
189     char *temp;
190     int len;
191
192     int i;
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
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;
214     return 0;
215 }
216
217 static int status_in_db;
218
219 vfy_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     
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 */
238
239     status_in_db = atoi(argv[7]);
240     reg_status = status_in_db;    
241
242     if (status_in_db != 0) {
243         (void) strcpy(retval, argv[0]);
244     }
245     user_id = atoi(argv[1]);
246     got_one = 1;
247     return 0;
248 }    
249
250 encrypt_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
265 int verify_user(message)
266     struct msg *message;
267
268 {
269     char *argv[3];
270     int status;
271     
272     com_err("reg_svr", 0, " verify_user %s %s\n",
273             message->first, message->last);
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
287     if (reg_status == 1) status = UREG_ALREADY_REGISTERED;
288     if (reg_status == 2) status = UREG_NO_PASSWD_YET;
289     
290 punt:
291     return status;
292 }
293
294 reserve_user(message)
295     struct msg *message;
296 {
297     char *argv[3];
298     int status;
299     int i;
300     char *login;
301     char uid_buf[20];
302     
303     com_err("reg_svr", 0, " reserve_user %s %s\n",
304             message->first, message->last);
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;
310     
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) {
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;
327         goto punt;
328     }
329
330     for (i = 0; i < reg_misc_len && reg_misc[i]; i++) {
331         if (!islower(reg_misc[i]) && !isdigit(reg_misc[i]) &&
332             reg_misc[i] != '_' && reg_misc[i] != '.') {
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 */
344     /* get keys */
345     status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
346                             "changepw", "kerberos",
347                             1, "/etc/srvtab");
348     if (status) {
349             status += krb_err_base;
350             goto punt;
351     }
352     
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);
359
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: */
373     
374     /* Set login name */
375     status = set_login(login, mit_id);
376
377     
378     if (status) {
379         com_err("set_login", status, 0);
380         goto punt;
381     }
382     /* choose post office */
383     
384     status = choose_pobox(login);
385     if (status) {
386         com_err("choose_pobox", status, 0);
387         goto punt;
388     }
389     /* create group */
390     
391     status = create_group(login);
392     if (status == SMS_LIST) status = UREG_LOGIN_USED;
393     
394     if (status) {
395         com_err("create_group", status, 0);
396         goto punt;
397     }
398     /* set quota entry, create filsys */
399     
400     status = alloc_filsys(login, SMS_FS_STUDENT, 0, 0);
401     if (status == SMS_FILESYS_EXISTS) status = UREG_LOGIN_USED;
402     if (status) {
403         com_err("alloc_filsys", status, 0);
404         goto punt;
405     }
406     /* set filsys and status in SMS database */
407     
408     status = set_status_filsys(reg_misc, mit_id);
409     if (status) {
410         com_err("set_filsys", status, 0);
411         goto punt;
412     }
413 punt:
414     dest_tkt();
415
416     com_err("reg_svr", status, " returned from reserve_user");
417     return status;
418 }
419
420 set_password(message)
421     struct msg *message;
422 {
423     char *argv[3];
424     int status;
425     char uid_buf[10];
426     
427     com_err("reg_svr", 0, " set_password %s %s\n",
428             message->first, message->last);
429
430     /* validate that user is who he claims to be */
431
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;
442     
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;
450     }
451
452     /* get keys */
453     status = get_svc_in_tkt("register", "sms", "ATHENA.MIT.EDU",
454                             "changepw", "kerberos",
455                             1, "/etc/srvtab");
456     if (status) {
457             status += krb_err_base;
458             goto punt;
459     }
460
461     (void) sprintf(uid_buf, "%013d", user_id); /* 13 chars of placebo */
462                                                /* for backwards-compat. */
463     /* send set password request to kerberos admin_server */
464     status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, retval, "", 
465                         reg_misc, uid_buf);
466
467     if (status) goto punt;
468     dest_tkt();
469     
470     status = set_final_status(retval, mit_id);
471
472     /* reflect reply to client */
473 punt:
474     dest_tkt();
475     return status;
476 }
477
478 parse_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
526 format_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
544 store_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
567 set_login(username, idnumber)
568     char *username;
569     char *idnumber;
570 {
571     char *argv[2];
572     int status, i;
573     char *retv[13];
574     
575     argv[0] = "get_user_by_mitid";
576     argv[1] = idnumber;
577
578     for (i=0; i<13; i++) {
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;
587     if (retv[4]) free(retv[4]);
588     retv[4] = "null";           /* No such filesystem */
589     
590     printf("Update_user(%s, %s)\n", retv[0], retv[1]);
591     
592     status = sms_query("update_user", 12, retv, abort, 0);
593     retv[1] = 0;
594     retv[4] = 0;
595     
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
608 set_status_filsys(username, idnumber)
609     char *username;
610     char *idnumber;
611 {
612     char *argv[2];
613     int status, i;
614     char *retv[13];
615     
616     argv[0] = "get_user_by_mitid";
617     argv[1] = idnumber;
618
619     for (i=0; i<13; i++) {
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 }    
645 /*
646  * Set the status and filsys of user with username "uname" and filesys filsys.
647  */
648
649 set_final_status(username, idnumber)
650     char *username;
651     char *idnumber;
652 {
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;
662     }
663
664     status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
665     if (status) return status;
666
667     retv[0] = retv[1];
668
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
683 create_group(login)
684     char *login;
685 {
686     int status;
687     static char *cr[] = {
688         "add_user_group",
689         0,
690     };
691     
692     cr[1] = login;
693     
694     return sms_query_internal(2, cr, abort, 0);
695 }    
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  */
706
This page took 0.091734 seconds and 5 git commands to generate.