]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
catch deadlock errors
[moira.git] / reg_svr / reg_svr.c
CommitLineData
47baf534 1/*
3e9b5b7b 2 * $Source$
3 * $Author$
4 * $Header$
47baf534 5 *
0a5ff702 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>.
47baf534 9 *
3e9b5b7b 10 * Server for user registration with SMS and Kerberos.
47baf534 11 *
803d15cb 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.
47baf534 16 */
17
18#ifndef lint
19static char *rcsid_reg_svr_c = "$Header$";
20#endif lint
21
0a5ff702 22#include <mit-copyright.h>
a640951a 23#include "reg_svr.h"
f46fccfa 24#include "admin_server.h"
007fdd80 25#include "admin_err.h"
a9b2e5c9 26#include "krb_et.h"
47baf534 27
f46fccfa 28extern char admin_errmsg[];
47baf534 29
f3c010f8 30static char krbhst[BUFSIZ]; /* kerberos server name */
31static char krbrealm[REALM_SZ]; /* kerberos realm name */
3f5f9b08 32void reg_com_err_hook();
33
f3c010f8 34
bac67528 35main(argc,argv)
36 int argc;
37 char *argv[];
47baf534 38{
3e9b5b7b 39 struct msg message; /* Storage for parsed packet */
29bc4461 40 int status = SUCCESS; /* Error status */
bac67528 41 char retval[BUFSIZ]; /* Buffer to hold return message for client */
42
a640951a 43 void req_initialize(); /* Initialize request layer */
44 void get_request(); /* Get a request */
45 void report(); /* Respond to a request */
bac67528 46
a640951a 47 /* Initialize */
bac67528 48 whoami = argv[0];
a640951a 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
3e9b5b7b 55 /* Error messages sent one line at a time */
f46fccfa 56 setlinebuf(stderr);
3f5f9b08 57 setlinebuf(stdout);
58 set_com_err_hook(reg_com_err_hook);
47baf534 59
29bc4461 60 /* Initialize user registration error table for com_err */
47baf534 61 init_ureg_err_tbl();
3e9b5b7b 62
3e9b5b7b 63 /* Connect to the SMS server */
9a2d61b0 64 if ((status = sms_connect(SMS_SERVER)) != SMS_SUCCESS)
3e9b5b7b 65 {
bac67528 66 com_err(whoami, status, " on connect");
78eff417 67 exit(1);
68 }
3e9b5b7b 69
70 /* Authorize, telling the server who you are */
bac67528 71 if ((status = sms_auth(whoami)) != SMS_SUCCESS)
3e9b5b7b 72 {
bac67528 73 com_err(whoami, status, " on auth");
78eff417 74 exit(1);
75 }
a640951a 76
851819f1 77 if (status = krb_get_lrealm(krbrealm, 1)) {
a9b2e5c9 78 status += ERROR_TABLE_BASE_krb;
f3c010f8 79 com_err(whoami, status, " fetching kerberos realm");
80 exit(1);
81 }
a640951a 82
851819f1 83 if (status = krb_get_krbhst(krbhst, krbrealm, 1)) {
a9b2e5c9 84 status += ERROR_TABLE_BASE_krb;
f3c010f8 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 }
0349fd4d 94
95 journal = fopen(JOURNAL, "a");
96 if (journal == NULL) {
97 com_err(whoami, errno, " while opening journal file");
98 exit(1);
99 }
a640951a 100
101 /* Allow request layer to initialize */
102 req_initialize();
103
3e9b5b7b 104 /* Sit around waiting for requests from the client. */
105 for (;;)
106 {
a640951a 107 get_request(&message);
3e9b5b7b 108
3e9b5b7b 109 switch((int)message.request)
110 {
111 case UREG_VERIFY_USER:
bac67528 112 status = verify_user(&message,retval);
47baf534 113 break;
3e9b5b7b 114 case UREG_RESERVE_LOGIN:
bac67528 115 status = reserve_user(&message,retval);
47baf534 116 break;
3e9b5b7b 117 case UREG_SET_PASSWORD:
3f5f9b08 118 case UREG_GET_KRB:
bac67528 119 status = set_password(&message,retval);
47baf534 120 break;
3f5f9b08 121 case UREG_SET_IDENT:
122 status = set_identity(&message,retval);
123 break;
3e9b5b7b 124 default:
47baf534 125 status = UREG_UNKNOWN_REQUEST;
a640951a 126 critical_alert(FAIL_INST,"Unknown request %d from userreg.",
127 message.request);
47baf534 128 break;
129 }
47baf534 130
3e9b5b7b 131 /* Report what happened to client */
a640951a 132 report(status, retval);
47baf534 133 }
134}
135
eb39a9ea 136/* This is necessary so that this server can know where to put its
137 tickets. */
138char *tkt_string()
139{
140 return("/tmp/tkt_ureg");
141}
142
bac67528 143int parse_encrypted(message,data)
3e9b5b7b 144 struct msg *message; /* Formatted packet */
bac67528 145 struct db_data *data; /* Data from the SMS database */
3e9b5b7b 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
803d15cb 150 The plain text ID number was encrypted via EncryptID() resulting
151 in the form that would appear in the SMS database. This is
29bc4461 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.
3e9b5b7b 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
bac67528 160 decrypt the packet with this information. If it succeeds, it returns
29bc4461 161 zero and initializes all the fields of the formatted packet structure
162 that depend on the encrypted information. */
47baf534 163{
3e9b5b7b 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 */
bac67528 171 char *temp; /* A temporary string pointer */
172 int len; /* Keeps track of length left in packet */
29bc4461 173 int status = SUCCESS; /* Error status */
3e9b5b7b 174
bac67528 175#ifdef DEBUG
176 com_err(whoami,0,"Entering parse_encrypted");
177#endif
178
3e9b5b7b 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. */
bac67528 182 decrypt_len = (long)message->encrypted_len;
47baf534 183
3e9b5b7b 184 /* Get key from the one-way encrypted ID in the SMS database */
bac67528 185 string_to_key(data->mit_id, key);
3e9b5b7b 186 /* Get schedule from key */
47baf534 187 key_sched(key, sched);
3e9b5b7b 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. */
bac67528 191 pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, DECRYPT);
3e9b5b7b 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. */
29bc4461 201 (void) strncpy(idnumber,decrypt,(int)decrypt_len);
3e9b5b7b 202 /* Point temp to the end of the plain text ID number. */
47baf534 203 temp = decrypt + strlen(idnumber) + 1;
29bc4461 204 /* Find out how much more packet there is. */
bac67528 205 len = message->encrypted_len - (temp - decrypt);
29bc4461 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
3e9b5b7b 208 if we have the right key. */
29bc4461 209 (void) strncpy(hashid, temp, min(len, CRYPT_LEN));
3e9b5b7b 210 /* Point temp to the end of the encrypted ID field */
47baf534 211 temp += strlen(hashid) + 1;
3e9b5b7b 212 /* Find out how much more room there is. */
bac67528 213 len = message->encrypted_len - (temp - decrypt);
3e9b5b7b 214
bac67528 215 /* Now compare encrypted ID's don't match. */
803d15cb 216 if (strcmp(hashid, data->mit_id)) status = FAILURE;
29bc4461 217 if (status == SUCCESS)
3e9b5b7b 218 {
803d15cb 219 EncryptID(recrypt, idnumber, message->first, message->last);
bac67528 220 /* Now compare encrypted plain text to ID from database. */
803d15cb 221 if (strcmp(recrypt, data->mit_id)) status = FAILURE;
47baf534 222 }
3e9b5b7b 223
29bc4461 224 if (status == SUCCESS)
bac67528 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;
29bc4461 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));
bac67528 237 }
47baf534 238
bac67528 239#ifdef DEBUG
240 if (status)
29bc4461 241 com_err(whoami,status," parse_encrypted failed.");
bac67528 242 else
29bc4461 243 com_err(whoami,status,"parse_encrypted succeeded.");
bac67528 244#endif
47baf534 245
47baf534 246 return status;
247}
248
bac67528 249int 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
29bc4461 254 used by find_user to cache information about each user found. */
47baf534 255{
bac67528 256 struct db_data *data; /* Structure to store the information in */
29bc4461 257 int status = SUCCESS; /* Error status */
47baf534 258
bac67528 259#ifdef DEBUG
260 com_err(whoami,0,"Entering db_callproc.");
261#endif
262
29bc4461 263 if (argc != U_END)
3e9b5b7b 264 {
a640951a 265 critical_alert
266 (FAIL_INST,
267 "Wrong number of arguments returned from get_user_by_name.");
803d15cb 268 status = SMS_ABORT;
f46fccfa 269 }
bac67528 270 else
3e9b5b7b 271 {
bac67528 272 /* extract the needed information from the results of the SMS query */
273 data = (struct db_data *)malloc(sizeof(struct db_data));
29bc4461 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));
bac67528 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);
47baf534 286 }
bac67528 287
288 return status;
289}
3e9b5b7b 290
bac67528 291int 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{
803d15cb 297#define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */
bac67528 298 char *q_name; /* Name of query */
29bc4461 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 */
bac67528 302
303 struct save_queue *queue; /* Queue to hold SMS data */
304 struct db_data *data; /* Structure for data for one tuple */
29bc4461 305 short verified = FALSE; /* Have we verified the user? */
bac67528 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
29bc4461 311 if (status == SUCCESS)
3e9b5b7b 312 {
bac67528 313 /* Get ready to make an SMS query */
314 q_name = "get_user_by_name";
29bc4461 315 q_argc = GUBN_ARGS; /* #defined in this routine */
bac67528 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
803d15cb 326 fprintf(stderr," %d returned by get_user_by_name\n",status);
bac67528 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 */
29bc4461 337 verified = (parse_encrypted(message,data) == SUCCESS);
338 free((char *)data);
bac67528 339 }
340 }
29bc4461 341
342 /* Destroy the queue */
343 sq_destroy(queue);
47baf534 344 }
47baf534 345
bac67528 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
bac67528 358int verify_user(message,retval)
3e9b5b7b 359 struct msg *message;
bac67528 360 char *retval;
29bc4461 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
47baf534 365{
29bc4461 366 int status = SUCCESS; /* Return status */
bac67528 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().) */
bac67528 374
375 status = find_user(message);
376
377 /* If SMS coudn't find the user */
378 if (status == SMS_NO_MATCH)
f46fccfa 379 status = UREG_USER_NOT_FOUND;
bac67528 380 else if (status == SMS_SUCCESS)
3e9b5b7b 381 {
bac67528 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. */
29bc4461 385 if (message->db.mit_id[0] == NULL)
bac67528 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 {
29bc4461 393 case US_NO_LOGIN_YET:
bac67528 394 status = SUCCESS;
395 break;
29bc4461 396 case US_REGISTERED:
bac67528 397 status = UREG_ALREADY_REGISTERED;
398 break;
29bc4461 399 case US_NO_PASSWD:
bac67528 400 status = UREG_NO_PASSWD_YET;
401 break;
29bc4461 402 case US_DELETED:
bac67528 403 status = UREG_DELETED;
404 break;
29bc4461 405 case US_NOT_ALLOWED:
bac67528 406 status = UREG_NOT_ALLOWED;
407 break;
3f5f9b08 408 case US_ENROLLED:
409 status = UREG_ENROLLED;
410 break;
411 case US_ENROLL_NOT_ALLOWED:
412 status = UREG_ENROLL_NOT_ALLOWED;
413 break;
bac67528 414 default:
415 status = UREG_MISC_ERROR;
3f5f9b08 416 critical_alert(FAIL_INST,"Bad user state %d for login %s.",
417 message->db.reg_status, message->db.login);
bac67528 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. */
29bc4461 422 (void) strcpy(retval,message->db.login);
bac67528 423 }
47baf534 424 }
3e9b5b7b 425
29bc4461 426 com_err(whoami,status," returned from verify_user");
bac67528 427
47baf534 428 return status;
429}
bac67528 430
431int ureg_get_tkt()
47baf534 432{
29bc4461 433 int status = SUCCESS; /* Return status */
bac67528 434
435 /* Get keys for interacting with Kerberos admin server. */
f3c010f8 436 /* principal, instance, realm, service, service instance, life, file */
851819f1 437 if (status = krb_get_svc_in_tkt("register", "sms", krbrealm, "changepw",
f3c010f8 438 krbhst, 1, KEYFILE))
a9b2e5c9 439 status += ERROR_TABLE_BASE_krb;
bac67528 440
803d15cb 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
bac67528 447 return status;
47baf534 448}
449
bac67528 450int null_callproc(argc,argv,message)
451 int argc;
452 char *argv[];
3e9b5b7b 453 char *message;
bac67528 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. */
47baf534 456{
a640951a 457 critical_alert(FAIL_INST,"Something returned from an update query.");
803d15cb 458 return FAILURE;
47baf534 459}
460
bac67528 461int do_admin_call(login, passwd, uid)
29bc4461 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. */
47baf534 467{
bac67528 468 int status; /* Error status */
469 char uid_buf[20]; /* Holds uid for kerberos */
470
803d15cb 471 com_err(whoami,0,"Entering do_admin_call");
472
bac67528 473 if ((status = ureg_get_tkt()) == SUCCESS)
3e9b5b7b 474 {
bac67528 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. */
803d15cb 479 /* 13 chars of placebo for backwards-compatability - the admin
480 server protocol reqires this. */
bac67528 481 bzero(uid_buf,sizeof(uid_buf));
f3c010f8 482 (void) sprintf(uid_buf, "%13s", uid);
bac67528 483
484 if ((status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, login,
485 "", passwd, uid_buf)) != KSUCCESS)
3e9b5b7b 486 {
29bc4461 487 com_err(whoami,status," server error: %s",admin_errmsg);
bac67528 488
489 if (strcmp(admin_errmsg,
490 "Principal already in kerberos database.") == 0)
491 status = UREG_KRB_TAKEN;
a640951a 492 critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.",
493 login);
47baf534 494 }
47baf534 495 }
bac67528 496
497 dest_tkt();
851819f1 498 com_err(whoami,status," returned from do_admin_call");
bac67528 499 return status;
47baf534 500}
3e9b5b7b 501
bac67528 502int reserve_user(message,retval)
503 struct msg *message;
504 char *retval;
47baf534 505{
bac67528 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 */
29bc4461 509 int status = SUCCESS; /* General purpose error status */
bac67528 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 */
bac67528 513
803d15cb 514 /* Log that we are about to reserve a user. */
29bc4461 515 com_err(whoami, 0, "reserve_user %s %s",
bac67528 516 message->first, message->last);
3e9b5b7b 517
bac67528 518 /* Check to make sure that we can verify this user. */
519 if ((status = verify_user(message,retval)) == SUCCESS)
3e9b5b7b 520 {
29bc4461 521 /* Get the requested login name from leftover packet information. */
bac67528 522 login = message->leftover;
29bc4461 523
524 /* Check the login name for validity. The login name is currently
525 is allowed to contain lowercase letters and numbers in any
97ee0ded 526 position and underscore characters in any position but the
527 first. */
29bc4461 528 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
bac67528 529 status = UREG_INVALID_UNAME;
47baf534 530 }
29bc4461 531 if (status == SUCCESS)
5fff8167 532 if (login[1] == '_')
29bc4461 533 status = UREG_INVALID_UNAME;
534 if (status == SUCCESS)
3e9b5b7b 535 {
803d15cb 536 for (i = 0; i < strlen(login); i++)
5fff8167 537 if (!islower(login[i]) && !isdigit(login[i]) &&
538 (login[i] != '_'))
803d15cb 539 {
540 status = UREG_INVALID_UNAME;
541 break;
542 }
47baf534 543 }
29bc4461 544 if (status == SUCCESS)
3e9b5b7b 545 {
bac67528 546 /* Now that we have a valid user with a valid login... */
547
548 /* First, try to reserve the user in SMS. */
29bc4461 549 (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
bac67528 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;
29bc4461 555 status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
bac67528 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;
62ba0b73 564 case SMS_DEADLOCK:
565 status = UREG_MISC_ERROR;
566 break;
bac67528 567 default:
a640951a 568 critical_alert(FAIL_INST,"%s returned from register_user.",
569 error_message(status));
9700b15a 570 status = UREG_MISC_ERROR;
bac67528 571 break;
572 }
47baf534 573 }
29bc4461 574 if (status == SUCCESS)
3e9b5b7b 575 {
bac67528 576 /* SMS login was successfully created; try to reserve kerberos
577 principal. */
29bc4461 578 /* If this routine fails, store the login in the retval so
bac67528 579 that it can be used in the client-side error message. */
580 if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
29bc4461 581 (void) strcpy(retval, login);
47baf534 582 }
bac67528 583
29bc4461 584 com_err(whoami, status, " returned from reserve_user");
bac67528 585
47baf534 586 return status;
bac67528 587}
47baf534 588
3f5f9b08 589int set_final_status(message)
590struct msg *message;
803d15cb 591 /* This routine updates a user's registration status to fully
29bc4461 592 registered. */
47baf534 593{
3f5f9b08 594 char *login;
bac67528 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 */
29bc4461 598 char state[7]; /* Can hold a 16 bit integer */
bac67528 599 int status; /* Error status */
600
3f5f9b08 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);
bac67528 610
611 q_name = "update_user_status";
612 q_argc = 2;
613 q_argv[0] = login;
29bc4461 614 q_argv[1] = state;
bac67528 615 if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
62ba0b73 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 }
29bc4461 623 com_err(whoami,status," returned from set_final_status");
f46fccfa 624 return status;
bac67528 625}
f46fccfa 626
bac67528 627
628int 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. */
47baf534 632{
29bc4461 633 int status = SUCCESS; /* Return status */
bac67528 634 char *passwd; /* User's password */
bac67528 635
29bc4461 636 com_err(whoami, 0, " set_password %s %s",
bac67528 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)
3e9b5b7b 646 {
bac67528 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 */
29bc4461 656 (void) strcpy(retval,message->db.login);
bac67528 657 else
658 /* Otherwise, mark user as finished. */
3f5f9b08 659 status = set_final_status(message);
bac67528 660 }
29bc4461 661 com_err(whoami, status, " returned from set_passwd");
47baf534 662
bac67528 663 return status;
664}
3f5f9b08 665
666
667int getuserinfo(argc, argv, qargv)
668int argc;
669char **argv;
670char **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
694int set_identity(message,retval)
695struct msg *message;
696char *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;
62ba0b73 759 case SMS_DEADLOCK:
760 status = UREG_MISC_ERROR;
761 break;
3f5f9b08 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
785void 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.664466 seconds and 5 git commands to generate.