]> andersk Git - moira.git/blame - reg_svr/reg_svr.c
remove coredump bug on bad ID numbers
[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
2ce085d2 14 * Moira server as it is linked with libmoiraglue 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>
2ce085d2 34#include "moira.h"
35#include "moira_site.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 */
2ce085d2 76 if ((status = mr_connect(MOIRA_SERVER)) != MR_SUCCESS)
3e9b5b7b 77 {
2ce085d2 78 com_err(whoami, status, " on mr_connect");
78eff417 79 exit(1);
80 }
3e9b5b7b 81
82 /* Authorize, telling the server who you are */
2ce085d2 83 if ((status = mr_auth(whoami)) != MR_SUCCESS)
3e9b5b7b 84 {
2ce085d2 85 com_err(whoami, status, " on mr_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{
d8ffd27c 151 des_cblock key; /* The key for DES en/decryption */
152 des_key_schedule sched; /* En/decryption schedule */
3e9b5b7b 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 */
d8ffd27c 172 des_string_to_key(data->mit_id, key);
3e9b5b7b 173 /* Get schedule from key */
d8ffd27c 174 des_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. */
d8ffd27c 178 des_pcbc_encrypt(message->encrypted, decrypt, decrypt_len,
179 sched, key, DES_DECRYPT);
3e9b5b7b 180
181 /* Extract the plain text and encrypted ID fields from the decrypted
182 packet information. */
183 /* Since the decrypted information starts with the plain-text ID
184 followed by a null, if the decryption worked, this will only
185 copy the plain text part of the decrypted information. It is
186 important that strncpy be used because if we are not using the
187 correct key, there is no guarantee that a null will occur
188 anywhere in the string. */
29bc4461 189 (void) strncpy(idnumber,decrypt,(int)decrypt_len);
32155899 190 /* Check that the idnumber of a mismatched decryption doesn't overflow
191 * the buffer.
192 */
193 if (strlen(idnumber) != 9) {
194#ifdef DEBUG
195 com_err(whoami, 0, "idnumber wrong size, probable user mismatch\n");
196#endif
197 return(FAILURE);
198 }
3e9b5b7b 199 /* Point temp to the end of the plain text ID number. */
47baf534 200 temp = decrypt + strlen(idnumber) + 1;
29bc4461 201 /* Find out how much more packet there is. */
bac67528 202 len = message->encrypted_len - (temp - decrypt);
29bc4461 203 /* Copy the next CRYPT_LEN bytes of the decrypted information into
204 hashid if there are CRYPT_LEN more bytes to copy. There will be
3e9b5b7b 205 if we have the right key. */
29bc4461 206 (void) strncpy(hashid, temp, min(len, CRYPT_LEN));
3e9b5b7b 207 /* Point temp to the end of the encrypted ID field */
47baf534 208 temp += strlen(hashid) + 1;
3e9b5b7b 209 /* Find out how much more room there is. */
bac67528 210 len = message->encrypted_len - (temp - decrypt);
3e9b5b7b 211
bac67528 212 /* Now compare encrypted ID's don't match. */
803d15cb 213 if (strcmp(hashid, data->mit_id)) status = FAILURE;
29bc4461 214 if (status == SUCCESS)
3e9b5b7b 215 {
803d15cb 216 EncryptID(recrypt, idnumber, message->first, message->last);
bac67528 217 /* Now compare encrypted plain text to ID from database. */
803d15cb 218 if (strcmp(recrypt, data->mit_id)) status = FAILURE;
47baf534 219 }
3e9b5b7b 220
29bc4461 221 if (status == SUCCESS)
bac67528 222 {
223 /* We made it. Now we can finish initializing message. */
224 /* Point leftover to whatever is left over! */
225 message->leftover = temp;
226 message->leftover_len = len;
227 /* Since we know we have the right user, fill in the information
40174425 228 from the Moira database. */
bac67528 229 message->db.reg_status = data->reg_status;
29bc4461 230 (void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid));
231 (void) strncpy(message->db.mit_id,data->mit_id,
232 sizeof(message->db.mit_id));
233 (void) strncpy(message->db.login,data->login, sizeof(message->db.login));
bac67528 234 }
47baf534 235
bac67528 236#ifdef DEBUG
237 if (status)
40174425 238 com_err(whoami, status, " in parse_encrypted");
bac67528 239 else
40174425 240 com_err(whoami, status, "parse_encrypted succeeded");
bac67528 241#endif
47baf534 242
47baf534 243 return status;
244}
245
bac67528 246int db_callproc(argc,argv,queue)
40174425 247 int argc; /* Number of arguments returned by Moira */
248 char *argv[]; /* Arguments returned by Moira */
bac67528 249 struct save_queue *queue; /* Queue to save information in */
2ce085d2 250/* This function is called by mr_query after each tuple found. It is
29bc4461 251 used by find_user to cache information about each user found. */
47baf534 252{
bac67528 253 struct db_data *data; /* Structure to store the information in */
29bc4461 254 int status = SUCCESS; /* Error status */
47baf534 255
bac67528 256#ifdef DEBUG
40174425 257 com_err(whoami, 0, "Entering db_callproc.");
bac67528 258#endif
259
29bc4461 260 if (argc != U_END)
3e9b5b7b 261 {
a640951a 262 critical_alert
263 (FAIL_INST,
264 "Wrong number of arguments returned from get_user_by_name.");
2ce085d2 265 status = MR_ABORT;
f46fccfa 266 }
bac67528 267 else
3e9b5b7b 268 {
40174425 269 /* extract the needed information from the results of the Moira query */
bac67528 270 data = (struct db_data *)malloc(sizeof(struct db_data));
29bc4461 271 data->reg_status = atoi(argv[U_STATE]);
272 (void) strncpy(data->login,argv[U_NAME],sizeof(data->login));
273 (void) strncpy(data->mit_id,argv[U_MITID],sizeof(data->mit_id));
274 (void) strncpy(data->uid,argv[U_UID],sizeof(data->uid));
bac67528 275#ifdef DEBUG
276 fprintf(stderr,"Found in database:\n");
277 fprintf(stderr," Registration status: %d\n",data->reg_status);
278 fprintf(stderr," login: %s\n",data->login);
279 fprintf(stderr," MIT ID: %s\n",data->mit_id);
280 fprintf(stderr," uid: %s\n",data->uid);
281#endif
282 sq_save_data(queue,data);
47baf534 283 }
bac67528 284
285 return status;
286}
3e9b5b7b 287
bac67528 288int find_user(message)
289 struct msg *message; /* Formatted packet structure */
290/* This routine verifies that a user is allowed to register by finding
40174425 291 him/her in the Moira database. It returns the status of the Moira
bac67528 292 query that it calls. */
293{
803d15cb 294#define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */
bac67528 295 char *q_name; /* Name of query */
29bc4461 296 int q_argc; /* Number of arguments for query */
297 char *q_argv[GUBN_ARGS]; /* Arguments to query */
298 int status = SUCCESS; /* Query return status */
bac67528 299
40174425 300 struct save_queue *queue; /* Queue to hold Moira data */
bac67528 301 struct db_data *data; /* Structure for data for one tuple */
29bc4461 302 short verified = FALSE; /* Have we verified the user? */
bac67528 303
304 /* Zero the mit_id field in the formatted packet structure. This
305 being zeroed means that no user was found. */
306 bzero(message->db.mit_id,sizeof(message->db.mit_id));
307
29bc4461 308 if (status == SUCCESS)
3e9b5b7b 309 {
40174425 310 /* Get ready to make an Moira query */
bac67528 311 q_name = "get_user_by_name";
29bc4461 312 q_argc = GUBN_ARGS; /* #defined in this routine */
bac67528 313 q_argv[0] = message->first;
314 q_argv[1] = message->last;
315
316 /* Create queue to hold information */
317 queue = sq_create();
318
319 /* Do it */
2ce085d2 320 status = mr_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
bac67528 321
322#ifdef DEBUG
803d15cb 323 fprintf(stderr," %d returned by get_user_by_name\n",status);
bac67528 324#endif
325
2ce085d2 326 if (status == MR_SUCCESS)
bac67528 327 {
328 /* Traverse the list, freeing data as we go. If sq_get_data()
329 returns zero if there is no more data on the queue. */
330 while (sq_get_data(queue,&data))
331 {
332 if (!verified)
333 /* parse_encrypted returns zero on success */
29bc4461 334 verified = (parse_encrypted(message,data) == SUCCESS);
335 free((char *)data);
bac67528 336 }
337 }
29bc4461 338
339 /* Destroy the queue */
340 sq_destroy(queue);
47baf534 341 }
47baf534 342
bac67528 343#ifdef DEBUG
344 fprintf(stderr,"Returned from find_user\n");
345 fprintf(stderr," MIT ID: %s\n", message->db.mit_id);
346 fprintf(stderr," Registration status: %d\n",message->db.reg_status);
347 fprintf(stderr," uid: %s\n",message->db.uid);
348 fprintf(stderr," login: %s\n",message->db.login);
349 fprintf(stderr," Status from query: %d\n",status);
350#endif DEBGUG
351
352 return status;
353}
354
bac67528 355int verify_user(message,retval)
3e9b5b7b 356 struct msg *message;
bac67528 357 char *retval;
29bc4461 358 /* This routine determines whether a user is in the databse and returns
359 his state so that other routines can figure out whether he is the
360 correct state for various transactions. */
361
47baf534 362{
29bc4461 363 int status = SUCCESS; /* Return status */
bac67528 364
365 /* Log that we are about to veryify user */
40174425 366 com_err(whoami, 0, "verifying user %s %s",message->first,message->last);
bac67528 367
368 /* Figure out what user (if any) can be found based on the
369 encrypted information in the packet. (See the comment on
370 parse_encrypted().) */
bac67528 371
372 status = find_user(message);
373
40174425 374 /* If Moira coudn't find the user */
2ce085d2 375 if (status == MR_NO_MATCH)
f46fccfa 376 status = UREG_USER_NOT_FOUND;
2ce085d2 377 else if (status == MR_SUCCESS)
3e9b5b7b 378 {
bac67528 379 /* If the information sent over in the packet did not point to a
380 valid user, the mit_id field in the formatted packet structure
381 will be empty. */
29bc4461 382 if (message->db.mit_id[0] == NULL)
bac67528 383 status = UREG_USER_NOT_FOUND;
384 /* If the user was found but the registration has already started,
385 use this as the status */
386 else
387 {
388 switch (message->db.reg_status)
389 {
29bc4461 390 case US_NO_LOGIN_YET:
bac67528 391 status = SUCCESS;
392 break;
29bc4461 393 case US_REGISTERED:
bac67528 394 status = UREG_ALREADY_REGISTERED;
395 break;
29bc4461 396 case US_NO_PASSWD:
bac67528 397 status = UREG_NO_PASSWD_YET;
398 break;
29bc4461 399 case US_DELETED:
bac67528 400 status = UREG_DELETED;
401 break;
29bc4461 402 case US_NOT_ALLOWED:
bac67528 403 status = UREG_NOT_ALLOWED;
404 break;
3f5f9b08 405 case US_ENROLLED:
406 status = UREG_ENROLLED;
407 break;
408 case US_ENROLL_NOT_ALLOWED:
409 status = UREG_ENROLL_NOT_ALLOWED;
410 break;
d8ffd27c 411 case US_HALF_ENROLLED:
412 status = UREG_HALF_ENROLLED;
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
40174425 426 if (status)
427 com_err(whoami, status, " returned from verify_user");
428 else
429 com_err(whoami, 0, "User verified");
bac67528 430
47baf534 431 return status;
432}
bac67528 433
40174425 434int ureg_kadm_init()
47baf534 435{
40174425 436 unsigned int status = SUCCESS; /* Return status */
437 static char krbrealm[REALM_SZ]; /* kerberos realm name */
6b407d0f 438 static char hostbuf[BUFSIZ], *host; /* local hostname in principal fmt */
40174425 439 static int inited = 0;
6b407d0f 440 char *p;
40174425 441
442#ifdef DEBUG
443 com_err(whoami, 0, "Entering ureg_kadm_init");
444#endif DEBUG
445
446 if (!inited) {
447 inited++;
448 bzero(krbrealm, sizeof(krbrealm));
449 if (status = krb_get_lrealm(krbrealm, 1)) {
450 status += krb_err_base;
451 com_err(whoami, status, " fetching kerberos realm");
452 exit(1);
453 }
6b407d0f 454 if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
455 com_err(whoami, errno, "getting local hostname");
456 host = canonicalize_hostname(strsave(hostbuf));
457 for (p = host; *p && *p != '.'; p++)
458 if (isupper(*p))
459 *p = tolower(*p);
460 *p = 0;
40174425 461 }
bac67528 462
463 /* Get keys for interacting with Kerberos admin server. */
f3c010f8 464 /* principal, instance, realm, service, service instance, life, file */
6b407d0f 465 if (status = krb_get_svc_in_tkt(MOIRA_SNAME, host, krbrealm, PWSERV_NAME,
40174425 466 KADM_SINST, 1, KEYFILE))
467 status += krb_err_base;
468
469 if (status != SUCCESS)
470 com_err(whoami, status, " while get admin tickets");
803d15cb 471#ifdef DEBUG
40174425 472 else {
473 com_err(whoami, status, "Succeeded in getting admin tickets");
474 }
803d15cb 475#endif
40174425 476
477 if (status == SUCCESS) {
478 if ((status = kadm_init_link(PWSERV_NAME, KADM_SINST, krbrealm)) !=
479 KADM_SUCCESS) {
480 com_err(whoami, status, " while initializing kadmin connection");
481 }
482 }
483
bac67528 484 return status;
47baf534 485}
486
bac67528 487int null_callproc(argc,argv,message)
488 int argc;
489 char *argv[];
3e9b5b7b 490 char *message;
bac67528 491 /* This routine is a null callback that should be used for queries that
492 do not return tuples. If it ever gets called, something is wrong. */
47baf534 493{
a640951a 494 critical_alert(FAIL_INST,"Something returned from an update query.");
803d15cb 495 return FAILURE;
47baf534 496}
497
40174425 498/*
499 * This routine reserves a principal in kerberos by setting up a
500 * principal with a random initial key.
501 */
502int reserve_krb(login)
503 char *login;
47baf534 504{
40174425 505 int status = SUCCESS;
506 Kadm_vals new;
507 des_cblock key;
508 u_long *lkey = (u_long *)key;
bac67528 509
40174425 510#ifdef DEBUG
511 com_err(whoami, 0, "Entering reserve_krb");
512#endif DEBUG
803d15cb 513
40174425 514 if ((status = ureg_kadm_init()) == SUCCESS) {
515 bzero((char *)&new, sizeof(new));
516 SET_FIELD(KADM_DESKEY, new.fields);
517 SET_FIELD(KADM_NAME, new.fields);
bac67528 518
40174425 519 (void) des_random_key(key);
520 new.key_low = htonl(lkey[0]);
521 new.key_high = htonl(lkey[1]);
522 strcpy(new.name, login);
523
524 com_err(whoami, 0, "Creating kerberos principal for %s", login);
525 status = kadm_add(&new);
526 if (status != KADM_SUCCESS)
527 com_err(whoami, status, " while reserving principal");
528
529 bzero((char *)&new, sizeof(new));
530 }
531
532 dest_tkt();
533
534 return(status);
535}
536
537/*
538 * This routine reserves a principal in kerberos by setting up a
539 * principal with a random initial key.
540 */
541int setpass_krb(login, password)
542 char *login;
543 char *password;
544{
545 int status = SUCCESS;
546 Kadm_vals new;
547 des_cblock key;
548 u_long *lkey = (u_long *)key;
549
550 if ((status = ureg_kadm_init()) == SUCCESS) {
551 bzero((char *)&new, sizeof(new));
552 SET_FIELD(KADM_DESKEY, new.fields);
553 SET_FIELD(KADM_NAME, new.fields);
554
555 (void) des_string_to_key(password, key);
556 new.key_low = htonl(lkey[0]);
557 new.key_high = htonl(lkey[1]);
558 strcpy(new.name, login);
559
560 com_err(whoami, 0, "Setting password for %s", login);
561 /* First arguement is not used if user has modify privileges */
562 if ((status = kadm_mod(&new, &new)) != KADM_SUCCESS) {
563 if (status == KADM_NOENTRY) {
564 com_err(whoami, 0,
565 "kerberos principal doesn't exist; creating");
566 if ((status = kadm_add(&new)) != KADM_SUCCESS)
567 com_err(whoami, status,
568 " while creating kerberos principal");
569 }
570 else
571 com_err(whoami, status, " while setting password");
47baf534 572 }
47baf534 573 }
bac67528 574
575 dest_tkt();
40174425 576 return(status);
47baf534 577}
3e9b5b7b 578
bac67528 579int reserve_user(message,retval)
580 struct msg *message;
581 char *retval;
47baf534 582{
bac67528 583 int q_argc; /* Number of arguments to query */
40174425 584 char *q_argv[3]; /* Arguments to Moira query */
585 char *q_name; /* Name of Moira query */
29bc4461 586 int status = SUCCESS; /* General purpose error status */
bac67528 587 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
588 char *login; /* The login name the user wants */
589 register int i; /* A counter */
bac67528 590
803d15cb 591 /* Log that we are about to reserve a user. */
40174425 592 com_err(whoami, 0, "reserving user %s %s",
bac67528 593 message->first, message->last);
3e9b5b7b 594
bac67528 595 /* Check to make sure that we can verify this user. */
596 if ((status = verify_user(message,retval)) == SUCCESS)
3e9b5b7b 597 {
29bc4461 598 /* Get the requested login name from leftover packet information. */
bac67528 599 login = message->leftover;
29bc4461 600
601 /* Check the login name for validity. The login name is currently
40174425 602 is allowed to contain lowercase letters in any position and
603 and numbers and underscore characters in any position but the
97ee0ded 604 first. */
29bc4461 605 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
bac67528 606 status = UREG_INVALID_UNAME;
47baf534 607 }
29bc4461 608 if (status == SUCCESS)
40174425 609 if ((login[0] == '_') || isdigit(login[0]))
29bc4461 610 status = UREG_INVALID_UNAME;
40174425 611
29bc4461 612 if (status == SUCCESS)
3e9b5b7b 613 {
803d15cb 614 for (i = 0; i < strlen(login); i++)
5fff8167 615 if (!islower(login[i]) && !isdigit(login[i]) &&
616 (login[i] != '_'))
803d15cb 617 {
618 status = UREG_INVALID_UNAME;
619 break;
620 }
47baf534 621 }
29bc4461 622 if (status == SUCCESS)
3e9b5b7b 623 {
bac67528 624 /* Now that we have a valid user with a valid login... */
625
40174425 626 /* First, try to reserve the user in Moira. */
2ce085d2 627 (void) sprintf(fstype_buf,"%d",MR_FS_STUDENT);
bac67528 628 q_name = "register_user";
629 q_argv[0] = message->db.uid;
630 q_argv[1] = login;
631 q_argv[2] = fstype_buf;
632 q_argc = 3;
2ce085d2 633 status = mr_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
bac67528 634 switch (status)
635 {
2ce085d2 636 case MR_SUCCESS:
bac67528 637 status = SUCCESS;
638 break;
2ce085d2 639 case MR_IN_USE:
bac67528 640 status = UREG_LOGIN_USED;
641 break;
2ce085d2 642 case MR_DEADLOCK:
62ba0b73 643 status = UREG_MISC_ERROR;
644 break;
bac67528 645 default:
a640951a 646 critical_alert(FAIL_INST,"%s returned from register_user.",
647 error_message(status));
9700b15a 648 status = UREG_MISC_ERROR;
bac67528 649 break;
650 }
47baf534 651 }
40174425 652
29bc4461 653 if (status == SUCCESS)
3e9b5b7b 654 {
40174425 655 /*
656 * Moira login was successfully created; try to reserve kerberos
657 * principal.
658 *
659 * If this routine fails, store the login in the retval so
660 * that it can be used in the client-side error message.
661 */
662 if ((status = reserve_krb(login)) != SUCCESS)
29bc4461 663 (void) strcpy(retval, login);
47baf534 664 }
bac67528 665
40174425 666 if (status)
667 com_err(whoami, status, " returned from reserve_user");
668 else {
669 com_err(whoami, 0, "User reserved");
670 }
bac67528 671
47baf534 672 return status;
bac67528 673}
47baf534 674
3f5f9b08 675int set_final_status(message)
676struct msg *message;
803d15cb 677 /* This routine updates a user's registration status to fully
29bc4461 678 registered. */
47baf534 679{
3f5f9b08 680 char *login;
40174425 681 char *q_name; /* Name of Moira query */
682 int q_argc; /* Number of arguments for Moira query */
bac67528 683 char *q_argv[2]; /* Arguments to get user by uid */
29bc4461 684 char state[7]; /* Can hold a 16 bit integer */
bac67528 685 int status; /* Error status */
686
3f5f9b08 687 if (message->request == UREG_SET_PASSWORD)
688 (void) sprintf(state,"%d",US_REGISTERED);
689 else if (message->db.reg_status == US_NO_LOGIN_YET)
690 (void) sprintf(state,"%d",US_ENROLLED);
691 else
692 (void) sprintf(state,"%d",US_ENROLL_NOT_ALLOWED);
693
694 login = message->db.login;
695 com_err(whoami, 0, "Setting final status for %s to %s", login, state);
bac67528 696
697 q_name = "update_user_status";
698 q_argc = 2;
699 q_argv[0] = login;
29bc4461 700 q_argv[1] = state;
2ce085d2 701 if ((status = mr_query(q_name, q_argc, q_argv, null_callproc,
702 (char *)0)) != MR_SUCCESS) {
703 if (status == MR_DEADLOCK)
62ba0b73 704 status = UREG_MISC_ERROR;
705 else
706 critical_alert(FAIL_INST,"%s returned from update_user_status.",
707 error_message(status));
708 }
40174425 709 if (status)
710 com_err(whoami, status, " returned from set_final_status");
711 else
712 com_err(whoami, 0, "Final status set");
f46fccfa 713 return status;
bac67528 714}
f46fccfa 715
bac67528 716
717int set_password(message,retval)
718 struct msg *message;
719 char *retval;
720 /* This routine is used to set the initial password for the new user. */
47baf534 721{
29bc4461 722 int status = SUCCESS; /* Return status */
bac67528 723 char *passwd; /* User's password */
bac67528 724
40174425 725 com_err(whoami, 0, "setting password %s %s",
bac67528 726 message->first, message->last);
727
728 status = verify_user(message,retval);
729
730 /* Don't set the password unless the registration status of the user
731 is that he exists and has no password. */
732 if (status == SUCCESS)
733 status = UREG_NO_LOGIN_YET;
d8ffd27c 734 if (((int)message->request == UREG_SET_PASSWORD &&
735 status == UREG_NO_PASSWD_YET) ||
736 ((int)message->request == UREG_GET_KRB &&
737 status == UREG_HALF_ENROLLED))
3e9b5b7b 738 {
bac67528 739 /* User is in proper state for this transaction. */
740
741 passwd = message->leftover;
742
743 /* Set password. */
40174425 744 if ((status = setpass_krb(message->db.login, passwd)) != SUCCESS)
bac67528 745 /* If failure, allow login name to be used in client
746 error message */
29bc4461 747 (void) strcpy(retval,message->db.login);
bac67528 748 else
749 /* Otherwise, mark user as finished. */
3f5f9b08 750 status = set_final_status(message);
bac67528 751 }
40174425 752
753 if (status)
754 com_err(whoami, status, " returned from set_passwd");
755 else
756 com_err(whoami, 0, "Password set");
757
bac67528 758 return status;
759}
3f5f9b08 760
761
762int getuserinfo(argc, argv, qargv)
763int argc;
764char **argv;
765char **qargv;
766{
767 int status = SUCCESS;
768
769 if (argc != U_END) {
770 critical_alert(FAIL_INST,
771 "Wrong number of args returned from get_user_by_uid");
2ce085d2 772 status = MR_ABORT;
3f5f9b08 773 } else {
774 qargv[U_NAME] = strsave(argv[U_NAME]);
775 qargv[U_UID+1] = strsave(argv[U_UID]);
776 qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
777 qargv[U_LAST+1] = strsave(argv[U_LAST]);
778 qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
779 qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
780 qargv[U_STATE+1] = strsave(argv[U_STATE]);
781 qargv[U_MITID+1] = strsave(argv[U_MITID]);
782 qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
783 qargv[U_MODTIME+1] = NULL;
784 }
785 return(status);
786}
787
788
789int set_identity(message,retval)
790struct msg *message;
791char *retval;
792{
793 int q_argc; /* Number of arguments to query */
40174425 794 char *q_argv[U_END]; /* Arguments to Moira query */
795 char *q_name; /* Name of Moira query */
3f5f9b08 796 int status = SUCCESS; /* General purpose error status */
797 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
798 char *login; /* The login name the user wants */
799 register int i; /* A counter */
800
801 /* Log that we are about to reserve a user. */
40174425 802 com_err(whoami, 0, "setting identity %s %s",
3f5f9b08 803 message->first, message->last);
804
805 /* Check to make sure that we can verify this user. */
806 status = verify_user(message,retval);
807 if (status == SUCCESS || status == UREG_NOT_ALLOWED)
808 {
809 status = SUCCESS;
810 /* Get the requested login name from leftover packet information. */
811 login = message->leftover;
812
813 /* Check the login name for validity. The login name is currently
40174425 814 is allowed to contain lowercase letters in any position and
815 and numbers and underscore characters in any position but the
3f5f9b08 816 first. */
817 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
818 status = UREG_INVALID_UNAME;
819 }
820 if (status == SUCCESS)
40174425 821 if ((login[0] == '_') || isdigit(login[0]))
3f5f9b08 822 status = UREG_INVALID_UNAME;
823 if (status == SUCCESS)
824 {
825 for (i = 0; i < strlen(login); i++)
826 if (!islower(login[i]) && !isdigit(login[i]) &&
827 (login[i] != '_'))
828 {
829 status = UREG_INVALID_UNAME;
830 break;
831 }
832 }
833 if (status == SUCCESS)
834 {
835 /* Now that we have a valid user with a valid login... */
836
837 q_argv[0] = message->db.uid;
2ce085d2 838 status = mr_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
3f5f9b08 839 if (status != SUCCESS) {
840 com_err(whoami, status, " while getting user info");
841 return(status);
842 }
843 q_argv[U_NAME+1] = login;
d8ffd27c 844 q_argv[U_STATE+1] = "7";
2ce085d2 845 status = mr_query("update_user", U_MODTIME+1, q_argv,
3f5f9b08 846 null_callproc, NULL);
847 switch (status)
848 {
2ce085d2 849 case MR_SUCCESS:
3f5f9b08 850 status = SUCCESS;
851 break;
2ce085d2 852 case MR_IN_USE:
3f5f9b08 853 status = UREG_LOGIN_USED;
854 break;
2ce085d2 855 case MR_DEADLOCK:
62ba0b73 856 status = UREG_MISC_ERROR;
857 break;
3f5f9b08 858 default:
859 critical_alert(FAIL_INST,"%s returned from update_user.",
860 error_message(status));
861 status = UREG_MISC_ERROR;
862 break;
863 }
864 }
865 if (status == SUCCESS)
866 {
40174425 867 /* Moira login was successfully created; try to reserve kerberos
3f5f9b08 868 principal. */
869 /* If this routine fails, store the login in the retval so
870 that it can be used in the client-side error message. */
40174425 871 if ((status = reserve_krb(login)) != SUCCESS)
3f5f9b08 872 (void) strcpy(retval, login);
873 }
874
40174425 875 if (status)
876 com_err(whoami, status, " returned from set_identity");
877 else
878 com_err(whoami, 0, "Identity set");
3f5f9b08 879
880 return status;
881}
882
883
884void reg_com_err_hook(whoami, code, fmt, pvar)
885 char *whoami;
886 int code;
887 char *fmt;
888 caddr_t pvar;
889{
890 if (whoami) {
891 fputs(whoami, stderr);
892 fputs(": ", stderr);
893 }
894 if (code) {
895 fputs(error_message(code), stderr);
896 }
897 if (fmt) {
898 _doprnt(fmt, pvar, stderr);
899 }
900 putc('\n', stderr);
901 fflush(stderr);
902}
This page took 0.676462 seconds and 5 git commands to generate.