#include <stdio.h>
#include <strings.h>
#include <ctype.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/file.h>
#include <krb.h>
init_ureg_err_tbl();
init_krb_err_tbl();
init_kadm_err_tbl();
+ initialize_gdss_error_table();
/* Use com_err or output to stderr for all log messages. */
#ifdef DEBUG
case UREG_SET_IDENT:
status = set_identity(&message,retval);
break;
+ case UREG_GET_SECURE:
+ status = get_secure(&message,retval);
+ break;
+ case UREG_SET_SECURE:
+ status = set_secure(&message,retval);
+ break;
default:
status = UREG_UNKNOWN_REQUEST;
critical_alert(FAIL_INST,"Unknown request %d from userreg.",
the ID sent accross in the packet. The information in the packet
was created in the following way:
+ The database used to contain encrypted IDs. Now we don't encrypt
+ them in the database, although there are still some encrypted IDs
+ there.
+
The plain text ID number was encrypted via EncryptID() resulting
in the form that would appear in the Moira database. This is
concatinated to the plain text ID so that the ID string contains plain
thing is then DES encrypted using the encrypted ID as the source of
the key.
- This routine tries each encrypted ID in the database that belongs
+ This routine tries each ID in the database that belongs
to someone with this user's first and last name and tries to
decrypt the packet with this information. If it succeeds, it returns
zero and initializes all the fields of the formatted packet structure
because of the DES encryption routines. */
decrypt_len = (long)message->encrypted_len;
- /* Get key from the one-way encrypted ID in the Moira database */
- des_string_to_key(data->mit_id, key);
+ /* Get key from the possibly one-way encrypted ID in the Moira database */
+ if (data->mit_id[0] >= '0' && data->mit_id[0] <= '9') {
+ char buf[32];
+
+ EncryptID(buf, data->mit_id, message->first, message->last);
+ des_string_to_key(buf, key);
+ } else
+ des_string_to_key(data->mit_id, key);
+
/* Get schedule from key */
des_key_sched(key, sched);
/* Decrypt information from packet using this key. Since decrypt_len
correct key, there is no guarantee that a null will occur
anywhere in the string. */
(void) strncpy(idnumber,decrypt,(int)decrypt_len);
+ /* Check that the idnumber of a mismatched decryption doesn't overflow
+ * the buffer.
+ */
+ if (strlen(idnumber) != 9) {
+#ifdef DEBUG
+ com_err(whoami, 0, "idnumber wrong size, probable user mismatch\n");
+#endif
+ return(FAILURE);
+ }
/* Point temp to the end of the plain text ID number. */
temp = decrypt + strlen(idnumber) + 1;
/* Find out how much more packet there is. */
/* Find out how much more room there is. */
len = message->encrypted_len - (temp - decrypt);
- /* Now compare encrypted ID's don't match. */
- if (strcmp(hashid, data->mit_id)) status = FAILURE;
- if (status == SUCCESS)
- {
- EncryptID(recrypt, idnumber, message->first, message->last);
- /* Now compare encrypted plain text to ID from database. */
- if (strcmp(recrypt, data->mit_id)) status = FAILURE;
- }
+ /* Now compare encrypted ID and clear text ID for a match. */
+ if (strcmp(hashid, data->mit_id) &&
+ strcmp(idnumber, data->mit_id))
+ status = FAILURE;
if (status == SUCCESS)
{
{
critical_alert
(FAIL_INST,
- "Wrong number of arguments returned from get_user_by_name.");
+ "Wrong number of arguments returned from get_user_account_by_name.");
status = MR_ABORT;
}
else
if (status == SUCCESS)
{
/* Get ready to make an Moira query */
- q_name = "get_user_by_name";
+ q_name = "get_user_account_by_name";
q_argc = GUBN_ARGS; /* #defined in this routine */
q_argv[0] = message->first;
q_argv[1] = message->last;
char **qargv;
{
int status = SUCCESS;
+ int i;
if (argc != U_END) {
critical_alert(FAIL_INST,
status = MR_ABORT;
} else {
qargv[U_NAME] = strsave(argv[U_NAME]);
- qargv[U_UID+1] = strsave(argv[U_UID]);
- qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
- qargv[U_LAST+1] = strsave(argv[U_LAST]);
- qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
- qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
- qargv[U_STATE+1] = strsave(argv[U_STATE]);
- qargv[U_MITID+1] = strsave(argv[U_MITID]);
- qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
+ for (i = 1; i < U_MODTIME; i++)
+ qargv[i+1] = strsave(argv[i]);
qargv[U_MODTIME+1] = NULL;
}
return(status);
/* Now that we have a valid user with a valid login... */
q_argv[0] = message->db.uid;
- status = mr_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
+ status = mr_query("get_user_account_by_uid", 1, q_argv,
+ getuserinfo, q_argv);
if (status != SUCCESS) {
com_err(whoami, status, " while getting user info");
return(status);
}
q_argv[U_NAME+1] = login;
q_argv[U_STATE+1] = "7";
- status = mr_query("update_user", U_MODTIME+1, q_argv,
+ q_argv[U_SIGNATURE+1] = "";
+ status = mr_query("update_user_account", U_MODTIME+1, q_argv,
null_callproc, NULL);
switch (status)
{
status = SUCCESS;
break;
case MR_IN_USE:
+ case MR_NOT_UNIQUE:
status = UREG_LOGIN_USED;
break;
case MR_DEADLOCK:
status = UREG_MISC_ERROR;
break;
default:
- critical_alert(FAIL_INST,"%s returned from update_user.",
+ critical_alert(FAIL_INST,"%s returned from update_user_account.",
error_message(status));
status = UREG_MISC_ERROR;
break;
putc('\n', stderr);
fflush(stderr);
}
+
+
+/* Find out of someone's secure instance password is set.
+ * Returns UREG_ALREADY_REGISTERED if set, SUCCESS (0) if not.
+ */
+
+int get_secure(message, retval)
+struct msg *message;
+char *retval;
+{
+ int status;
+ char *argv[U_END];
+
+ com_err(whoami, 0, "checking status of secure password for %s",
+ message->first);
+ argv[0] = message->first;
+ status = mr_query("get_user_account_by_login", 1, argv, getuserinfo, argv);
+ if (status != SUCCESS) {
+ com_err(whoami, status, " while getting user info");
+ return(status);
+ }
+ if (atoi(argv[U_SECURE + 1]))
+ return UREG_ALREADY_REGISTERED;
+ return SUCCESS;
+}
+
+
+/* Set someone's secure instance password. */
+
+int set_secure(message, retval)
+struct msg *message;
+char *retval;
+{
+ int status, i;
+ char *argv[U_END], hostbuf[256], *bp, *p, buf[512], *passwd, *id;
+ KTEXT_ST creds;
+ AUTH_DAT auth;
+ C_Block key;
+ Key_schedule keys;
+ Kadm_vals kv;
+ u_long *lkey = (u_long *)key;
+ struct timeval now;
+ static int inited = 0;
+ static char *host;
+
+ if (!inited) {
+ inited++;
+ if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
+ com_err(whoami, errno, "getting local hostname");
+ host = strsave(krb_get_phost(hostbuf));
+ }
+
+ com_err(whoami, 0, "setting secure passwd for %s", message->first);
+ argv[0] = message->first;
+ status = mr_query("get_user_account_by_login", 1, argv, getuserinfo, argv);
+ if (status != SUCCESS) {
+ com_err(whoami, status, " while getting user info");
+ return(status);
+ }
+ if (atoi(argv[U_SECURE + 1])) {
+ com_err(whoami, UREG_ALREADY_REGISTERED, "in set_secure()");
+ return UREG_ALREADY_REGISTERED;
+ }
+
+ bp = message->encrypted;
+ /* round up to word boundary */
+ bp = (char *)((((u_long)bp + 3) >> 2) << 2);
+
+ creds.length = ntohl(*((int *)bp));
+ bp += sizeof(int);
+ bcopy(bp, creds.dat, creds.length);
+ creds.mbz = 0;
+ bp += creds.length;
+
+#ifdef DEBUG
+ com_err(whoami, 0, "Cred: length %d", creds.length);
+ for (i = 0; i < creds.length; i += 16)
+ com_err(whoami, 0, " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+ creds.dat[i+0], creds.dat[i+1], creds.dat[i+2], creds.dat[i+3],
+ creds.dat[i+4], creds.dat[i+5], creds.dat[i+6], creds.dat[i+7],
+ creds.dat[i+8], creds.dat[i+9], creds.dat[i+10], creds.dat[i+11],
+ creds.dat[i+12], creds.dat[i+13], creds.dat[i+14], creds.dat[i+15]);
+#endif /* DEBUG */
+
+ status = krb_rd_req(&creds, "changepw", host, cur_req_sender(),
+ &auth, "");
+ if (status) {
+ status += krb_err_base;
+ com_err(whoami, status, " verifying credentials in set_secure()");
+ return(status);
+ }
+
+ message->leftover_len = ntohl(*((int*)(bp)));
+ bp += sizeof(int);
+ message->leftover = bp;
+
+ des_key_sched(auth.session, keys);
+ des_pcbc_encrypt(message->leftover, buf, message->leftover_len,
+ keys, auth.session, 0);
+
+ id = buf;
+ passwd = index(buf, ',');
+ *passwd++ = 0;
+#ifdef DEBUG
+ com_err(whoami, 0, "Got id: %s, passwd %d chars", id, strlen(passwd));
+#endif
+
+ if (strcmp(id, argv[U_MITID + 1])) {
+ char buf[32];
+
+ EncryptID(buf, id, argv[U_FIRST+1], argv[U_LAST+1]);
+ if (strcmp(buf, argv[U_MITID + 1])) {
+ status = UREG_USER_NOT_FOUND;
+ com_err(whoami, status, "IDs mismatch: %s (%s), %s", id, buf,
+ argv[U_MITID + 1]);
+ return status;
+ }
+ }
+
+ /* now do actual password setting stuff */
+
+ if ((status = ureg_kadm_init()) != SUCCESS) {
+ com_err(whoami, status, "initing kadm stuff");
+ return(status);
+ }
+
+ bzero((char *)&kv, sizeof(kv));
+ SET_FIELD(KADM_DESKEY, kv.fields);
+ SET_FIELD(KADM_NAME, kv.fields);
+ SET_FIELD(KADM_INST, kv.fields);
+ (void) des_string_to_key(passwd, key);
+ kv.key_low = htonl(lkey[0]);
+ kv.key_high = htonl(lkey[1]);
+ strcpy(kv.name, message->first);
+ strcpy(kv.instance, "extra");
+
+ if ((status = kadm_add(&kv)) != KADM_SUCCESS) {
+ com_err(whoami, status, " while creating kerberos principal");
+ return(status);
+ }
+
+ argv[0] = message->first;
+ argv[1] = buf;
+ gettimeofday(&now, NULL);
+ sprintf(buf, "%d", now.tv_sec);
+ status = mr_query("update_user_security_status", 2, argv, getuserinfo, argv);
+ if (status != SUCCESS) {
+ com_err(whoami, status, " while updating user status");
+ return(status);
+ }
+ return SUCCESS;
+}