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