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