6 * Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
10 * Server for user registration with Moira and Kerberos.
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
14 * Moira server as it is linked with libmoiraglue which bypasses
15 * the network protocol.
19 static char *rcsid_reg_svr_c = "$Header$";
22 #include <mit-copyright.h>
28 #include <sys/types.h>
38 #include "moira_site.h"
41 extern char admin_errmsg[];
43 void reg_com_err_hook();
45 int main(int argc, char *argv[])
47 struct msg message; /* Storage for parsed packet */
48 int status = SUCCESS; /* Error status */
49 char retval[BUFSIZ]; /* Buffer to hold return message for client */
51 void req_initialize(); /* Initialize request layer */
52 void get_request(); /* Get a request */
53 void report(); /* Respond to a request */
58 /* Error messages sent one line at a time */
59 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
60 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
61 set_com_err_hook(reg_com_err_hook);
63 /* Initialize com_err error tables */
67 initialize_gdss_error_table();
69 /* Set the name of our kerberos ticket file */
70 krb_set_tkt_string("/tmp/tkt_ureg");
72 /* Connect to the Moira server */
73 if ((status = mr_connect(MOIRA_SERVER)) != MR_SUCCESS)
75 com_err(whoami, status, " on mr_connect");
79 /* Authorize, telling the server who you are */
80 if ((status = mr_auth(whoami)) != MR_SUCCESS)
82 com_err(whoami, status, " on mr_auth");
86 journal = fopen(REGJOURNAL, "a");
89 com_err(whoami, errno, " while opening journal file");
93 /* Allow request layer to initialize */
96 /* Sit around waiting for requests from the client. */
99 get_request(&message);
101 switch (message.request)
103 case UREG_VERIFY_USER:
104 status = verify_user(&message, retval);
106 case UREG_RESERVE_LOGIN:
107 status = reserve_user(&message, retval);
109 case UREG_SET_PASSWORD:
111 status = set_password(&message, retval);
114 status = set_identity(&message, retval);
116 case UREG_GET_SECURE:
117 status = get_secure(&message, retval);
119 case UREG_SET_SECURE:
120 status = set_secure(&message, retval);
123 status = UREG_UNKNOWN_REQUEST;
124 critical_alert(FAIL_INST, "Unknown request %d from userreg.",
129 /* Report what happened to client */
130 report(status, retval);
134 /* This routine makes sure that the ID from the database matches
135 the ID sent accross in the packet. The information in the packet
136 was created in the following way:
138 The database used to contain encrypted IDs. Now we don't encrypt
139 them in the database, although there are still some encrypted IDs
142 The plain text ID number was encrypted via EncryptID() resulting
143 in the form that would appear in the Moira database. This is
144 concatenated to the plain text ID so that the ID string contains plain
145 text ID followed by a null followed by the encrypted ID. Other
146 information such as the username or password is appended. The whole
147 thing is then DES encrypted using the encrypted ID as the source of
150 This routine tries each ID in the database that belongs
151 to someone with this user's first and last name and tries to
152 decrypt the packet with this information. If it succeeds, it returns
153 zero and initializes all the fields of the formatted packet structure
154 that depend on the encrypted information. */
156 int parse_encrypted(struct msg *message, struct db_data *data)
158 des_cblock key; /* The key for DES en/decryption */
159 des_key_schedule sched; /* En/decryption schedule */
160 static char decrypt[BUFSIZ]; /* Buffer to hold decrypted information */
161 long decrypt_len; /* Length of decypted ID information */
162 char recrypt[14]; /* Buffer to hold re-encrypted information */
163 static char hashid[14]; /* Buffer to hold one-way encrypted ID */
164 char idnumber[BUFSIZ]; /* Buffer to hold plain-text ID */
165 char *temp; /* A temporary string pointer */
166 int len; /* Keeps track of length left in packet */
167 int status = SUCCESS; /* Error status */
169 /* Make the decrypted information length the same as the encrypted
170 information length. Both are integral multples of eight bytes
171 because of the DES encryption routines. */
172 decrypt_len = message->encrypted_len;
174 /* Get key from the possibly one-way encrypted ID in the Moira database */
175 if (data->mit_id[0] >= '0' && data->mit_id[0] <= '9')
179 EncryptID(buf, data->mit_id, message->first, message->last);
180 des_string_to_key(buf, key);
183 des_string_to_key(data->mit_id, key);
185 /* Get schedule from key */
186 des_key_sched(key, sched);
187 /* Decrypt information from packet using this key. Since decrypt_len
188 is an integral multiple of eight bytes, it will probably be null-
190 des_pcbc_encrypt(message->encrypted, decrypt, decrypt_len,
191 sched, key, DES_DECRYPT);
193 /* Extract the plain text and encrypted ID fields from the decrypted
194 packet information. */
195 /* Since the decrypted information starts with the plain-text ID
196 followed by a null, if the decryption worked, this will only
197 copy the plain text part of the decrypted information. It is
198 important that strncpy be used because if we are not using the
199 correct key, there is no guarantee that a null will occur
200 anywhere in the string. */
201 strncpy(idnumber, decrypt, decrypt_len);
202 /* Check that the idnumber of a mismatched decryption doesn't overflow
204 if (strlen(idnumber) != 9)
207 /* Point temp to the end of the plain text ID number. */
208 temp = decrypt + strlen(idnumber) + 1;
209 /* Find out how much more packet there is. */
210 len = message->encrypted_len - (temp - decrypt);
211 /* Copy the next CRYPT_LEN bytes of the decrypted information into
212 hashid if there are CRYPT_LEN more bytes to copy. There will be
213 if we have the right key. */
214 strncpy(hashid, temp, min(len, CRYPT_LEN));
215 /* Point temp to the end of the encrypted ID field */
216 temp += strlen(hashid) + 1;
217 /* Find out how much more room there is. */
218 len = message->encrypted_len - (temp - decrypt);
220 /* Now compare encrypted ID and clear text ID for a match. */
221 if (strcmp(hashid, data->mit_id) &&
222 strcmp(idnumber, data->mit_id))
225 if (status == SUCCESS)
227 /* We made it. Now we can finish initializing message. */
228 /* Point leftover to whatever is left over! */
229 message->leftover = temp;
230 message->leftover_len = len;
231 /* Since we know we have the right user, fill in the information
232 from the Moira database. */
233 message->db.reg_status = data->reg_status;
234 strncpy(message->db.uid, data->uid, sizeof(message->db.uid));
235 strncpy(message->db.mit_id, data->mit_id, sizeof(message->db.mit_id));
236 strncpy(message->db.login, data->login, sizeof(message->db.login));
242 /* This function is called by mr_query after each tuple found. It is
243 used by find_user to cache information about each user found. */
244 int db_callproc(int argc, char **argv, struct save_queue *queue)
246 struct db_data *data; /* Structure to store the information in */
247 int status = SUCCESS; /* Error status */
251 critical_alert(FAIL_INST, "Wrong number of arguments returned "
252 "from get_user_account_by_name.");
257 /* extract the needed information from the results of the Moira query */
258 data = malloc(sizeof(struct db_data));
259 data->reg_status = atoi(argv[U_STATE]);
260 strncpy(data->login, argv[U_NAME], sizeof(data->login));
261 strncpy(data->mit_id, argv[U_MITID], sizeof(data->mit_id));
262 strncpy(data->uid, argv[U_UID], sizeof(data->uid));
263 sq_save_data(queue, data);
269 /* This routine verifies that a user is allowed to register by finding
270 him/her in the Moira database. It returns the status of the Moira
271 query that it calls. */
272 int find_user(struct msg *message)
274 #define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */
275 char *q_name; /* Name of query */
276 int q_argc; /* Number of arguments for query */
277 char *q_argv[GUBN_ARGS]; /* Arguments to query */
278 int status = SUCCESS; /* Query return status */
280 struct save_queue *queue; /* Queue to hold Moira data */
281 struct db_data *data; /* Structure for data for one tuple */
282 short verified = FALSE; /* Have we verified the user? */
284 /* Zero the mit_id field in the formatted packet structure. This
285 being zeroed means that no user was found. */
286 memset(message->db.mit_id, 0, sizeof(message->db.mit_id));
288 if (status == SUCCESS)
290 /* Get ready to make an Moira query */
291 q_name = "get_user_account_by_name";
292 q_argc = GUBN_ARGS; /* #defined in this routine */
293 q_argv[0] = message->first;
294 q_argv[1] = message->last;
296 /* Create queue to hold information */
300 status = mr_query(q_name, q_argc, q_argv, db_callproc, (char *)queue);
302 if (status == MR_SUCCESS)
304 /* Traverse the list, freeing data as we go. If sq_get_data()
305 returns zero if there is no more data on the queue. */
306 while (sq_get_data(queue, &data))
309 /* parse_encrypted returns zero on success */
310 verified = (parse_encrypted(message, data) == SUCCESS);
315 /* Destroy the queue */
322 /* This routine determines whether a user is in the databse and returns
323 his state so that other routines can figure out whether he is the
324 correct state for various transactions. */
325 int verify_user(struct msg *message, char *retval)
327 int status = SUCCESS; /* Return status */
329 /* Log that we are about to veryify user */
330 com_err(whoami, 0, "verifying user %s %s", message->first, message->last);
332 /* Figure out what user (if any) can be found based on the
333 encrypted information in the packet. (See the comment on
334 parse_encrypted().) */
336 status = find_user(message);
338 /* If Moira coudn't find the user */
339 if (status == MR_NO_MATCH)
340 status = UREG_USER_NOT_FOUND;
341 else if (status == MR_SUCCESS)
343 /* If the information sent over in the packet did not point to a
344 valid user, the mit_id field in the formatted packet structure
346 if (message->db.mit_id[0] == '\0')
347 status = UREG_USER_NOT_FOUND;
348 /* If the user was found but the registration has already started,
349 use this as the status */
352 switch (message->db.reg_status)
354 case US_NO_LOGIN_YET:
358 status = UREG_ALREADY_REGISTERED;
361 status = UREG_NO_PASSWD_YET;
364 status = UREG_DELETED;
367 status = UREG_NOT_ALLOWED;
370 status = UREG_ENROLLED;
372 case US_ENROLL_NOT_ALLOWED:
373 status = UREG_ENROLL_NOT_ALLOWED;
375 case US_HALF_ENROLLED:
376 status = UREG_HALF_ENROLLED;
379 status = UREG_MISC_ERROR;
380 critical_alert(FAIL_INST, "Bad user state %d for login %s.",
381 message->db.reg_status, message->db.login);
384 /* Set retval to the login name so that the client can use
385 it in the error message it will give the user. */
386 strcpy(retval, message->db.login);
391 com_err(whoami, status, " returned from verify_user");
393 com_err(whoami, 0, "User verified");
398 int ureg_kadm_init(void)
400 unsigned int status = SUCCESS; /* Return status */
401 static char krbrealm[REALM_SZ]; /* kerberos realm name */
402 static char hostbuf[BUFSIZ], *host; /* local hostname in principal fmt */
403 static int inited = 0;
409 memset(krbrealm, 0, sizeof(krbrealm));
410 if (status = krb_get_lrealm(krbrealm, 1))
412 status += krb_err_base;
413 com_err(whoami, status, " fetching kerberos realm");
416 if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
417 com_err(whoami, errno, "getting local hostname");
418 host = canonicalize_hostname(strsave(hostbuf));
419 for (p = host; *p && *p != '.'; p++)
427 /* Get keys for interacting with Kerberos admin server. */
428 /* principal, instance, realm, service, service instance, life, file */
429 if (status = krb_get_svc_in_tkt(MOIRA_SNAME, host, krbrealm, PWSERV_NAME,
430 KADM_SINST, 1, KEYFILE))
431 status += krb_err_base;
433 if (status != SUCCESS)
434 com_err(whoami, status, " while get admin tickets");
437 if ((status = kadm_init_link(PWSERV_NAME, KADM_SINST, krbrealm)) !=
439 com_err(whoami, status, " while initializing kadmin connection");
445 /* This routine is a null callback that should be used for queries that
446 do not return tuples. If it ever gets called, something is wrong. */
447 int null_callproc(int argc, char *argv[], char *message)
449 critical_alert(FAIL_INST, "Something returned from an update query.");
454 * This routine reserves a principal in kerberos by setting up a
455 * principal with a random initial key.
457 int reserve_krb(char *login)
459 int status = SUCCESS;
462 u_long *lkey = (u_long *)key;
464 if ((status = ureg_kadm_init()) == SUCCESS)
466 memset(&new, 0, sizeof(new));
467 SET_FIELD(KADM_DESKEY, new.fields);
468 SET_FIELD(KADM_NAME, new.fields);
471 new.key_low = htonl(lkey[0]);
472 new.key_high = htonl(lkey[1]);
473 strcpy(new.name, login);
475 com_err(whoami, 0, "Creating kerberos principal for %s", login);
476 status = kadm_add(&new);
477 if (status != KADM_SUCCESS)
478 com_err(whoami, status, " while reserving principal");
480 memset(&new, 0, sizeof(new));
489 * This routine reserves a principal in kerberos by setting up a
490 * principal with a random initial key.
492 int setpass_krb(char *login, char *password)
494 int status = SUCCESS;
497 u_long *lkey = (u_long *)key;
499 if ((status = ureg_kadm_init()) == SUCCESS)
501 memset(&new, 0, sizeof(new));
502 SET_FIELD(KADM_DESKEY, new.fields);
503 SET_FIELD(KADM_NAME, new.fields);
505 des_string_to_key(password, key);
506 new.key_low = htonl(lkey[0]);
507 new.key_high = htonl(lkey[1]);
508 strcpy(new.name, login);
510 com_err(whoami, 0, "Setting password for %s", login);
511 /* First arguement is not used if user has modify privileges */
512 if ((status = kadm_mod(&new, &new)) != KADM_SUCCESS)
514 if (status == KADM_NOENTRY)
516 com_err(whoami, 0, "kerberos principal doesn't exist; creating");
517 if ((status = kadm_add(&new)) != KADM_SUCCESS)
518 com_err(whoami, status, " while creating kerberos principal");
521 com_err(whoami, status, " while setting password");
529 int reserve_user(struct msg *message, char *retval)
531 int q_argc; /* Number of arguments to query */
532 char *q_argv[3]; /* Arguments to Moira query */
533 char *q_name; /* Name of Moira query */
534 int status = SUCCESS; /* General purpose error status */
535 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
536 char *login; /* The login name the user wants */
537 register int i; /* A counter */
539 /* Log that we are about to reserve a user. */
540 com_err(whoami, 0, "reserving user %s %s", message->first, message->last);
542 /* Check to make sure that we can verify this user. */
543 if ((status = verify_user(message, retval)) == SUCCESS)
545 /* Get the requested login name from leftover packet information. */
546 login = message->leftover;
548 /* Check the login name for validity. The login name is currently
549 is allowed to contain lowercase letters in any position and
550 and numbers and underscore characters in any position but the
552 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
553 status = UREG_INVALID_UNAME;
555 if (status == SUCCESS)
556 if ((login[0] == '_') || isdigit(login[0]))
557 status = UREG_INVALID_UNAME;
559 if (status == SUCCESS)
561 for (i = 0; i < strlen(login); i++)
563 if (!islower(login[i]) && !isdigit(login[i]) &&
566 status = UREG_INVALID_UNAME;
571 if (status == SUCCESS)
573 /* Now that we have a valid user with a valid login... */
575 /* First, try to reserve the user in Moira. */
576 sprintf(fstype_buf, "%d", MR_FS_STUDENT);
577 q_name = "register_user";
578 q_argv[0] = message->db.uid;
580 q_argv[2] = fstype_buf;
582 status = mr_query(q_name, q_argc, q_argv, null_callproc, NULL);
589 status = UREG_LOGIN_USED;
592 status = UREG_MISC_ERROR;
595 critical_alert(FAIL_INST, "%s returned from register_user.",
596 error_message(status));
597 status = UREG_MISC_ERROR;
602 if (status == SUCCESS)
605 * Moira login was successfully created; try to reserve kerberos
608 * If this routine fails, store the login in the retval so
609 * that it can be used in the client-side error message.
611 if ((status = reserve_krb(login)) != SUCCESS)
612 strcpy(retval, login);
616 com_err(whoami, status, " returned from reserve_user");
618 com_err(whoami, 0, "User reserved");
623 /* This routine updates a user's registration status to fully
625 int set_final_status(struct msg *message)
628 char *q_name; /* Name of Moira query */
629 int q_argc; /* Number of arguments for Moira query */
630 char *q_argv[2]; /* Arguments to get user by uid */
631 char state[7]; /* Can hold a 16 bit integer */
632 int status; /* Error status */
634 if (message->request == UREG_SET_PASSWORD)
635 sprintf(state, "%d", US_REGISTERED);
636 else if (message->db.reg_status == US_NO_LOGIN_YET)
637 sprintf(state, "%d", US_ENROLLED);
639 sprintf(state, "%d", US_ENROLL_NOT_ALLOWED);
641 login = message->db.login;
642 com_err(whoami, 0, "Setting final status for %s to %s", login, state);
644 q_name = "update_user_status";
648 if ((status = mr_query(q_name, q_argc, q_argv, null_callproc, NULL))
651 if (status == MR_DEADLOCK)
652 status = UREG_MISC_ERROR;
654 critical_alert(FAIL_INST, "%s returned from update_user_status.",
655 error_message(status));
658 com_err(whoami, status, " returned from set_final_status");
660 com_err(whoami, 0, "Final status set");
665 /* This routine is used to set the initial password for the new user. */
666 int set_password(struct msg *message, char *retval)
668 int status = SUCCESS; /* Return status */
669 char *passwd; /* User's password */
671 com_err(whoami, 0, "setting password %s %s", message->first, message->last);
673 status = verify_user(message, retval);
675 /* Don't set the password unless the registration status of the user
676 is that he exists and has no password. */
677 if (status == SUCCESS)
678 status = UREG_NO_LOGIN_YET;
679 if ((message->request == UREG_SET_PASSWORD &&
680 status == UREG_NO_PASSWD_YET) ||
681 (message->request == UREG_GET_KRB &&
682 status == UREG_HALF_ENROLLED))
684 /* User is in proper state for this transaction. */
686 passwd = message->leftover;
689 if ((status = setpass_krb(message->db.login, passwd)) != SUCCESS)
690 /* If failure, allow login name to be used in client error message */
691 strcpy(retval, message->db.login);
693 /* Otherwise, mark user as finished. */
694 status = set_final_status(message);
698 com_err(whoami, status, " returned from set_passwd");
700 com_err(whoami, 0, "Password set");
706 int getuserinfo(int argc, char **argv, char **qargv)
708 int status = SUCCESS;
713 critical_alert(FAIL_INST,
714 "Wrong number of args returned from get_user_by_uid");
719 qargv[U_NAME] = strsave(argv[U_NAME]);
720 for (i = 1; i < U_MODTIME; i++)
721 qargv[i + 1] = strsave(argv[i]);
722 qargv[U_MODTIME + 1] = NULL;
728 int set_identity(struct msg *message, char *retval)
730 int q_argc; /* Number of arguments to query */
731 char *q_argv[U_END]; /* Arguments to Moira query */
732 char *q_name; /* Name of Moira query */
733 int status = SUCCESS; /* General purpose error status */
734 char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
735 char *login; /* The login name the user wants */
736 register int i; /* A counter */
738 /* Log that we are about to reserve a user. */
739 com_err(whoami, 0, "setting identity %s %s",
740 message->first, message->last);
742 /* Check to make sure that we can verify this user. */
743 status = verify_user(message, retval);
744 if (status == SUCCESS || status == UREG_NOT_ALLOWED)
747 /* Get the requested login name from leftover packet information. */
748 login = message->leftover;
750 /* Check the login name for validity. The login name is currently
751 is allowed to contain lowercase letters in any position and
752 and numbers and underscore characters in any position but the
754 if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
755 status = UREG_INVALID_UNAME;
757 if (status == SUCCESS)
759 if ((login[0] == '_') || isdigit(login[0]))
760 status = UREG_INVALID_UNAME;
762 if (status == SUCCESS)
764 for (i = 0; i < strlen(login); i++)
766 if (!islower(login[i]) && !isdigit(login[i]) &&
769 status = UREG_INVALID_UNAME;
774 if (status == SUCCESS)
776 /* Now that we have a valid user with a valid login... */
778 q_argv[0] = message->db.uid;
779 status = mr_query("get_user_account_by_uid", 1, q_argv,
780 getuserinfo, (char *)q_argv);
781 if (status != SUCCESS)
783 com_err(whoami, status, " while getting user info");
786 q_argv[U_NAME + 1] = login;
787 q_argv[U_STATE + 1] = "7";
788 q_argv[U_SIGNATURE + 1] = "";
789 status = mr_query("update_user_account", U_MODTIME + 1, q_argv,
790 null_callproc, NULL);
798 status = UREG_LOGIN_USED;
801 status = UREG_MISC_ERROR;
804 critical_alert(FAIL_INST, "%s returned from update_user_account.",
805 error_message(status));
806 status = UREG_MISC_ERROR;
810 if (status == SUCCESS)
812 /* Moira login was successfully created; try to reserve kerberos
814 /* If this routine fails, store the login in the retval so
815 that it can be used in the client-side error message. */
816 if ((status = reserve_krb(login)) != SUCCESS)
817 strcpy(retval, login);
821 com_err(whoami, status, " returned from set_identity");
823 com_err(whoami, 0, "Identity set");
829 void reg_com_err_hook(char *whoami, int code, char *fmt, caddr_t pvar)
833 fputs(whoami, stderr);
837 fputs(error_message(code), stderr);
839 _doprnt(fmt, pvar, stderr);
845 /* Find out if someone's secure instance password is set.
846 * Returns UREG_ALREADY_REGISTERED if set, SUCCESS (0) if not.
849 int get_secure(struct msg *message, char *retval)
854 com_err(whoami, 0, "checking status of secure password for %s",
856 argv[0] = message->first;
857 status = mr_query("get_user_account_by_login", 1, argv, getuserinfo,
859 if (status != SUCCESS)
861 com_err(whoami, status, " while getting user info");
864 if (atoi(argv[U_SECURE + 1]))
865 return UREG_ALREADY_REGISTERED;
870 /* Set someone's secure instance password. */
872 int set_secure(struct msg *message, char *retval)
875 char *argv[U_END], hostbuf[256], *bp, *p, buf[512], *passwd, *id;
881 u_long *lkey = (u_long *)key;
883 static int inited = 0;
885 extern char *krb_get_phost(char *);
890 if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
891 com_err(whoami, errno, "getting local hostname");
892 host = strsave(krb_get_phost(hostbuf));
895 com_err(whoami, 0, "setting secure passwd for %s", message->first);
896 argv[0] = message->first;
897 status = mr_query("get_user_account_by_login", 1, argv, getuserinfo,
899 if (status != SUCCESS)
901 com_err(whoami, status, " while getting user info");
904 if (atoi(argv[U_SECURE + 1]))
906 com_err(whoami, UREG_ALREADY_REGISTERED, "in set_secure()");
907 return UREG_ALREADY_REGISTERED;
910 bp = message->encrypted;
911 /* round up to word boundary */
912 bp = (char *)((((u_long)bp + 3) >> 2) << 2);
914 creds.length = ntohl(*((int *)bp));
916 memcpy(creds.dat, bp, creds.length);
920 status = krb_rd_req(&creds, "changepw", host, cur_req_sender(), &auth, "");
923 status += krb_err_base;
924 com_err(whoami, status, " verifying credentials in set_secure()");
928 message->leftover_len = ntohl(*((int *)(bp)));
930 message->leftover = bp;
932 des_key_sched(auth.session, keys);
933 des_pcbc_encrypt(message->leftover, buf, message->leftover_len,
934 keys, auth.session, 0);
937 passwd = strchr(buf, ',');
940 if (strcmp(id, argv[U_MITID + 1]))
944 EncryptID(buf, id, argv[U_FIRST + 1], argv[U_LAST + 1]);
945 if (strcmp(buf, argv[U_MITID + 1]))
947 status = UREG_USER_NOT_FOUND;
948 com_err(whoami, status, "IDs mismatch: %s (%s), %s", id, buf,
954 /* now do actual password setting stuff */
956 if ((status = ureg_kadm_init()) != SUCCESS)
958 com_err(whoami, status, "initing kadm stuff");
962 memset(&kv, 0, sizeof(kv));
963 SET_FIELD(KADM_DESKEY, kv.fields);
964 SET_FIELD(KADM_NAME, kv.fields);
965 SET_FIELD(KADM_INST, kv.fields);
966 des_string_to_key(passwd, key);
967 kv.key_low = htonl(lkey[0]);
968 kv.key_high = htonl(lkey[1]);
969 strcpy(kv.name, message->first);
970 strcpy(kv.instance, "extra");
972 if ((status = kadm_add(&kv)) != KADM_SUCCESS)
974 com_err(whoami, status, " while creating kerberos principal");
978 argv[0] = message->first;
980 gettimeofday(&now, NULL);
981 sprintf(buf, "%d", now.tv_sec);
982 status = mr_query("update_user_security_status", 2, argv, getuserinfo,
984 if (status != SUCCESS)
986 com_err(whoami, status, " while updating user status");