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