]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
do com_err stuff so that logging works OK;
[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;
564 default:
a640951a 565 critical_alert(FAIL_INST,"%s returned from register_user.",
566 error_message(status));
9700b15a 567 status = UREG_MISC_ERROR;
bac67528 568 break;
569 }
47baf534 570 }
29bc4461 571 if (status == SUCCESS)
3e9b5b7b 572 {
bac67528 573 /* SMS login was successfully created; try to reserve kerberos
574 principal. */
29bc4461 575 /* If this routine fails, store the login in the retval so
bac67528 576 that it can be used in the client-side error message. */
577 if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
29bc4461 578 (void) strcpy(retval, login);
47baf534 579 }
bac67528 580
29bc4461 581 com_err(whoami, status, " returned from reserve_user");
bac67528 582
47baf534 583 return status;
bac67528 584}
47baf534 585
3f5f9b08 586int set_final_status(message)
587struct msg *message;
803d15cb 588 /* This routine updates a user's registration status to fully
29bc4461 589 registered. */
47baf534 590{
3f5f9b08 591 char *login;
bac67528 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 */
29bc4461 595 char state[7]; /* Can hold a 16 bit integer */
bac67528 596 int status; /* Error status */
597
3f5f9b08 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);
bac67528 607
608 q_name = "update_user_status";
609 q_argc = 2;
610 q_argv[0] = login;
29bc4461 611 q_argv[1] = state;
bac67528 612 if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
613 (char *)0)) != SMS_SUCCESS)
a640951a 614 critical_alert(FAIL_INST,"%s returned from update_user_status.",
615 error_message(status));
3e9b5b7b 616
29bc4461 617 com_err(whoami,status," returned from set_final_status");
f46fccfa 618 return status;
bac67528 619}
f46fccfa 620
bac67528 621
622int 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. */
47baf534 626{
29bc4461 627 int status = SUCCESS; /* Return status */
bac67528 628 char *passwd; /* User's password */
bac67528 629
29bc4461 630 com_err(whoami, 0, " set_password %s %s",
bac67528 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)
3e9b5b7b 640 {
bac67528 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 */
29bc4461 650 (void) strcpy(retval,message->db.login);
bac67528 651 else
652 /* Otherwise, mark user as finished. */
3f5f9b08 653 status = set_final_status(message);
bac67528 654 }
29bc4461 655 com_err(whoami, status, " returned from set_passwd");
47baf534 656
bac67528 657 return status;
658}
3f5f9b08 659
660
661int getuserinfo(argc, argv, qargv)
662int argc;
663char **argv;
664char **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
688int set_identity(message,retval)
689struct msg *message;
690char *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
776void 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.346052 seconds and 5 git commands to generate.