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