]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
moved directory definitions
[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
6eafbf8b 95 journal = fopen(REGJOURNAL, "a");
0349fd4d 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;
d962b222 492 if (status != ETIMEDOUT)
493 critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.",
494 login);
47baf534 495 }
47baf534 496 }
bac67528 497
498 dest_tkt();
851819f1 499 com_err(whoami,status," returned from do_admin_call");
bac67528 500 return status;
47baf534 501}
3e9b5b7b 502
bac67528 503int reserve_user(message,retval)
504 struct msg *message;
505 char *retval;
47baf534 506{
bac67528 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 */
29bc4461 510 int status = SUCCESS; /* General purpose error status */
bac67528 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 */
bac67528 514
803d15cb 515 /* Log that we are about to reserve a user. */
29bc4461 516 com_err(whoami, 0, "reserve_user %s %s",
bac67528 517 message->first, message->last);
3e9b5b7b 518
bac67528 519 /* Check to make sure that we can verify this user. */
520 if ((status = verify_user(message,retval)) == SUCCESS)
3e9b5b7b 521 {
29bc4461 522 /* Get the requested login name from leftover packet information. */
bac67528 523 login = message->leftover;
29bc4461 524
525 /* Check the login name for validity. The login name is currently
526 is allowed to contain lowercase letters and numbers in any
97ee0ded 527 position and underscore characters in any position but the
528 first. */
29bc4461 529 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
bac67528 530 status = UREG_INVALID_UNAME;
47baf534 531 }
29bc4461 532 if (status == SUCCESS)
5fff8167 533 if (login[1] == '_')
29bc4461 534 status = UREG_INVALID_UNAME;
535 if (status == SUCCESS)
3e9b5b7b 536 {
803d15cb 537 for (i = 0; i < strlen(login); i++)
5fff8167 538 if (!islower(login[i]) && !isdigit(login[i]) &&
539 (login[i] != '_'))
803d15cb 540 {
541 status = UREG_INVALID_UNAME;
542 break;
543 }
47baf534 544 }
29bc4461 545 if (status == SUCCESS)
3e9b5b7b 546 {
bac67528 547 /* Now that we have a valid user with a valid login... */
548
549 /* First, try to reserve the user in SMS. */
29bc4461 550 (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
bac67528 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;
29bc4461 556 status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
bac67528 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;
62ba0b73 565 case SMS_DEADLOCK:
566 status = UREG_MISC_ERROR;
567 break;
bac67528 568 default:
a640951a 569 critical_alert(FAIL_INST,"%s returned from register_user.",
570 error_message(status));
9700b15a 571 status = UREG_MISC_ERROR;
bac67528 572 break;
573 }
47baf534 574 }
29bc4461 575 if (status == SUCCESS)
3e9b5b7b 576 {
bac67528 577 /* SMS login was successfully created; try to reserve kerberos
578 principal. */
29bc4461 579 /* If this routine fails, store the login in the retval so
bac67528 580 that it can be used in the client-side error message. */
581 if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
29bc4461 582 (void) strcpy(retval, login);
47baf534 583 }
bac67528 584
29bc4461 585 com_err(whoami, status, " returned from reserve_user");
bac67528 586
47baf534 587 return status;
bac67528 588}
47baf534 589
3f5f9b08 590int set_final_status(message)
591struct msg *message;
803d15cb 592 /* This routine updates a user's registration status to fully
29bc4461 593 registered. */
47baf534 594{
3f5f9b08 595 char *login;
bac67528 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 */
29bc4461 599 char state[7]; /* Can hold a 16 bit integer */
bac67528 600 int status; /* Error status */
601
3f5f9b08 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);
bac67528 611
612 q_name = "update_user_status";
613 q_argc = 2;
614 q_argv[0] = login;
29bc4461 615 q_argv[1] = state;
bac67528 616 if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
62ba0b73 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 }
29bc4461 624 com_err(whoami,status," returned from set_final_status");
f46fccfa 625 return status;
bac67528 626}
f46fccfa 627
bac67528 628
629int 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. */
47baf534 633{
29bc4461 634 int status = SUCCESS; /* Return status */
bac67528 635 char *passwd; /* User's password */
bac67528 636
29bc4461 637 com_err(whoami, 0, " set_password %s %s",
bac67528 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)
3e9b5b7b 647 {
bac67528 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 */
29bc4461 657 (void) strcpy(retval,message->db.login);
bac67528 658 else
659 /* Otherwise, mark user as finished. */
3f5f9b08 660 status = set_final_status(message);
bac67528 661 }
29bc4461 662 com_err(whoami, status, " returned from set_passwd");
47baf534 663
bac67528 664 return status;
665}
3f5f9b08 666
667
668int getuserinfo(argc, argv, qargv)
669int argc;
670char **argv;
671char **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
695int set_identity(message,retval)
696struct msg *message;
697char *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;
62ba0b73 760 case SMS_DEADLOCK:
761 status = UREG_MISC_ERROR;
762 break;
3f5f9b08 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
786void 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.193547 seconds and 5 git commands to generate.