]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
make the install's -c
[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 *
40174425 10 * Server for user registration with Moira 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
40174425 14 * Moira server as it is linked with libsmsglue which bypasses
803d15cb 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>
40174425 23#include <stdio.h>
24#include <strings.h>
25#include <ctype.h>
26#include <sys/types.h>
27#include <sys/file.h>
28#include <krb.h>
29#include <des.h>
30#include <kadm.h>
31#include <kadm_err.h>
32#include <krb_err.h>
33#include <errno.h>
34#include "sms.h"
35#include "sms_app.h"
a640951a 36#include "reg_svr.h"
47baf534 37
f46fccfa 38extern char admin_errmsg[];
47baf534 39
3f5f9b08 40void reg_com_err_hook();
41
bac67528 42main(argc,argv)
43 int argc;
44 char *argv[];
47baf534 45{
3e9b5b7b 46 struct msg message; /* Storage for parsed packet */
29bc4461 47 int status = SUCCESS; /* Error status */
bac67528 48 char retval[BUFSIZ]; /* Buffer to hold return message for client */
49
a640951a 50 void req_initialize(); /* Initialize request layer */
51 void get_request(); /* Get a request */
52 void report(); /* Respond to a request */
bac67528 53
a640951a 54 /* Initialize */
bac67528 55 whoami = argv[0];
a640951a 56
3e9b5b7b 57 /* Error messages sent one line at a time */
f46fccfa 58 setlinebuf(stderr);
3f5f9b08 59 setlinebuf(stdout);
60 set_com_err_hook(reg_com_err_hook);
47baf534 61
40174425 62 /* Initialize com_err error tables */
47baf534 63 init_ureg_err_tbl();
40174425 64 init_krb_err_tbl();
65 init_kadm_err_tbl();
3e9b5b7b 66
40174425 67 /* Use com_err or output to stderr for all log messages. */
68#ifdef DEBUG
69 com_err(whoami, 0, "*** Debugging messages enabled. ***");
70#endif DEBUG
71
72 /* Set the name of our kerberos ticket file */
73 krb_set_tkt_string("/tmp/tkt_ureg");
74
75 /* Connect to the Moira server */
9a2d61b0 76 if ((status = sms_connect(SMS_SERVER)) != SMS_SUCCESS)
3e9b5b7b 77 {
40174425 78 com_err(whoami, status, " on sms_connect");
78eff417 79 exit(1);
80 }
3e9b5b7b 81
82 /* Authorize, telling the server who you are */
bac67528 83 if ((status = sms_auth(whoami)) != SMS_SUCCESS)
3e9b5b7b 84 {
40174425 85 com_err(whoami, status, " on sms_auth");
78eff417 86 exit(1);
87 }
a640951a 88
6eafbf8b 89 journal = fopen(REGJOURNAL, "a");
0349fd4d 90 if (journal == NULL) {
91 com_err(whoami, errno, " while opening journal file");
92 exit(1);
93 }
a640951a 94
95 /* Allow request layer to initialize */
96 req_initialize();
97
3e9b5b7b 98 /* Sit around waiting for requests from the client. */
99 for (;;)
100 {
a640951a 101 get_request(&message);
3e9b5b7b 102
3e9b5b7b 103 switch((int)message.request)
104 {
105 case UREG_VERIFY_USER:
bac67528 106 status = verify_user(&message,retval);
47baf534 107 break;
3e9b5b7b 108 case UREG_RESERVE_LOGIN:
bac67528 109 status = reserve_user(&message,retval);
47baf534 110 break;
3e9b5b7b 111 case UREG_SET_PASSWORD:
3f5f9b08 112 case UREG_GET_KRB:
bac67528 113 status = set_password(&message,retval);
47baf534 114 break;
3f5f9b08 115 case UREG_SET_IDENT:
116 status = set_identity(&message,retval);
117 break;
3e9b5b7b 118 default:
47baf534 119 status = UREG_UNKNOWN_REQUEST;
a640951a 120 critical_alert(FAIL_INST,"Unknown request %d from userreg.",
121 message.request);
47baf534 122 break;
123 }
47baf534 124
3e9b5b7b 125 /* Report what happened to client */
a640951a 126 report(status, retval);
47baf534 127 }
128}
129
bac67528 130int parse_encrypted(message,data)
3e9b5b7b 131 struct msg *message; /* Formatted packet */
40174425 132 struct db_data *data; /* Data from the Moira database */
3e9b5b7b 133/* This routine makes sure that the ID from the database matches
134 the ID sent accross in the packet. The information in the packet
135 was created in the following way:
136
803d15cb 137 The plain text ID number was encrypted via EncryptID() resulting
40174425 138 in the form that would appear in the Moira database. This is
29bc4461 139 concatinated to the plain text ID so that the ID string contains plain
140 text ID followed by a null followed by the encrypted ID. Other
141 information such as the username or password is appended. The whole
142 thing is then DES encrypted using the encrypted ID as the source of
143 the key.
3e9b5b7b 144
145 This routine tries each encrypted ID in the database that belongs
146 to someone with this user's first and last name and tries to
bac67528 147 decrypt the packet with this information. If it succeeds, it returns
29bc4461 148 zero and initializes all the fields of the formatted packet structure
149 that depend on the encrypted information. */
47baf534 150{
3e9b5b7b 151 C_Block key; /* The key for DES en/decryption */
152 Key_schedule sched; /* En/decryption schedule */
153 static char decrypt[BUFSIZ]; /* Buffer to hold decrypted information */
154 long decrypt_len; /* Length of decypted ID information */
155 char recrypt[14]; /* Buffer to hold re-encrypted information */
156 static char hashid[14]; /* Buffer to hold one-way encrypted ID */
157 char idnumber[BUFSIZ]; /* Buffer to hold plain-text ID */
bac67528 158 char *temp; /* A temporary string pointer */
159 int len; /* Keeps track of length left in packet */
29bc4461 160 int status = SUCCESS; /* Error status */
3e9b5b7b 161
bac67528 162#ifdef DEBUG
40174425 163 com_err(whoami, 0, "Entering parse_encrypted");
bac67528 164#endif
165
3e9b5b7b 166 /* Make the decrypted information length the same as the encrypted
167 information length. Both are integral multples of eight bytes
168 because of the DES encryption routines. */
bac67528 169 decrypt_len = (long)message->encrypted_len;
47baf534 170
40174425 171 /* Get key from the one-way encrypted ID in the Moira database */
bac67528 172 string_to_key(data->mit_id, key);
3e9b5b7b 173 /* Get schedule from key */
47baf534 174 key_sched(key, sched);
3e9b5b7b 175 /* Decrypt information from packet using this key. Since decrypt_len
176 is an integral multiple of eight bytes, it will probably be null-
177 padded. */
bac67528 178 pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, DECRYPT);
3e9b5b7b 179
180 /* Extract the plain text and encrypted ID fields from the decrypted
181 packet information. */
182 /* Since the decrypted information starts with the plain-text ID
183 followed by a null, if the decryption worked, this will only
184 copy the plain text part of the decrypted information. It is
185 important that strncpy be used because if we are not using the
186 correct key, there is no guarantee that a null will occur
187 anywhere in the string. */
29bc4461 188 (void) strncpy(idnumber,decrypt,(int)decrypt_len);
3e9b5b7b 189 /* Point temp to the end of the plain text ID number. */
47baf534 190 temp = decrypt + strlen(idnumber) + 1;
29bc4461 191 /* Find out how much more packet there is. */
bac67528 192 len = message->encrypted_len - (temp - decrypt);
29bc4461 193 /* Copy the next CRYPT_LEN bytes of the decrypted information into
194 hashid if there are CRYPT_LEN more bytes to copy. There will be
3e9b5b7b 195 if we have the right key. */
29bc4461 196 (void) strncpy(hashid, temp, min(len, CRYPT_LEN));
3e9b5b7b 197 /* Point temp to the end of the encrypted ID field */
47baf534 198 temp += strlen(hashid) + 1;
3e9b5b7b 199 /* Find out how much more room there is. */
bac67528 200 len = message->encrypted_len - (temp - decrypt);
3e9b5b7b 201
bac67528 202 /* Now compare encrypted ID's don't match. */
803d15cb 203 if (strcmp(hashid, data->mit_id)) status = FAILURE;
29bc4461 204 if (status == SUCCESS)
3e9b5b7b 205 {
803d15cb 206 EncryptID(recrypt, idnumber, message->first, message->last);
bac67528 207 /* Now compare encrypted plain text to ID from database. */
803d15cb 208 if (strcmp(recrypt, data->mit_id)) status = FAILURE;
47baf534 209 }
3e9b5b7b 210
29bc4461 211 if (status == SUCCESS)
bac67528 212 {
213 /* We made it. Now we can finish initializing message. */
214 /* Point leftover to whatever is left over! */
215 message->leftover = temp;
216 message->leftover_len = len;
217 /* Since we know we have the right user, fill in the information
40174425 218 from the Moira database. */
bac67528 219 message->db.reg_status = data->reg_status;
29bc4461 220 (void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid));
221 (void) strncpy(message->db.mit_id,data->mit_id,
222 sizeof(message->db.mit_id));
223 (void) strncpy(message->db.login,data->login, sizeof(message->db.login));
bac67528 224 }
47baf534 225
bac67528 226#ifdef DEBUG
227 if (status)
40174425 228 com_err(whoami, status, " in parse_encrypted");
bac67528 229 else
40174425 230 com_err(whoami, status, "parse_encrypted succeeded");
bac67528 231#endif
47baf534 232
47baf534 233 return status;
234}
235
bac67528 236int db_callproc(argc,argv,queue)
40174425 237 int argc; /* Number of arguments returned by Moira */
238 char *argv[]; /* Arguments returned by Moira */
bac67528 239 struct save_queue *queue; /* Queue to save information in */
240/* This function is called by sms_query after each tuple found. It is
29bc4461 241 used by find_user to cache information about each user found. */
47baf534 242{
bac67528 243 struct db_data *data; /* Structure to store the information in */
29bc4461 244 int status = SUCCESS; /* Error status */
47baf534 245
bac67528 246#ifdef DEBUG
40174425 247 com_err(whoami, 0, "Entering db_callproc.");
bac67528 248#endif
249
29bc4461 250 if (argc != U_END)
3e9b5b7b 251 {
a640951a 252 critical_alert
253 (FAIL_INST,
254 "Wrong number of arguments returned from get_user_by_name.");
803d15cb 255 status = SMS_ABORT;
f46fccfa 256 }
bac67528 257 else
3e9b5b7b 258 {
40174425 259 /* extract the needed information from the results of the Moira query */
bac67528 260 data = (struct db_data *)malloc(sizeof(struct db_data));
29bc4461 261 data->reg_status = atoi(argv[U_STATE]);
262 (void) strncpy(data->login,argv[U_NAME],sizeof(data->login));
263 (void) strncpy(data->mit_id,argv[U_MITID],sizeof(data->mit_id));
264 (void) strncpy(data->uid,argv[U_UID],sizeof(data->uid));
bac67528 265#ifdef DEBUG
266 fprintf(stderr,"Found in database:\n");
267 fprintf(stderr," Registration status: %d\n",data->reg_status);
268 fprintf(stderr," login: %s\n",data->login);
269 fprintf(stderr," MIT ID: %s\n",data->mit_id);
270 fprintf(stderr," uid: %s\n",data->uid);
271#endif
272 sq_save_data(queue,data);
47baf534 273 }
bac67528 274
275 return status;
276}
3e9b5b7b 277
bac67528 278int find_user(message)
279 struct msg *message; /* Formatted packet structure */
280/* This routine verifies that a user is allowed to register by finding
40174425 281 him/her in the Moira database. It returns the status of the Moira
bac67528 282 query that it calls. */
283{
803d15cb 284#define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */
bac67528 285 char *q_name; /* Name of query */
29bc4461 286 int q_argc; /* Number of arguments for query */
287 char *q_argv[GUBN_ARGS]; /* Arguments to query */
288 int status = SUCCESS; /* Query return status */
bac67528 289
40174425 290 struct save_queue *queue; /* Queue to hold Moira data */
bac67528 291 struct db_data *data; /* Structure for data for one tuple */
29bc4461 292 short verified = FALSE; /* Have we verified the user? */
bac67528 293
294 /* Zero the mit_id field in the formatted packet structure. This
295 being zeroed means that no user was found. */
296 bzero(message->db.mit_id,sizeof(message->db.mit_id));
297
29bc4461 298 if (status == SUCCESS)
3e9b5b7b 299 {
40174425 300 /* Get ready to make an Moira query */
bac67528 301 q_name = "get_user_by_name";
29bc4461 302 q_argc = GUBN_ARGS; /* #defined in this routine */
bac67528 303 q_argv[0] = message->first;
304 q_argv[1] = message->last;
305
306 /* Create queue to hold information */
307 queue = sq_create();
308
309 /* Do it */
310 status = sms_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
311
312#ifdef DEBUG
803d15cb 313 fprintf(stderr," %d returned by get_user_by_name\n",status);
bac67528 314#endif
315
316 if (status == SMS_SUCCESS)
317 {
318 /* Traverse the list, freeing data as we go. If sq_get_data()
319 returns zero if there is no more data on the queue. */
320 while (sq_get_data(queue,&data))
321 {
322 if (!verified)
323 /* parse_encrypted returns zero on success */
29bc4461 324 verified = (parse_encrypted(message,data) == SUCCESS);
325 free((char *)data);
bac67528 326 }
327 }
29bc4461 328
329 /* Destroy the queue */
330 sq_destroy(queue);
47baf534 331 }
47baf534 332
bac67528 333#ifdef DEBUG
334 fprintf(stderr,"Returned from find_user\n");
335 fprintf(stderr," MIT ID: %s\n", message->db.mit_id);
336 fprintf(stderr," Registration status: %d\n",message->db.reg_status);
337 fprintf(stderr," uid: %s\n",message->db.uid);
338 fprintf(stderr," login: %s\n",message->db.login);
339 fprintf(stderr," Status from query: %d\n",status);
340#endif DEBGUG
341
342 return status;
343}
344
bac67528 345int verify_user(message,retval)
3e9b5b7b 346 struct msg *message;
bac67528 347 char *retval;
29bc4461 348 /* This routine determines whether a user is in the databse and returns
349 his state so that other routines can figure out whether he is the
350 correct state for various transactions. */
351
47baf534 352{
29bc4461 353 int status = SUCCESS; /* Return status */
bac67528 354
355 /* Log that we are about to veryify user */
40174425 356 com_err(whoami, 0, "verifying user %s %s",message->first,message->last);
bac67528 357
358 /* Figure out what user (if any) can be found based on the
359 encrypted information in the packet. (See the comment on
360 parse_encrypted().) */
bac67528 361
362 status = find_user(message);
363
40174425 364 /* If Moira coudn't find the user */
bac67528 365 if (status == SMS_NO_MATCH)
f46fccfa 366 status = UREG_USER_NOT_FOUND;
bac67528 367 else if (status == SMS_SUCCESS)
3e9b5b7b 368 {
bac67528 369 /* If the information sent over in the packet did not point to a
370 valid user, the mit_id field in the formatted packet structure
371 will be empty. */
29bc4461 372 if (message->db.mit_id[0] == NULL)
bac67528 373 status = UREG_USER_NOT_FOUND;
374 /* If the user was found but the registration has already started,
375 use this as the status */
376 else
377 {
378 switch (message->db.reg_status)
379 {
29bc4461 380 case US_NO_LOGIN_YET:
bac67528 381 status = SUCCESS;
382 break;
29bc4461 383 case US_REGISTERED:
bac67528 384 status = UREG_ALREADY_REGISTERED;
385 break;
29bc4461 386 case US_NO_PASSWD:
bac67528 387 status = UREG_NO_PASSWD_YET;
388 break;
29bc4461 389 case US_DELETED:
bac67528 390 status = UREG_DELETED;
391 break;
29bc4461 392 case US_NOT_ALLOWED:
bac67528 393 status = UREG_NOT_ALLOWED;
394 break;
3f5f9b08 395 case US_ENROLLED:
396 status = UREG_ENROLLED;
397 break;
398 case US_ENROLL_NOT_ALLOWED:
399 status = UREG_ENROLL_NOT_ALLOWED;
400 break;
bac67528 401 default:
402 status = UREG_MISC_ERROR;
3f5f9b08 403 critical_alert(FAIL_INST,"Bad user state %d for login %s.",
404 message->db.reg_status, message->db.login);
bac67528 405 break;
406 }
407 /* Set retval to the login name so that the client can use
408 it in the error message it will give the user. */
29bc4461 409 (void) strcpy(retval,message->db.login);
bac67528 410 }
47baf534 411 }
3e9b5b7b 412
40174425 413 if (status)
414 com_err(whoami, status, " returned from verify_user");
415 else
416 com_err(whoami, 0, "User verified");
bac67528 417
47baf534 418 return status;
419}
bac67528 420
40174425 421int ureg_kadm_init()
47baf534 422{
40174425 423 unsigned int status = SUCCESS; /* Return status */
424 static char krbrealm[REALM_SZ]; /* kerberos realm name */
425 static int inited = 0;
426
427#ifdef DEBUG
428 com_err(whoami, 0, "Entering ureg_kadm_init");
429#endif DEBUG
430
431 if (!inited) {
432 inited++;
433 bzero(krbrealm, sizeof(krbrealm));
434 if (status = krb_get_lrealm(krbrealm, 1)) {
435 status += krb_err_base;
436 com_err(whoami, status, " fetching kerberos realm");
437 exit(1);
438 }
439 }
bac67528 440
441 /* Get keys for interacting with Kerberos admin server. */
f3c010f8 442 /* principal, instance, realm, service, service instance, life, file */
40174425 443 if (status = krb_get_svc_in_tkt("register", "sms", krbrealm, PWSERV_NAME,
444 KADM_SINST, 1, KEYFILE))
445 status += krb_err_base;
446
447 if (status != SUCCESS)
448 com_err(whoami, status, " while get admin tickets");
803d15cb 449#ifdef DEBUG
40174425 450 else {
451 com_err(whoami, status, "Succeeded in getting admin tickets");
452 }
803d15cb 453#endif
40174425 454
455 if (status == SUCCESS) {
456 if ((status = kadm_init_link(PWSERV_NAME, KADM_SINST, krbrealm)) !=
457 KADM_SUCCESS) {
458 com_err(whoami, status, " while initializing kadmin connection");
459 }
460 }
461
bac67528 462 return status;
47baf534 463}
464
bac67528 465int null_callproc(argc,argv,message)
466 int argc;
467 char *argv[];
3e9b5b7b 468 char *message;
bac67528 469 /* This routine is a null callback that should be used for queries that
470 do not return tuples. If it ever gets called, something is wrong. */
47baf534 471{
a640951a 472 critical_alert(FAIL_INST,"Something returned from an update query.");
803d15cb 473 return FAILURE;
47baf534 474}
475
40174425 476/*
477 * This routine reserves a principal in kerberos by setting up a
478 * principal with a random initial key.
479 */
480int reserve_krb(login)
481 char *login;
47baf534 482{
40174425 483 int status = SUCCESS;
484 Kadm_vals new;
485 des_cblock key;
486 u_long *lkey = (u_long *)key;
bac67528 487
40174425 488#ifdef DEBUG
489 com_err(whoami, 0, "Entering reserve_krb");
490#endif DEBUG
803d15cb 491
40174425 492 if ((status = ureg_kadm_init()) == SUCCESS) {
493 bzero((char *)&new, sizeof(new));
494 SET_FIELD(KADM_DESKEY, new.fields);
495 SET_FIELD(KADM_NAME, new.fields);
bac67528 496
40174425 497 (void) des_random_key(key);
498 new.key_low = htonl(lkey[0]);
499 new.key_high = htonl(lkey[1]);
500 strcpy(new.name, login);
501
502 com_err(whoami, 0, "Creating kerberos principal for %s", login);
503 status = kadm_add(&new);
504 if (status != KADM_SUCCESS)
505 com_err(whoami, status, " while reserving principal");
506
507 bzero((char *)&new, sizeof(new));
508 }
509
510 dest_tkt();
511
512 return(status);
513}
514
515/*
516 * This routine reserves a principal in kerberos by setting up a
517 * principal with a random initial key.
518 */
519int setpass_krb(login, password)
520 char *login;
521 char *password;
522{
523 int status = SUCCESS;
524 Kadm_vals new;
525 des_cblock key;
526 u_long *lkey = (u_long *)key;
527
528 if ((status = ureg_kadm_init()) == SUCCESS) {
529 bzero((char *)&new, sizeof(new));
530 SET_FIELD(KADM_DESKEY, new.fields);
531 SET_FIELD(KADM_NAME, new.fields);
532
533 (void) des_string_to_key(password, key);
534 new.key_low = htonl(lkey[0]);
535 new.key_high = htonl(lkey[1]);
536 strcpy(new.name, login);
537
538 com_err(whoami, 0, "Setting password for %s", login);
539 /* First arguement is not used if user has modify privileges */
540 if ((status = kadm_mod(&new, &new)) != KADM_SUCCESS) {
541 if (status == KADM_NOENTRY) {
542 com_err(whoami, 0,
543 "kerberos principal doesn't exist; creating");
544 if ((status = kadm_add(&new)) != KADM_SUCCESS)
545 com_err(whoami, status,
546 " while creating kerberos principal");
547 }
548 else
549 com_err(whoami, status, " while setting password");
47baf534 550 }
47baf534 551 }
bac67528 552
553 dest_tkt();
40174425 554 return(status);
47baf534 555}
3e9b5b7b 556
bac67528 557int reserve_user(message,retval)
558 struct msg *message;
559 char *retval;
47baf534 560{
bac67528 561 int q_argc; /* Number of arguments to query */
40174425 562 char *q_argv[3]; /* Arguments to Moira query */
563 char *q_name; /* Name of Moira query */
29bc4461 564 int status = SUCCESS; /* General purpose error status */
bac67528 565 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
566 char *login; /* The login name the user wants */
567 register int i; /* A counter */
bac67528 568
803d15cb 569 /* Log that we are about to reserve a user. */
40174425 570 com_err(whoami, 0, "reserving user %s %s",
bac67528 571 message->first, message->last);
3e9b5b7b 572
bac67528 573 /* Check to make sure that we can verify this user. */
574 if ((status = verify_user(message,retval)) == SUCCESS)
3e9b5b7b 575 {
29bc4461 576 /* Get the requested login name from leftover packet information. */
bac67528 577 login = message->leftover;
29bc4461 578
579 /* Check the login name for validity. The login name is currently
40174425 580 is allowed to contain lowercase letters in any position and
581 and numbers and underscore characters in any position but the
97ee0ded 582 first. */
29bc4461 583 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
bac67528 584 status = UREG_INVALID_UNAME;
47baf534 585 }
29bc4461 586 if (status == SUCCESS)
40174425 587 if ((login[0] == '_') || isdigit(login[0]))
29bc4461 588 status = UREG_INVALID_UNAME;
40174425 589
29bc4461 590 if (status == SUCCESS)
3e9b5b7b 591 {
803d15cb 592 for (i = 0; i < strlen(login); i++)
5fff8167 593 if (!islower(login[i]) && !isdigit(login[i]) &&
594 (login[i] != '_'))
803d15cb 595 {
596 status = UREG_INVALID_UNAME;
597 break;
598 }
47baf534 599 }
29bc4461 600 if (status == SUCCESS)
3e9b5b7b 601 {
bac67528 602 /* Now that we have a valid user with a valid login... */
603
40174425 604 /* First, try to reserve the user in Moira. */
29bc4461 605 (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
bac67528 606 q_name = "register_user";
607 q_argv[0] = message->db.uid;
608 q_argv[1] = login;
609 q_argv[2] = fstype_buf;
610 q_argc = 3;
29bc4461 611 status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
bac67528 612 switch (status)
613 {
614 case SMS_SUCCESS:
615 status = SUCCESS;
616 break;
617 case SMS_IN_USE:
618 status = UREG_LOGIN_USED;
619 break;
62ba0b73 620 case SMS_DEADLOCK:
621 status = UREG_MISC_ERROR;
622 break;
bac67528 623 default:
a640951a 624 critical_alert(FAIL_INST,"%s returned from register_user.",
625 error_message(status));
9700b15a 626 status = UREG_MISC_ERROR;
bac67528 627 break;
628 }
47baf534 629 }
40174425 630
29bc4461 631 if (status == SUCCESS)
3e9b5b7b 632 {
40174425 633 /*
634 * Moira login was successfully created; try to reserve kerberos
635 * principal.
636 *
637 * If this routine fails, store the login in the retval so
638 * that it can be used in the client-side error message.
639 */
640 if ((status = reserve_krb(login)) != SUCCESS)
29bc4461 641 (void) strcpy(retval, login);
47baf534 642 }
bac67528 643
40174425 644 if (status)
645 com_err(whoami, status, " returned from reserve_user");
646 else {
647 com_err(whoami, 0, "User reserved");
648 }
bac67528 649
47baf534 650 return status;
bac67528 651}
47baf534 652
3f5f9b08 653int set_final_status(message)
654struct msg *message;
803d15cb 655 /* This routine updates a user's registration status to fully
29bc4461 656 registered. */
47baf534 657{
3f5f9b08 658 char *login;
40174425 659 char *q_name; /* Name of Moira query */
660 int q_argc; /* Number of arguments for Moira query */
bac67528 661 char *q_argv[2]; /* Arguments to get user by uid */
29bc4461 662 char state[7]; /* Can hold a 16 bit integer */
bac67528 663 int status; /* Error status */
664
3f5f9b08 665 if (message->request == UREG_SET_PASSWORD)
666 (void) sprintf(state,"%d",US_REGISTERED);
667 else if (message->db.reg_status == US_NO_LOGIN_YET)
668 (void) sprintf(state,"%d",US_ENROLLED);
669 else
670 (void) sprintf(state,"%d",US_ENROLL_NOT_ALLOWED);
671
672 login = message->db.login;
673 com_err(whoami, 0, "Setting final status for %s to %s", login, state);
bac67528 674
675 q_name = "update_user_status";
676 q_argc = 2;
677 q_argv[0] = login;
29bc4461 678 q_argv[1] = state;
bac67528 679 if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
62ba0b73 680 (char *)0)) != SMS_SUCCESS) {
681 if (status == SMS_DEADLOCK)
682 status = UREG_MISC_ERROR;
683 else
684 critical_alert(FAIL_INST,"%s returned from update_user_status.",
685 error_message(status));
686 }
40174425 687 if (status)
688 com_err(whoami, status, " returned from set_final_status");
689 else
690 com_err(whoami, 0, "Final status set");
f46fccfa 691 return status;
bac67528 692}
f46fccfa 693
bac67528 694
695int set_password(message,retval)
696 struct msg *message;
697 char *retval;
698 /* This routine is used to set the initial password for the new user. */
47baf534 699{
29bc4461 700 int status = SUCCESS; /* Return status */
bac67528 701 char *passwd; /* User's password */
bac67528 702
40174425 703 com_err(whoami, 0, "setting password %s %s",
bac67528 704 message->first, message->last);
705
706 status = verify_user(message,retval);
707
708 /* Don't set the password unless the registration status of the user
709 is that he exists and has no password. */
710 if (status == SUCCESS)
711 status = UREG_NO_LOGIN_YET;
712 if (status == UREG_NO_PASSWD_YET)
3e9b5b7b 713 {
bac67528 714 /* User is in proper state for this transaction. */
715
716 passwd = message->leftover;
717
718 /* Set password. */
40174425 719 if ((status = setpass_krb(message->db.login, passwd)) != SUCCESS)
bac67528 720 /* If failure, allow login name to be used in client
721 error message */
29bc4461 722 (void) strcpy(retval,message->db.login);
bac67528 723 else
724 /* Otherwise, mark user as finished. */
3f5f9b08 725 status = set_final_status(message);
bac67528 726 }
40174425 727
728 if (status)
729 com_err(whoami, status, " returned from set_passwd");
730 else
731 com_err(whoami, 0, "Password set");
732
bac67528 733 return status;
734}
3f5f9b08 735
736
737int getuserinfo(argc, argv, qargv)
738int argc;
739char **argv;
740char **qargv;
741{
742 int status = SUCCESS;
743
744 if (argc != U_END) {
745 critical_alert(FAIL_INST,
746 "Wrong number of args returned from get_user_by_uid");
747 status = SMS_ABORT;
748 } else {
749 qargv[U_NAME] = strsave(argv[U_NAME]);
750 qargv[U_UID+1] = strsave(argv[U_UID]);
751 qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
752 qargv[U_LAST+1] = strsave(argv[U_LAST]);
753 qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
754 qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
755 qargv[U_STATE+1] = strsave(argv[U_STATE]);
756 qargv[U_MITID+1] = strsave(argv[U_MITID]);
757 qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
758 qargv[U_MODTIME+1] = NULL;
759 }
760 return(status);
761}
762
763
764int set_identity(message,retval)
765struct msg *message;
766char *retval;
767{
768 int q_argc; /* Number of arguments to query */
40174425 769 char *q_argv[U_END]; /* Arguments to Moira query */
770 char *q_name; /* Name of Moira query */
3f5f9b08 771 int status = SUCCESS; /* General purpose error status */
772 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
773 char *login; /* The login name the user wants */
774 register int i; /* A counter */
775
776 /* Log that we are about to reserve a user. */
40174425 777 com_err(whoami, 0, "setting identity %s %s",
3f5f9b08 778 message->first, message->last);
779
780 /* Check to make sure that we can verify this user. */
781 status = verify_user(message,retval);
782 if (status == SUCCESS || status == UREG_NOT_ALLOWED)
783 {
784 status = SUCCESS;
785 /* Get the requested login name from leftover packet information. */
786 login = message->leftover;
787
788 /* Check the login name for validity. The login name is currently
40174425 789 is allowed to contain lowercase letters in any position and
790 and numbers and underscore characters in any position but the
3f5f9b08 791 first. */
792 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
793 status = UREG_INVALID_UNAME;
794 }
795 if (status == SUCCESS)
40174425 796 if ((login[0] == '_') || isdigit(login[0]))
3f5f9b08 797 status = UREG_INVALID_UNAME;
798 if (status == SUCCESS)
799 {
800 for (i = 0; i < strlen(login); i++)
801 if (!islower(login[i]) && !isdigit(login[i]) &&
802 (login[i] != '_'))
803 {
804 status = UREG_INVALID_UNAME;
805 break;
806 }
807 }
808 if (status == SUCCESS)
809 {
810 /* Now that we have a valid user with a valid login... */
811
812 q_argv[0] = message->db.uid;
813 status = sms_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
814 if (status != SUCCESS) {
815 com_err(whoami, status, " while getting user info");
816 return(status);
817 }
818 q_argv[U_NAME+1] = login;
819 status = sms_query("update_user", U_MODTIME+1, q_argv,
820 null_callproc, NULL);
821 switch (status)
822 {
823 case SMS_SUCCESS:
824 status = SUCCESS;
825 break;
826 case SMS_IN_USE:
827 status = UREG_LOGIN_USED;
828 break;
62ba0b73 829 case SMS_DEADLOCK:
830 status = UREG_MISC_ERROR;
831 break;
3f5f9b08 832 default:
833 critical_alert(FAIL_INST,"%s returned from update_user.",
834 error_message(status));
835 status = UREG_MISC_ERROR;
836 break;
837 }
838 }
839 if (status == SUCCESS)
840 {
40174425 841 /* Moira login was successfully created; try to reserve kerberos
3f5f9b08 842 principal. */
843 /* If this routine fails, store the login in the retval so
844 that it can be used in the client-side error message. */
40174425 845 if ((status = reserve_krb(login)) != SUCCESS)
3f5f9b08 846 (void) strcpy(retval, login);
847 }
848
40174425 849 if (status)
850 com_err(whoami, status, " returned from set_identity");
851 else
852 com_err(whoami, 0, "Identity set");
3f5f9b08 853
854 return status;
855}
856
857
858void reg_com_err_hook(whoami, code, fmt, pvar)
859 char *whoami;
860 int code;
861 char *fmt;
862 caddr_t pvar;
863{
864 if (whoami) {
865 fputs(whoami, stderr);
866 fputs(": ", stderr);
867 }
868 if (code) {
869 fputs(error_message(code), stderr);
870 }
871 if (fmt) {
872 _doprnt(fmt, pvar, stderr);
873 }
874 putc('\n', stderr);
875 fflush(stderr);
876}
This page took 0.212501 seconds and 5 git commands to generate.