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