]> andersk Git - moira.git/blob - reg_svr/reg_svr.c
3cdd98296cda2c9a15fde208937ccf7a1ce69b46
[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             if (status != ETIMEDOUT)
493               critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.", 
494                              login);
495         }
496     }
497     
498     dest_tkt();
499     com_err(whoami,status," returned from do_admin_call");
500     return status;
501 }
502
503 int reserve_user(message,retval)
504   struct msg *message;
505   char *retval;
506 {
507     int q_argc;                 /* Number of arguments to query */
508     char *q_argv[3];            /* Arguments to SMS query */
509     char *q_name;               /* Name of SMS query */
510     int status = SUCCESS;       /* General purpose error status */
511     char fstype_buf[7];         /* Buffer to hold fs_type, a 16 bit number */
512     char *login;                /* The login name the user wants */
513     register int i;             /* A counter */
514
515     /* Log that we are about to reserve a user. */
516     com_err(whoami, 0, "reserve_user %s %s", 
517             message->first, message->last);
518     
519     /* Check to make sure that we can verify this user. */
520     if ((status = verify_user(message,retval)) == SUCCESS)
521     {
522         /* Get the requested login name from leftover packet information. */
523         login = message->leftover;
524
525         /* Check the login name for validity.  The login name is currently
526            is allowed to contain lowercase letters and numbers in any
527            position and underscore characters in any position but the 
528            first. */
529         if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
530             status = UREG_INVALID_UNAME;
531     }
532     if (status == SUCCESS)
533         if (login[1] == '_')
534             status = UREG_INVALID_UNAME;
535     if (status == SUCCESS)
536     {
537         for (i = 0; i < strlen(login); i++)
538             if (!islower(login[i]) && !isdigit(login[i]) && 
539                 (login[i] != '_'))
540             {
541                 status = UREG_INVALID_UNAME;
542                 break;
543             }
544     }
545     if (status == SUCCESS)
546     {
547         /* Now that we have a valid user with a valid login... */
548
549         /* First, try to reserve the user in SMS. */
550         (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
551         q_name = "register_user";
552         q_argv[0] = message->db.uid;
553         q_argv[1] = login;
554         q_argv[2] = fstype_buf;
555         q_argc = 3;
556         status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
557         switch (status)
558         {
559           case SMS_SUCCESS:
560             status = SUCCESS;
561             break;
562           case SMS_IN_USE:
563             status = UREG_LOGIN_USED;
564             break;
565           case SMS_DEADLOCK:
566             status = UREG_MISC_ERROR;
567             break;
568           default:
569             critical_alert(FAIL_INST,"%s returned from register_user.",
570                            error_message(status));
571             status = UREG_MISC_ERROR;
572             break;
573         }
574     }
575     if (status == SUCCESS)
576     {
577         /* SMS login was successfully created; try to reserve kerberos
578            principal. */
579         /* If this routine fails, store the login in the retval so
580            that it can be used in the client-side error message. */
581         if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
582             (void) strcpy(retval, login);
583     }
584
585     com_err(whoami, status, " returned from reserve_user");
586     
587     return status;
588 }
589
590 int set_final_status(message)
591 struct msg *message;
592     /* This routine updates a user's registration status to fully 
593        registered. */
594 {
595     char *login;
596     char *q_name;               /* Name of SMS query */
597     int q_argc;                 /* Number of arguments for SMS query */
598     char *q_argv[2];            /* Arguments to get user by uid */
599     char state[7];              /* Can hold a 16 bit integer */
600     int status;                 /* Error status */
601
602     if (message->request == UREG_SET_PASSWORD)
603       (void) sprintf(state,"%d",US_REGISTERED);
604     else if (message->db.reg_status == US_NO_LOGIN_YET)
605       (void) sprintf(state,"%d",US_ENROLLED);
606     else
607       (void) sprintf(state,"%d",US_ENROLL_NOT_ALLOWED);
608
609     login = message->db.login;
610     com_err(whoami, 0, "Setting final status for %s to %s", login, state);
611
612     q_name = "update_user_status";
613     q_argc = 2;
614     q_argv[0] = login;
615     q_argv[1] = state;
616     if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
617                             (char *)0)) != SMS_SUCCESS) {
618         if (status == SMS_DEADLOCK)
619           status = UREG_MISC_ERROR;
620         else
621           critical_alert(FAIL_INST,"%s returned from update_user_status.",
622                          error_message(status));
623     }
624     com_err(whoami,status," returned from set_final_status");
625     return status;
626 }
627
628
629 int set_password(message,retval)
630   struct msg *message;
631   char *retval;
632   /* This routine is used to set the initial password for the new user. */
633 {
634     int status = SUCCESS;       /* Return status */
635     char *passwd;               /* User's password */
636
637     com_err(whoami, 0, " set_password %s %s",
638             message->first, message->last);
639
640     status = verify_user(message,retval);
641
642     /* Don't set the password unless the registration status of the user
643        is that he exists and has no password. */
644     if (status == SUCCESS)
645         status = UREG_NO_LOGIN_YET;
646     if (status == UREG_NO_PASSWD_YET)
647     {
648         /* User is in proper state for this transaction. */
649         
650         passwd = message->leftover;
651         
652         /* Set password. */
653         if ((status = do_admin_call(message->db.login, 
654                                     passwd, message->db.uid)) != SUCCESS)
655             /* If failure, allow login name to be used in client 
656                error message */
657             (void) strcpy(retval,message->db.login);
658         else
659             /* Otherwise, mark user as finished. */
660             status = set_final_status(message);
661     }
662     com_err(whoami, status, " returned from set_passwd");
663     
664     return status;
665 }
666
667
668 int getuserinfo(argc, argv, qargv)
669 int argc;
670 char **argv;
671 char **qargv;
672 {
673     int status = SUCCESS;
674
675     if (argc != U_END) {
676         critical_alert(FAIL_INST,
677                        "Wrong number of args returned from get_user_by_uid");
678         status = SMS_ABORT;
679     } else {
680         qargv[U_NAME] = strsave(argv[U_NAME]);
681         qargv[U_UID+1] = strsave(argv[U_UID]);
682         qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
683         qargv[U_LAST+1] = strsave(argv[U_LAST]);
684         qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
685         qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
686         qargv[U_STATE+1] = strsave(argv[U_STATE]);
687         qargv[U_MITID+1] = strsave(argv[U_MITID]);
688         qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
689         qargv[U_MODTIME+1] = NULL;
690     }
691     return(status);
692 }
693
694
695 int set_identity(message,retval)
696 struct msg *message;
697 char *retval;
698 {
699     int q_argc;                 /* Number of arguments to query */
700     char *q_argv[U_END];        /* Arguments to SMS query */
701     char *q_name;               /* Name of SMS query */
702     int status = SUCCESS;       /* General purpose error status */
703     char fstype_buf[7];         /* Buffer to hold fs_type, a 16 bit number */
704     char *login;                /* The login name the user wants */
705     register int i;             /* A counter */
706
707     /* Log that we are about to reserve a user. */
708     com_err(whoami, 0, "set_identity %s %s", 
709             message->first, message->last);
710     
711     /* Check to make sure that we can verify this user. */
712     status = verify_user(message,retval);
713     if (status == SUCCESS || status == UREG_NOT_ALLOWED)
714     {
715         status = SUCCESS;
716         /* Get the requested login name from leftover packet information. */
717         login = message->leftover;
718
719         /* Check the login name for validity.  The login name is currently
720            is allowed to contain lowercase letters and numbers in any
721            position and underscore characters in any position but the 
722            first. */
723         if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
724             status = UREG_INVALID_UNAME;
725     }
726     if (status == SUCCESS)
727         if (login[1] == '_')
728             status = UREG_INVALID_UNAME;
729     if (status == SUCCESS)
730     {
731         for (i = 0; i < strlen(login); i++)
732             if (!islower(login[i]) && !isdigit(login[i]) && 
733                 (login[i] != '_'))
734             {
735                 status = UREG_INVALID_UNAME;
736                 break;
737             }
738     }
739     if (status == SUCCESS)
740     {
741         /* Now that we have a valid user with a valid login... */
742
743         q_argv[0] = message->db.uid;
744         status = sms_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
745         if (status != SUCCESS) {
746             com_err(whoami, status, " while getting user info");
747             return(status);
748         }
749         q_argv[U_NAME+1] = login;
750         status = sms_query("update_user", U_MODTIME+1, q_argv,
751                            null_callproc, NULL);
752         switch (status)
753         {
754           case SMS_SUCCESS:
755             status = SUCCESS;
756             break;
757           case SMS_IN_USE:
758             status = UREG_LOGIN_USED;
759             break;
760           case SMS_DEADLOCK:
761             status = UREG_MISC_ERROR;
762             break;
763           default:
764             critical_alert(FAIL_INST,"%s returned from update_user.",
765                            error_message(status));
766             status = UREG_MISC_ERROR;
767             break;
768         }
769     }
770     if (status == SUCCESS)
771     {
772         /* SMS login was successfully created; try to reserve kerberos
773            principal. */
774         /* If this routine fails, store the login in the retval so
775            that it can be used in the client-side error message. */
776         if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
777             (void) strcpy(retval, login);
778     }
779
780     com_err(whoami, status, " returned from set_identity");
781     
782     return status;
783 }
784
785
786 void reg_com_err_hook(whoami, code, fmt, pvar)
787         char *whoami;
788         int code;
789         char *fmt;
790         caddr_t pvar;
791 {
792         if (whoami) {
793                 fputs(whoami, stderr);
794                 fputs(": ", stderr);
795         }
796         if (code) {
797                 fputs(error_message(code), stderr);
798         }
799         if (fmt) {
800                 _doprnt(fmt, pvar, stderr);
801         }
802         putc('\n', stderr);
803         fflush(stderr);
804 }
This page took 0.100956 seconds and 3 git commands to generate.