]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
Prevent recursive query call.
[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.1  1987-07-31 15:48:13  wesommer
15  *      Initial revision
16  *
17  */
18
19 #ifndef lint
20 static char *rcsid_reg_svr_c = "$Header$";
21 #endif lint
22
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/file.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 #include <des.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include "ureg_err.h"
33 #include "ureg_proto.h"
34 #include "../../include/sms.h"
35 #include <strings.h>
36
37 extern void abort();
38
39 struct msg {
40     u_long version;
41     u_long request;
42     char *first;
43     char *last;
44     char *sealed;
45     int sealed_len;
46 };
47
48 static char retval[BUFSIZ];
49
50 #if defined(vax) || defined(ibm032) || defined(sun)
51 #define MAXINT 0x7fffffff
52 #else
53     Hey turkey!  What's the biggest integer on this machine?
54 #endif
55
56 main()
57 {
58     struct sockaddr_in sin;
59     struct servent *sp;
60     int s;
61     int status;
62     int addrlen, len;
63     char buf[BUFSIZ];
64     extern int errno;
65     u_long seqno;
66     struct msg message;
67     
68     init_ureg_err_tbl();
69     
70     status = sms_connect();
71     if (status != 0) {
72         com_err("reg_svr", status, "");
73         exit(1);
74     }
75     status = sms_auth();
76     if (status != 0) {
77         com_err("reg_svr", status, "");
78         exit(1);
79     }
80     
81     sp = getservbyname("sms_ureg", "udp");
82     if (sp == NULL) {
83         fprintf(stderr, "Unknown service sms_ureg/udp\n");
84         exit(1);
85     }
86     s = socket(AF_INET, SOCK_DGRAM, 0);
87     if (s < 0) {
88         perror("socket");
89         exit(1);
90     }
91     bzero((char *)&sin, sizeof(sin));
92
93     sin.sin_family = AF_INET;
94     sin.sin_port = sp->s_port;
95     sin.sin_addr.s_addr = INADDR_ANY;
96
97     if (bind(s, &sin, sizeof(sin)) < 0) {
98         perror("bind");
99         exit(1);
100     }
101     
102     for (;;) {
103         addrlen = sizeof(sin);
104         bzero(retval, BUFSIZ);
105         len = recvfrom(s, buf, BUFSIZ, 0, &sin, &addrlen);
106         if (len < 0) {
107             perror("recvfrom");
108             if (errno == EINTR) continue;
109             
110             exit(1);
111         }
112         /* Parse a request packet */
113         status = parse_pkt(buf, len, &seqno, &message);
114         if (status != 0) {
115             len = BUFSIZ;
116             format_pkt(buf, &len, seqno, status, (char *)NULL);
117             (void) sendto(s, buf, len, 0, &sin, addrlen);
118             continue;
119         }
120         /* do action */
121         switch((int)message.request) {
122         case UREG_VERIFY_USER:
123             status = verify_user(&message);
124             break;
125         case UREG_RESERVE_LOGIN:
126             status = reserve_user(&message);
127             break;
128         case UREG_SET_PASSWORD:
129             status = set_password(&message);
130             break;
131             
132         default:
133             status = UREG_UNKNOWN_REQUEST;
134             break;
135         }
136         len = BUFSIZ;
137         format_pkt(buf, &len, seqno, status, retval);
138         
139         sendto(s, buf, len, 0, &sin, addrlen);
140     }
141 }
142
143 set_password(message)
144     struct msg *message;
145 {
146     /* validate, as with verify, that user is who he claims to be */
147     /* validate that state is equal to '1' */
148     /* send set password request to kerberos admin_server */
149     /* reflect reply to client */
150     return 0;
151 }
152     
153 int got_one;
154 int reg_status;
155 char *mit_id;
156 char *reg_misc;
157 int reg_misc_len;
158 #define min(a,b) ((a)>(b)?(b):(a))
159     
160 int validate_idno(message, db_mit_id, first, last)
161     struct msg *message;
162     char *db_mit_id;
163     char *first, *last;
164 {
165     C_Block key;
166     Key_schedule sched;
167     char decrypt[BUFSIZ];
168     char recrypt[14];
169     static char hashid[14];
170     char idnumber[BUFSIZ];
171     char *temp;
172     int len;
173
174     int i;
175 #ifdef notdef
176     for (i = 0; i < message->sealed_len; i++) {
177         printf("%02x ", (unsigned char)message->sealed[i]);
178     }
179     printf("\n");
180 #endif notdef
181     mit_id = 0;
182     
183     string_to_key(db_mit_id, key);
184     key_sched(key, sched);
185     pcbc_encrypt(message->sealed, decrypt, message->sealed_len, sched, key, 0);
186
187 #ifdef notdef
188     for (i = 0; i < message->sealed_len; i++) {
189         printf("%02x ", (unsigned char)decrypt[i]);
190     }
191     printf("\n");
192     for (i = 0; i < message->sealed_len; i++) {
193         if (isprint(decrypt[i])) 
194             printf("%c  ", (unsigned char)decrypt[i]);
195         else printf(".  ");
196     }
197     printf("\n");
198 #endif notdef
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     
215     return 0;
216 }
217
218 vfy_callbk(argc, argv, p_message)
219     int argc;                   /* Should sanity check this.. */
220     char **argv;
221     char *p_message;
222 {
223     struct msg *message = (struct msg *)p_message;
224     char *db_mit_id;
225     char *firstname, *lastname;
226     int status;
227     
228     printf("Callback: %s %s %s\n", argv[8], argv[5], argv[4]);
229     
230     if (got_one) return 0;
231     reg_status = 0;
232     
233     db_mit_id = argv[8];
234     firstname = argv[5];
235     lastname = argv[4];
236
237     status = validate_idno(message, db_mit_id, firstname, lastname);
238     if (status) return 0; /* Nope; decryption failed */
239     
240     if (atoi(argv[7]) == 1) {
241         reg_status = UREG_ALREADY_REGISTERED;
242         (void) strcpy(retval, argv[0]);
243     }
244     got_one = 1;
245     return 0;
246 }    
247
248 encrypt_mitid(buf, idnumber, first, last)
249     char *buf, *idnumber, *first, *last;
250 {
251     char salt[3];
252     extern char *crypt();
253     
254 #define _tolower(c) ((c)|0x60)
255
256     salt[0] = _tolower(last[0]);
257     salt[1] = _tolower(first[0]);
258     salt[2] = 0;
259     
260     (void) strcpy(buf, crypt(&idnumber[2], salt));
261 }
262
263 int verify_user(message)
264     struct msg *message;
265
266 {
267     char *argv[3];
268     int status;
269     
270     printf("verify_user\n");
271     argv[0] = "get_user_by_first_and_last";
272     argv[1] = message->first;
273     argv[2] = message->last;
274     got_one = 0;
275     
276     status = sms_query_internal(3, argv, vfy_callbk, (char *)message);
277     
278     if (status == SMS_NO_MATCH) status = UREG_USER_NOT_FOUND;
279     if (!got_one && !status)
280         status = UREG_USER_NOT_FOUND;
281     
282     if (status != 0) goto punt;
283
284     if (reg_status != 0) status = reg_status;
285     
286 punt:
287     return status;
288 }
289
290 reserve_user(message)
291     struct msg *message;
292 {
293     char *argv[3];
294     int status;
295     int i;
296     char *login;
297     
298     printf("reserve_user\n");
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 = reg_status;
314         goto punt;
315     }
316
317     /* Sanity check requested login name. */
318     printf("reg_misc_len = %d\n", reg_misc_len);
319
320     for (i = 0; i < reg_misc_len && reg_misc[i]; i++) {
321         if (!islower(reg_misc[i])) {
322             status = UREG_INVALID_UNAME;
323             goto punt;
324         }
325     }
326     if (i < 3 || i > 8) {
327         status = UREG_INVALID_UNAME;
328         goto punt;
329     }
330     login = reg_misc;
331     
332     /* Send request to kerberos admin_server for login name */
333     /* If valid: */
334
335     /* Set login name */
336     set_login(login, mit_id);
337     
338     /* choose post office */
339     choose_pobox(login);
340
341     /* set quota entry, create filsys */
342     alloc_filsys(login);
343
344     /* set filsys and status in SMS database */
345     set_status_filsys(reg_misc, mit_id);
346     
347 punt:
348     printf("reserve_user returning %s\n", error_message(status));
349     return status;
350 }
351
352 extern char *malloc();
353
354 char *strdup(cp)
355     char *cp;
356 {
357     int len = strlen(cp) + 1;
358     char *np = malloc(len);
359     bcopy(cp, np, len);
360     return np;
361 }
362
363 static char *pohost;
364 static int min_usage;
365
366 static po_callbk(argc, argv, argp)
367     int argc;
368     char **argv;
369 {
370     if (!isdigit(*argv[6])) {
371         printf("non-digit value_1 field??\n");
372         return 0;       
373     }
374     
375     if (atoi(argv[6]) < min_usage) {
376         min_usage = atoi(argv[6]);
377         if (pohost) free(pohost);
378         pohost = strdup(argv[1]);
379     }
380         
381     return 0;
382 }
383
384 choose_pobox(login)
385     char *login;
386 {
387     int status;
388     static char *argv[3]={
389         "gshi",
390         "pop",
391         "*"
392     };
393     static char *apoa[5] = {
394         "add_pobox",
395         0,
396         "pop",
397         0,
398         0
399     }; 
400     
401     pohost = NULL;
402     min_usage = MAXINT; /* MAXINT */
403     status = sms_query_internal(3, argv, po_callbk,(char *)&min_usage);
404     if (status != 0) {
405         com_err("reg_svr", status, "finding pobox");
406         printf("Can't find postoffices\n");
407         return status;
408     }
409     printf("Chose %s\n", pohost);
410     apoa[1] = apoa[4] = login;
411     apoa[3] = pohost;
412     status = sms_query_internal(5, apoa, abort, 0);
413
414     if (status == SMS_EXISTS) status = 0;
415     
416     if (status != 0) {
417         com_err("reg_svr", status, "adding pobox");
418     }
419     return status;
420 }
421
422
423 parse_pkt(buf, len, seqnop, messagep)
424     char *buf;
425     int len;
426     u_long *seqnop;
427     struct msg *messagep;
428 {
429     if (len < 4) return UREG_BROKEN_PACKET;
430     bcopy(buf, (char *)&messagep->version, sizeof(long));
431     messagep->version = ntohl(messagep->version);
432     if (messagep->version != 1) return UREG_WRONG_VERSION;
433     
434     buf += 4;
435     len -= 4;
436
437     if (len < 4) return UREG_BROKEN_PACKET;
438     bcopy(buf, (char *)seqnop, sizeof(long));
439
440     buf += 4;
441     len -= 4;
442     
443     if (len < 4) return UREG_BROKEN_PACKET;
444     bcopy(buf, (char *)(&messagep->request), sizeof(long));
445     messagep->request = ntohl(messagep->request);
446     buf += 4;
447     len -= 4;
448     
449     messagep->first = buf;
450
451     for (; *buf && len > 0; --len, ++buf) continue;
452     if (len <= 0) return UREG_BROKEN_PACKET;
453
454     buf++, len--;
455
456     messagep->last = buf;
457
458     for (; *buf && len > 0; --len, ++buf) continue;
459     if (len <= 0) return UREG_BROKEN_PACKET;
460     
461     buf++, len--;
462
463     if (len <= 0) return UREG_BROKEN_PACKET;
464     
465     messagep->sealed = buf;
466     messagep->sealed_len = len;
467     
468     return 0;
469 }
470
471 format_pkt(buf, lenp, seqno, status, message)
472     char *buf;
473     int *lenp;
474     u_long seqno;
475     int status;
476     char *message;
477 {
478     u_long vers = htonl((u_long)1);
479     status = htonl((u_long)status);
480     
481     bcopy((char *)&vers, buf, sizeof(long));
482     bcopy((char *)&seqno, buf+sizeof(long), sizeof(long));
483     bcopy((char *)&status, buf+ 2*sizeof(long), sizeof(long));
484     *lenp = sizeof(long) * 3;
485     (void) strcpy(buf+3*sizeof(long), message);
486     (*lenp) += strlen(message);
487 }
488
489 store_user(argc, argv, argp)
490     int argc;
491     char **argv;
492     char *argp;
493 {
494     char **retv = (char **) argp;
495     int i;
496     
497     for (i = 0; i < argc; i++) {
498         if (retv[i]) {
499             free(retv[i]);
500             retv[i]=0;
501         }
502         retv[i] = strdup(argv[i]);
503     }
504     return 0;
505 }
506     
507
508 /*
509  * Set login name of user with "idnumber" to be "username"
510  */
511
512 set_login(username, idnumber)
513     char *username;
514     char *idnumber;
515 {
516     char *argv[2];
517     int status, i;
518     char *retv[12];
519     
520     argv[0] = "get_user_by_mitid";
521     argv[1] = idnumber;
522
523     for (i=0; i<12; i++) {
524         retv[i] = 0;
525     }
526
527     status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
528     if (status) return status;
529
530     retv[0] = retv[1];
531     retv[1] = username;
532     
533     printf("Update_user(%s, %s)\n", retv[0], retv[1]);
534     
535     status = sms_query("update_user", 12, retv, abort, 0);
536     for (i=1; i<12; i++) {
537         if (retv[i]) free(retv[i]);
538         retv[i] = 0;
539     }
540     
541     return status;
542 }    
543
544 /*
545  * Set the status and filsys of user with username "uname" and filesys filsys.
546  */
547
548 set_status_filsys(username, idnumber)
549     char *username;
550     char *idnumber;
551 {
552     char *argv[2];
553     int status, i;
554     char *retv[12];
555     
556     argv[0] = "get_user_by_mitid";
557     argv[1] = idnumber;
558
559     for (i=0; i<12; i++) {
560         retv[i] = 0;
561     }
562
563     status = sms_query_internal(2, argv, store_user, (char *)(retv+1));
564     if (status) return status;
565
566     retv[0] = retv[1];
567
568     free(retv[4]);
569     retv[4] = username;
570
571     free(retv[8]);
572     retv[8] = "2";
573     
574     printf("Update_user(%s, %s)\n", retv[0], retv[1]);
575     
576     status = sms_query("update_user", 12, retv, abort, 0);
577     retv[4] = 0;
578     retv[8] = 0;
579     for (i=1; i<12; i++) {
580         if (retv[i]) free(retv[i]);
581         retv[i] = 0;
582     }
583     return status;
584 }    
585
586 static char *nfs_device;
587 static char *nfs_dir;
588 static char *nfs_host;
589 static int nfs_alloc;
590
591     
592 static afcb(argc, argv, argp)
593     int argc;
594     char **argv;
595     char *argp;
596 {
597     if ((atoi(argv[3]) & 1) == 0) return 0; /* not free for alloc. */
598     
599     if (atoi(argv[4]) < nfs_alloc) {
600         nfs_alloc = atoi(argv[4]);
601         if (nfs_device) free(nfs_device);
602         if (nfs_dir) free(nfs_dir);
603         if (nfs_host) free(nfs_host);
604         nfs_host = strdup(argv[0]);
605         nfs_device = strdup(argv[1]);
606         nfs_dir = strdup(argv[2]);
607     }
608     return 0;
609 }
610
611 /*
612  * Allocate home filesystem.
613  */
614
615 alloc_filsys(login)
616     char *login;
617 {
618     static char *argv[] = {
619         "get_all_nfsphys"
620         };
621     static char *alocv[] = {
622         "add_locker",
623         0,
624         0,
625         0,
626         "1024"
627         };
628     
629     int status;
630     nfs_alloc = MAXINT;
631     
632     status = sms_query_internal(1, argv, afcb, 0);
633     if (status) {
634         com_err("reg_svr", status, "while doing get_all_nfsphys");
635         return status;
636     }
637     alocv[1] = login;
638     alocv[2] = nfs_host;
639     alocv[3] = nfs_device;
640     printf("add_locker(%s, %s, %s)\n", login, nfs_host, nfs_device);
641     
642     status = sms_query_internal(5, alocv, abort, 0);
643     if (status) {
644         com_err("reg_svr", status, "while adding locker");
645         return status;
646     }
647 }
648
649 /*
650  * Local Variables:
651  * mode: c
652  * c-indent-level: 4
653  * c-continued-statement-offset: 4
654  * c-brace-offset: -4
655  * c-argdecl-indent: 4
656  * c-label-offset: -4
657  * End:
658  */
This page took 0.103018 seconds and 5 git commands to generate.