]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
0217c8a6379d0d0a7d0fc976b46d57df2ac5a1f5
[moira.git] / reg_svr / reg_svr.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  *
10  *      Server for user registration with Moira and Kerberos.
11  *
12  *      This program is a client of the Kerberos admin_server and a
13  *      server for the userreg program.  It is not a client of the
14  *      Moira server as it is linked with libsmsglue which bypasses
15  *      the network protocol.
16  */
17
18 #ifndef lint
19 static char *rcsid_reg_svr_c = "$Header$";
20 #endif lint
21
22 #include <mit-copyright.h>
23 #include <stdio.h>
24 #include <strings.h>
25 #include <ctype.h>
26 #include <sys/types.h>
27 #include <sys/file.h>
28 #include <krb.h>
29 #include <des.h>
30 #include <kadm.h>
31 #include <kadm_err.h>
32 #include <krb_err.h>
33 #include <errno.h>
34 #include "sms.h"
35 #include "sms_app.h"
36 #include "reg_svr.h"
37
38 extern char admin_errmsg[];
39
40 void reg_com_err_hook();
41
42 main(argc,argv)
43   int argc;
44   char *argv[];
45 {
46     struct msg message;         /* Storage for parsed packet */
47     int status = SUCCESS;       /* Error status */
48     char retval[BUFSIZ];        /* Buffer to hold return message for client */
49     
50     void req_initialize();      /* Initialize request layer */
51     void get_request();         /* Get a request */
52     void report();              /* Respond to a request */
53
54     /* Initialize */
55     whoami = argv[0];
56     
57     /* Error messages sent one line at a time */
58     setlinebuf(stderr);
59     setlinebuf(stdout);
60     set_com_err_hook(reg_com_err_hook);
61     
62     /* Initialize com_err error tables */
63     init_ureg_err_tbl();
64     init_krb_err_tbl();
65     init_kadm_err_tbl();
66     
67     /* Use com_err or output to stderr for all log messages. */    
68 #ifdef DEBUG
69     com_err(whoami, 0, "*** Debugging messages enabled. ***");
70 #endif DEBUG
71     
72     /* Set the name of our kerberos ticket file */
73     krb_set_tkt_string("/tmp/tkt_ureg");
74
75     /* Connect to the Moira server */
76     if ((status = sms_connect(SMS_SERVER)) != SMS_SUCCESS) 
77     {
78         com_err(whoami, status, " on sms_connect");
79         exit(1);
80     }
81     
82     /* Authorize, telling the server who you are */
83     if ((status = sms_auth(whoami)) != SMS_SUCCESS) 
84     {
85         com_err(whoami, status, " on sms_auth");
86         exit(1);
87     }
88     
89     journal = fopen(REGJOURNAL, "a");
90     if (journal == NULL) {
91         com_err(whoami, errno, " while opening journal file");
92         exit(1);
93     }
94     
95     /* Allow request layer to initialize */
96     req_initialize();
97     
98     /* Sit around waiting for requests from the client. */
99     for (;;) 
100     {
101         get_request(&message);
102         
103         switch((int)message.request) 
104         {
105           case UREG_VERIFY_USER:
106             status = verify_user(&message,retval);
107             break;
108           case UREG_RESERVE_LOGIN:
109             status = reserve_user(&message,retval);
110             break;
111           case UREG_SET_PASSWORD:
112           case UREG_GET_KRB:
113             status = set_password(&message,retval);
114             break;
115           case UREG_SET_IDENT:
116             status = set_identity(&message,retval);
117             break;
118           default:
119             status = UREG_UNKNOWN_REQUEST;
120             critical_alert(FAIL_INST,"Unknown request %d from userreg.",
121                            message.request);
122             break;
123         }
124         
125         /* Report what happened to client */
126         report(status, retval);
127     }
128 }
129
130 int parse_encrypted(message,data)
131   struct msg *message;          /* Formatted packet */
132   struct db_data *data;         /* Data from the Moira database */
133 /* This routine makes sure that the ID from the database matches
134    the ID sent accross in the packet.  The information in the packet
135    was created in the following way:
136
137    The plain text ID number was encrypted via EncryptID() resulting
138    in the form that would appear in the Moira database.  This is
139    concatinated to the plain text ID so that the ID string contains plain
140    text ID followed by a null followed by the encrypted ID.  Other
141    information such as the username or password is appended.  The whole
142    thing is then DES encrypted using the encrypted ID as the source of
143    the key.
144
145    This routine tries each encrypted ID in the database that belongs
146    to someone with this user's first and last name and tries to 
147    decrypt the packet with this information.  If it succeeds, it returns 
148    zero and initializes all the fields of the formatted packet structure
149    that depend on the encrypted information. */
150 {
151     C_Block key;                /* The key for DES en/decryption */
152     Key_schedule sched;         /* En/decryption schedule */
153     static char decrypt[BUFSIZ];   /* Buffer to hold decrypted information */
154     long decrypt_len;           /* Length of decypted ID information */
155     char recrypt[14];           /* Buffer to hold re-encrypted information */
156     static char hashid[14];     /* Buffer to hold one-way encrypted ID */
157     char idnumber[BUFSIZ];      /* Buffer to hold plain-text ID */
158     char *temp;                 /* A temporary string pointer */
159     int len;                    /* Keeps track of length left in packet */
160     int status = SUCCESS;       /* Error status */
161     
162 #ifdef DEBUG
163     com_err(whoami, 0, "Entering parse_encrypted");
164 #endif
165
166     /* Make the decrypted information length the same as the encrypted
167        information length.  Both are integral multples of eight bytes 
168        because of the DES encryption routines. */
169     decrypt_len = (long)message->encrypted_len;
170     
171     /* Get key from the one-way encrypted ID in the Moira database */
172     string_to_key(data->mit_id, key);
173     /* Get schedule from key */
174     key_sched(key, sched);
175     /* Decrypt information from packet using this key.  Since decrypt_len
176        is an integral multiple of eight bytes, it will probably be null-
177        padded. */
178     pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, DECRYPT);
179     
180     /* Extract the plain text and encrypted ID fields from the decrypted
181        packet information. */
182     /* Since the decrypted information starts with the plain-text ID
183        followed by a null, if the decryption worked, this will only 
184        copy the plain text part of the decrypted information.  It is
185        important that strncpy be used because if we are not using the
186        correct key, there is no guarantee that a null will occur
187        anywhere in the string. */
188     (void) strncpy(idnumber,decrypt,(int)decrypt_len);
189     /* Point temp to the end of the plain text ID number. */
190     temp = decrypt + strlen(idnumber) + 1;
191     /* Find out how much more packet there is. */
192     len = message->encrypted_len - (temp - decrypt);
193     /* Copy the next CRYPT_LEN bytes of the decrypted information into 
194        hashid if there are CRYPT_LEN more bytes to copy.  There will be
195        if we have the right key. */
196     (void) strncpy(hashid, temp, min(len, CRYPT_LEN));
197     /* Point temp to the end of the encrypted ID field */
198     temp += strlen(hashid) + 1;
199     /* Find out how much more room there is. */
200     len = message->encrypted_len - (temp - decrypt);
201     
202     /* Now compare encrypted ID's don't match. */
203     if (strcmp(hashid, data->mit_id)) status = FAILURE;
204     if (status == SUCCESS)
205     {
206         EncryptID(recrypt, idnumber, message->first, message->last);
207         /* Now compare encrypted plain text to ID from database. */
208         if (strcmp(recrypt, data->mit_id)) status = FAILURE;
209     }
210     
211     if (status == SUCCESS)
212     {
213         /* We made it.  Now we can finish initializing message. */
214         /* Point leftover to whatever is left over! */
215         message->leftover = temp;
216         message->leftover_len = len;
217         /* Since we know we have the right user, fill in the information 
218            from the Moira database. */
219         message->db.reg_status = data->reg_status;
220         (void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid));
221         (void) strncpy(message->db.mit_id,data->mit_id, 
222                        sizeof(message->db.mit_id));
223         (void) strncpy(message->db.login,data->login, sizeof(message->db.login));
224     }
225     
226 #ifdef DEBUG
227     if (status)
228         com_err(whoami, status, " in parse_encrypted");
229     else
230         com_err(whoami, status, "parse_encrypted succeeded");
231 #endif
232
233     return status;
234 }
235
236 int db_callproc(argc,argv,queue)
237   int argc;                     /* Number of arguments returned by Moira */
238   char *argv[];                 /* Arguments returned by Moira */
239   struct save_queue *queue;     /* Queue to save information in */
240 /* This function is called by sms_query after each tuple found.  It is
241    used by find_user to cache information about each user found.  */
242 {
243     struct db_data *data;       /* Structure to store the information in */
244     int status = SUCCESS;       /* Error status */
245     
246 #ifdef DEBUG
247     com_err(whoami, 0, "Entering db_callproc.");
248 #endif
249
250     if (argc != U_END)
251     {
252         critical_alert
253             (FAIL_INST,
254              "Wrong number of arguments returned from get_user_by_name.");
255         status = SMS_ABORT;
256     }
257     else
258     {
259         /* extract the needed information from the results of the Moira query */
260         data = (struct db_data *)malloc(sizeof(struct db_data));
261         data->reg_status = atoi(argv[U_STATE]);
262         (void) strncpy(data->login,argv[U_NAME],sizeof(data->login));
263         (void) strncpy(data->mit_id,argv[U_MITID],sizeof(data->mit_id));
264         (void) strncpy(data->uid,argv[U_UID],sizeof(data->uid));
265 #ifdef DEBUG
266         fprintf(stderr,"Found in database:\n");
267         fprintf(stderr,"   Registration status: %d\n",data->reg_status);
268         fprintf(stderr,"   login: %s\n",data->login);
269         fprintf(stderr,"   MIT ID: %s\n",data->mit_id);
270         fprintf(stderr,"   uid: %s\n",data->uid);
271 #endif
272         sq_save_data(queue,data);
273     }
274
275     return status;
276 }
277     
278 int find_user(message)
279   struct msg *message;          /* Formatted packet structure */
280 /* This routine verifies that a user is allowed to register by finding
281    him/her in the Moira database.  It returns the status of the Moira
282    query that it calls. */
283 {
284 #define GUBN_ARGS 2             /* Arguements needed by get_user_by_name */
285     char *q_name;               /* Name of query */
286     int q_argc;                 /* Number of arguments for query */
287     char *q_argv[GUBN_ARGS];    /* Arguments to query */
288     int status = SUCCESS;       /* Query return status */
289
290     struct save_queue *queue;   /* Queue to hold Moira data */
291     struct db_data *data;       /* Structure for data for one tuple */
292     short verified = FALSE;     /* Have we verified the user? */
293
294     /* Zero the mit_id field in the formatted packet structure.  This
295        being zeroed means that no user was found. */
296     bzero(message->db.mit_id,sizeof(message->db.mit_id));
297     
298     if (status == SUCCESS)
299     {
300         /* Get ready to make an Moira query */
301         q_name = "get_user_by_name";
302         q_argc = GUBN_ARGS;     /* #defined in this routine */
303         q_argv[0] = message->first;
304         q_argv[1] = message->last;
305         
306         /* Create queue to hold information */
307         queue = sq_create();
308         
309         /* Do it */
310         status = sms_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
311         
312 #ifdef DEBUG
313         fprintf(stderr," %d returned by get_user_by_name\n",status);
314 #endif
315         
316         if (status == SMS_SUCCESS) 
317         {
318             /* Traverse the list, freeing data as we go.  If sq_get_data()
319                returns zero if there is no more data on the queue. */
320             while (sq_get_data(queue,&data))
321             {
322                 if (!verified)
323                     /* parse_encrypted returns zero on success */
324                     verified = (parse_encrypted(message,data) == SUCCESS);
325                 free((char *)data);
326             }
327         }
328
329         /* Destroy the queue */
330         sq_destroy(queue);
331     }
332     
333 #ifdef DEBUG
334     fprintf(stderr,"Returned from find_user\n");
335     fprintf(stderr,"   MIT ID: %s\n", message->db.mit_id);
336     fprintf(stderr,"   Registration status: %d\n",message->db.reg_status);
337     fprintf(stderr,"   uid: %s\n",message->db.uid);
338     fprintf(stderr,"   login: %s\n",message->db.login);
339     fprintf(stderr,"   Status from query: %d\n",status);
340 #endif DEBGUG
341
342     return status;
343 }
344
345 int verify_user(message,retval)
346   struct msg *message;
347   char *retval;
348   /* This routine determines whether a user is in the databse and returns
349      his state so that other routines can figure out whether he is the 
350      correct state for various transactions. */
351      
352 {
353     int status = SUCCESS;       /* Return status */
354
355     /* Log that we are about to veryify user */
356     com_err(whoami, 0, "verifying user %s %s",message->first,message->last);
357
358     /* Figure out what user (if any) can be found based on the
359        encrypted information in the packet.  (See the comment on 
360        parse_encrypted().) */
361
362     status = find_user(message);
363
364     /* If Moira coudn't find the user */
365     if (status == SMS_NO_MATCH) 
366         status = UREG_USER_NOT_FOUND;
367     else if (status == SMS_SUCCESS)
368     {
369         /* If the information sent over in the packet did not point to a
370            valid user, the mit_id field in the formatted packet structure
371            will be empty. */
372         if (message->db.mit_id[0] == NULL)
373             status = UREG_USER_NOT_FOUND;
374         /* If the user was found but the registration has already started,
375            use this as the status */
376         else
377         {
378             switch (message->db.reg_status)
379             {
380               case US_NO_LOGIN_YET:
381                 status = SUCCESS;
382                 break;
383               case US_REGISTERED:
384                 status = UREG_ALREADY_REGISTERED;
385                 break;
386               case US_NO_PASSWD:
387                 status = UREG_NO_PASSWD_YET;
388                 break;
389               case US_DELETED:
390                 status = UREG_DELETED;
391                 break;
392               case US_NOT_ALLOWED:
393                 status = UREG_NOT_ALLOWED;
394                 break;
395               case US_ENROLLED:
396                 status = UREG_ENROLLED;
397                 break;
398               case US_ENROLL_NOT_ALLOWED:
399                 status = UREG_ENROLL_NOT_ALLOWED;
400                 break;
401               default:
402                 status = UREG_MISC_ERROR;
403                 critical_alert(FAIL_INST,"Bad user state %d for login %s.",
404                                message->db.reg_status, message->db.login);
405                 break;
406             }
407             /* Set retval to the login name so that the client can use
408                it in the error message it will give the user. */
409             (void) strcpy(retval,message->db.login);
410         }
411     }
412     
413     if (status)
414         com_err(whoami, status, " returned from verify_user");
415     else
416         com_err(whoami, 0, "User verified");
417
418     return status;
419 }
420         
421 int ureg_kadm_init()
422 {
423     unsigned int status = SUCCESS;       /* Return status */
424     static char krbrealm[REALM_SZ];      /* kerberos realm name */
425     static int inited = 0;
426
427 #ifdef DEBUG
428     com_err(whoami, 0, "Entering ureg_kadm_init");
429 #endif DEBUG
430
431     if (!inited) {
432         inited++;
433         bzero(krbrealm, sizeof(krbrealm));
434         if (status = krb_get_lrealm(krbrealm, 1)) {
435             status += krb_err_base;
436             com_err(whoami, status, " fetching kerberos realm");
437             exit(1);
438         }
439     }
440
441     /* Get keys for interacting with Kerberos admin server. */
442     /* principal, instance, realm, service, service instance, life, file */
443     if (status = krb_get_svc_in_tkt("register", "sms", krbrealm, PWSERV_NAME,
444                                     KADM_SINST, 1, KEYFILE))
445         status += krb_err_base;
446     
447     if (status != SUCCESS)
448         com_err(whoami, status, " while get admin tickets");
449 #ifdef DEBUG
450     else {
451         com_err(whoami, status, "Succeeded in getting admin tickets");
452     }
453 #endif
454
455     if (status == SUCCESS) {
456         if ((status = kadm_init_link(PWSERV_NAME, KADM_SINST, krbrealm)) !=
457             KADM_SUCCESS) {
458             com_err(whoami, status, " while initializing kadmin connection");
459         }
460     }
461
462     return status;
463 }
464
465 int null_callproc(argc,argv,message)
466   int argc;
467   char *argv[];
468   char *message;
469   /* This routine is a null callback that should be used for queries that
470      do not return tuples.  If it ever gets called, something is wrong. */
471 {
472     critical_alert(FAIL_INST,"Something returned from an update query.");
473     return FAILURE;
474 }
475
476 /*
477  * This routine reserves a principal in kerberos by setting up a 
478  * principal with a random initial key.
479  */
480 int reserve_krb(login)
481   char *login;
482 {
483     int status = SUCCESS;
484     Kadm_vals new;
485     des_cblock key;
486     u_long *lkey = (u_long *)key;
487
488 #ifdef DEBUG
489     com_err(whoami, 0, "Entering reserve_krb");
490 #endif DEBUG
491
492     if ((status = ureg_kadm_init()) == SUCCESS) {
493         bzero((char *)&new, sizeof(new));
494         SET_FIELD(KADM_DESKEY, new.fields);
495         SET_FIELD(KADM_NAME, new.fields);
496         
497         (void) des_random_key(key);
498         new.key_low = htonl(lkey[0]);
499         new.key_high = htonl(lkey[1]);
500         strcpy(new.name, login);
501         
502         com_err(whoami, 0, "Creating kerberos principal for %s", login);
503         status = kadm_add(&new);
504         if (status != KADM_SUCCESS) 
505             com_err(whoami, status, " while reserving principal");
506         
507         bzero((char *)&new, sizeof(new));
508     }
509
510     dest_tkt();
511
512     return(status);
513 }
514
515 /*
516  * This routine reserves a principal in kerberos by setting up a 
517  * principal with a random initial key.
518  */
519 int setpass_krb(login, password)
520   char *login;
521   char *password;
522 {
523     int status = SUCCESS;
524     Kadm_vals new;
525     des_cblock key;
526     u_long *lkey = (u_long *)key;
527
528     if ((status = ureg_kadm_init()) == SUCCESS) {
529         bzero((char *)&new, sizeof(new));
530         SET_FIELD(KADM_DESKEY, new.fields);
531         SET_FIELD(KADM_NAME, new.fields);
532         
533         (void) des_string_to_key(password, key);
534         new.key_low = htonl(lkey[0]);
535         new.key_high = htonl(lkey[1]);
536         strcpy(new.name, login);
537         
538         com_err(whoami, 0, "Setting password for %s", login);
539         /* First arguement is not used if user has modify privileges */
540         if ((status = kadm_mod(&new, &new)) != KADM_SUCCESS) {
541             if (status == KADM_NOENTRY) {
542                 com_err(whoami, 0, 
543                         "kerberos principal doesn't exist; creating");
544                 if ((status = kadm_add(&new)) != KADM_SUCCESS)
545                     com_err(whoami, status, 
546                             " while creating kerberos principal");
547             }
548             else
549                 com_err(whoami, status, " while setting password");
550         }
551     }
552     
553     dest_tkt();
554     return(status);
555 }
556
557 int reserve_user(message,retval)
558   struct msg *message;
559   char *retval;
560 {
561     int q_argc;                 /* Number of arguments to query */
562     char *q_argv[3];            /* Arguments to Moira query */
563     char *q_name;               /* Name of Moira query */
564     int status = SUCCESS;       /* General purpose error status */
565     char fstype_buf[7];         /* Buffer to hold fs_type, a 16 bit number */
566     char *login;                /* The login name the user wants */
567     register int i;             /* A counter */
568
569     /* Log that we are about to reserve a user. */
570     com_err(whoami, 0, "reserving user %s %s", 
571             message->first, message->last);
572     
573     /* Check to make sure that we can verify this user. */
574     if ((status = verify_user(message,retval)) == SUCCESS)
575     {
576         /* Get the requested login name from leftover packet information. */
577         login = message->leftover;
578
579         /* Check the login name for validity.  The login name is currently
580            is allowed to contain lowercase letters in any position and 
581            and numbers and underscore characters in any position but the 
582            first. */
583         if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
584             status = UREG_INVALID_UNAME;
585     }
586     if (status == SUCCESS)
587         if ((login[0] == '_') || isdigit(login[0]))
588             status = UREG_INVALID_UNAME;
589     
590     if (status == SUCCESS)
591     {
592         for (i = 0; i < strlen(login); i++)
593             if (!islower(login[i]) && !isdigit(login[i]) && 
594                 (login[i] != '_'))
595             {
596                 status = UREG_INVALID_UNAME;
597                 break;
598             }
599     }
600     if (status == SUCCESS)
601     {
602         /* Now that we have a valid user with a valid login... */
603
604         /* First, try to reserve the user in Moira. */
605         (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
606         q_name = "register_user";
607         q_argv[0] = message->db.uid;
608         q_argv[1] = login;
609         q_argv[2] = fstype_buf;
610         q_argc = 3;
611         status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
612         switch (status)
613         {
614           case SMS_SUCCESS:
615             status = SUCCESS;
616             break;
617           case SMS_IN_USE:
618             status = UREG_LOGIN_USED;
619             break;
620           case SMS_DEADLOCK:
621             status = UREG_MISC_ERROR;
622             break;
623           default:
624             critical_alert(FAIL_INST,"%s returned from register_user.",
625                            error_message(status));
626             status = UREG_MISC_ERROR;
627             break;
628         }
629     }
630
631     if (status == SUCCESS)
632     {
633         /* 
634          * Moira login was successfully created; try to reserve kerberos
635          * principal. 
636          *
637          * If this routine fails, store the login in the retval so
638          * that it can be used in the client-side error message.
639          */
640         if ((status = reserve_krb(login)) != SUCCESS)
641             (void) strcpy(retval, login);
642     }
643
644     if (status)
645         com_err(whoami, status, " returned from reserve_user");
646     else {
647         com_err(whoami, 0, "User reserved");
648     }
649     
650     return status;
651 }
652
653 int set_final_status(message)
654 struct msg *message;
655     /* This routine updates a user's registration status to fully 
656        registered. */
657 {
658     char *login;
659     char *q_name;               /* Name of Moira query */
660     int q_argc;                 /* Number of arguments for Moira query */
661     char *q_argv[2];            /* Arguments to get user by uid */
662     char state[7];              /* Can hold a 16 bit integer */
663     int status;                 /* Error status */
664
665     if (message->request == UREG_SET_PASSWORD)
666       (void) sprintf(state,"%d",US_REGISTERED);
667     else if (message->db.reg_status == US_NO_LOGIN_YET)
668       (void) sprintf(state,"%d",US_ENROLLED);
669     else
670       (void) sprintf(state,"%d",US_ENROLL_NOT_ALLOWED);
671
672     login = message->db.login;
673     com_err(whoami, 0, "Setting final status for %s to %s", login, state);
674
675     q_name = "update_user_status";
676     q_argc = 2;
677     q_argv[0] = login;
678     q_argv[1] = state;
679     if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
680                             (char *)0)) != SMS_SUCCESS) {
681         if (status == SMS_DEADLOCK)
682           status = UREG_MISC_ERROR;
683         else
684           critical_alert(FAIL_INST,"%s returned from update_user_status.",
685                          error_message(status));
686     }
687     if (status)
688         com_err(whoami, status, " returned from set_final_status");
689     else
690         com_err(whoami, 0, "Final status set");
691     return status;
692 }
693
694
695 int set_password(message,retval)
696   struct msg *message;
697   char *retval;
698   /* This routine is used to set the initial password for the new user. */
699 {
700     int status = SUCCESS;       /* Return status */
701     char *passwd;               /* User's password */
702
703     com_err(whoami, 0, "setting password %s %s",
704             message->first, message->last);
705
706     status = verify_user(message,retval);
707
708     /* Don't set the password unless the registration status of the user
709        is that he exists and has no password. */
710     if (status == SUCCESS)
711         status = UREG_NO_LOGIN_YET;
712     if (status == UREG_NO_PASSWD_YET)
713     {
714         /* User is in proper state for this transaction. */
715         
716         passwd = message->leftover;
717         
718         /* Set password. */
719         if ((status = setpass_krb(message->db.login, passwd)) != SUCCESS)
720             /* If failure, allow login name to be used in client 
721                error message */
722             (void) strcpy(retval,message->db.login);
723         else
724             /* Otherwise, mark user as finished. */
725             status = set_final_status(message);
726     }
727
728     if (status)
729         com_err(whoami, status, " returned from set_passwd");
730     else
731         com_err(whoami, 0, "Password set");
732
733     return status;
734 }
735
736
737 int getuserinfo(argc, argv, qargv)
738 int argc;
739 char **argv;
740 char **qargv;
741 {
742     int status = SUCCESS;
743
744     if (argc != U_END) {
745         critical_alert(FAIL_INST,
746                        "Wrong number of args returned from get_user_by_uid");
747         status = SMS_ABORT;
748     } else {
749         qargv[U_NAME] = strsave(argv[U_NAME]);
750         qargv[U_UID+1] = strsave(argv[U_UID]);
751         qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
752         qargv[U_LAST+1] = strsave(argv[U_LAST]);
753         qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
754         qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
755         qargv[U_STATE+1] = strsave(argv[U_STATE]);
756         qargv[U_MITID+1] = strsave(argv[U_MITID]);
757         qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
758         qargv[U_MODTIME+1] = NULL;
759     }
760     return(status);
761 }
762
763
764 int set_identity(message,retval)
765 struct msg *message;
766 char *retval;
767 {
768     int q_argc;                 /* Number of arguments to query */
769     char *q_argv[U_END];        /* Arguments to Moira query */
770     char *q_name;               /* Name of Moira query */
771     int status = SUCCESS;       /* General purpose error status */
772     char fstype_buf[7];         /* Buffer to hold fs_type, a 16 bit number */
773     char *login;                /* The login name the user wants */
774     register int i;             /* A counter */
775
776     /* Log that we are about to reserve a user. */
777     com_err(whoami, 0, "setting identity %s %s", 
778             message->first, message->last);
779     
780     /* Check to make sure that we can verify this user. */
781     status = verify_user(message,retval);
782     if (status == SUCCESS || status == UREG_NOT_ALLOWED)
783     {
784         status = SUCCESS;
785         /* Get the requested login name from leftover packet information. */
786         login = message->leftover;
787
788         /* Check the login name for validity.  The login name is currently
789            is allowed to contain lowercase letters in any position and 
790            and numbers and underscore characters in any position but the 
791            first. */
792         if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
793             status = UREG_INVALID_UNAME;
794     }
795     if (status == SUCCESS)
796         if ((login[0] == '_') || isdigit(login[0]))
797             status = UREG_INVALID_UNAME;
798     if (status == SUCCESS)
799     {
800         for (i = 0; i < strlen(login); i++)
801             if (!islower(login[i]) && !isdigit(login[i]) && 
802                 (login[i] != '_'))
803             {
804                 status = UREG_INVALID_UNAME;
805                 break;
806             }
807     }
808     if (status == SUCCESS)
809     {
810         /* Now that we have a valid user with a valid login... */
811
812         q_argv[0] = message->db.uid;
813         status = sms_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
814         if (status != SUCCESS) {
815             com_err(whoami, status, " while getting user info");
816             return(status);
817         }
818         q_argv[U_NAME+1] = login;
819         status = sms_query("update_user", U_MODTIME+1, q_argv,
820                            null_callproc, NULL);
821         switch (status)
822         {
823           case SMS_SUCCESS:
824             status = SUCCESS;
825             break;
826           case SMS_IN_USE:
827             status = UREG_LOGIN_USED;
828             break;
829           case SMS_DEADLOCK:
830             status = UREG_MISC_ERROR;
831             break;
832           default:
833             critical_alert(FAIL_INST,"%s returned from update_user.",
834                            error_message(status));
835             status = UREG_MISC_ERROR;
836             break;
837         }
838     }
839     if (status == SUCCESS)
840     {
841         /* Moira login was successfully created; try to reserve kerberos
842            principal. */
843         /* If this routine fails, store the login in the retval so
844            that it can be used in the client-side error message. */
845         if ((status = reserve_krb(login)) != SUCCESS)
846             (void) strcpy(retval, login);
847     }
848
849     if (status)
850         com_err(whoami, status, " returned from set_identity");
851     else
852         com_err(whoami, 0, "Identity set");
853     
854     return status;
855 }
856
857
858 void reg_com_err_hook(whoami, code, fmt, pvar)
859         char *whoami;
860         int code;
861         char *fmt;
862         caddr_t pvar;
863 {
864         if (whoami) {
865                 fputs(whoami, stderr);
866                 fputs(": ", stderr);
867         }
868         if (code) {
869                 fputs(error_message(code), stderr);
870         }
871         if (fmt) {
872                 _doprnt(fmt, pvar, stderr);
873         }
874         putc('\n', stderr);
875         fflush(stderr);
876 }
This page took 0.093911 seconds and 3 git commands to generate.