char *mkey_fullname;
krb5_kvno use_kvno;
krb5_timestamp now, start_time;
- krb5_actkvno_node *actkvno_list, *new_actkvno_list_head, *new_actkvno,
+ krb5_actkvno_node *actkvno_list, *new_actkvno,
*prev_actkvno, *cur_actkvno;
krb5_db_entry master_entry;
int nentries = 0;
krb5_boolean more = 0, found;
krb5_keylist_node *keylist_node;
+ krb5_boolean inserted = FALSE;
if (argc < 2 || argc > 3) {
/* usage calls exit */
if (argc == 3) {
time_t t = get_date(argv[2]);
- if (t == -1) {
+ if (t == -1) {
com_err(progname, 0, "could not parse date-time string '%s'",
argv[2]);
exit_status++;
return;
}
- /* alloc enough space to hold new and existing key_data */
- new_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node));
- if (new_actkvno == NULL) {
- com_err(progname, ENOMEM, "while adding new master key");
- exit_status++;
- return;
- }
- memset(new_actkvno, 0, sizeof(krb5_actkvno_node));
-
- new_actkvno->act_kvno = use_kvno;
- new_actkvno->act_time = start_time;
-
/*
- * determine which nodes to delete and where to insert new act kvno node
+ * If an entry already exists with the same kvno either delete it or if it's
+ * the only entry, just set its active time.
*/
+ for (prev_actkvno = NULL, cur_actkvno = actkvno_list;
+ cur_actkvno != NULL;
+ prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) {
+
+ if (cur_actkvno->act_kvno == use_kvno) {
+ /* delete it */
+ if (prev_actkvno) {
+ prev_actkvno->next = cur_actkvno->next;
+ cur_actkvno->next = NULL;
+ krb5_dbe_free_actkvno_list(util_context, cur_actkvno);
+ } else {
+ if (cur_actkvno->next) {
+ /* delete it from front of list */
+ actkvno_list = cur_actkvno->next;
+ cur_actkvno->next = NULL;
+ krb5_dbe_free_actkvno_list(util_context, cur_actkvno);
+ } else {
+ /* There's only one entry, go ahead and change the time */
+ cur_actkvno->act_time = start_time;
+ inserted = TRUE;
+ }
+ }
+ break;
+ }
+ }
- if (actkvno_list == NULL) {
- /* new actkvno is the list */
- new_actkvno_list_head = new_actkvno;
- } else {
- krb5_boolean inserted = FALSE, trimed = FALSE;
+ if (!inserted) {
+ /* alloc enough space to hold new and existing key_data */
+ new_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node));
+ if (new_actkvno == NULL) {
+ com_err(progname, ENOMEM, "while adding new master key");
+ exit_status++;
+ return;
+ }
+ memset(new_actkvno, 0, sizeof(krb5_actkvno_node));
+ new_actkvno->act_kvno = use_kvno;
+ new_actkvno->act_time = start_time;
- for (prev_actkvno = NULL, cur_actkvno = actkvno_list;
- cur_actkvno != NULL;
- prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) {
+ /* insert new act kvno node */
+
+ if (actkvno_list == NULL) {
+ /* new actkvno is the list */
+ actkvno_list = new_actkvno;
+ } else {
+ for (prev_actkvno = NULL, cur_actkvno = actkvno_list;
+ cur_actkvno != NULL;
+ prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) {
- if (cur_actkvno->act_kvno == use_kvno) {
- cur_actkvno->act_time = start_time;
- inserted = TRUE; /* fake it */
- }
- if (!inserted) {
if (new_actkvno->act_time < cur_actkvno->act_time) {
if (prev_actkvno) {
prev_actkvno->next = new_actkvno;
new_actkvno->next = actkvno_list;
actkvno_list = new_actkvno;
}
- inserted = TRUE;
+ break;
} else if (cur_actkvno->next == NULL) {
/* end of line, just add new node to end of list */
cur_actkvno->next = new_actkvno;
- inserted = TRUE;
- }
- }
- if (!trimed) {
- /* trim entries in past that are superceded */
- if (cur_actkvno->act_time > now) {
- if (prev_actkvno) {
- new_actkvno_list_head = prev_actkvno;
- } else {
- new_actkvno_list_head = actkvno_list;
- }
- trimed = TRUE;
- } else if (cur_actkvno->next == NULL) {
- /* XXX this is buggy, fix soon. */
- new_actkvno_list_head = cur_actkvno;
- trimed = TRUE;
+ break;
}
}
- if (trimed && inserted)
- break;
}
}
- if ((retval = krb5_dbe_update_actkvno(util_context, &master_entry,
- new_actkvno_list_head))) {
- com_err(progname, retval, "while updating actkvno data for master principal entry");
+ if (actkvno_list->act_time > now) {
+ com_err(progname, EINVAL, "there must be one master key currently active");
exit_status++;
return;
}
+ if ((retval = krb5_dbe_update_actkvno(util_context, &master_entry,
+ /* new_actkvno_list_head))) { */
+ actkvno_list))) {
+ com_err(progname, retval, "while updating actkvno data for master principal entry");
+ exit_status++;
+ return;
+ }
+
if ((retval = krb5_dbe_update_mod_princ_data(util_context, &master_entry,
- now, master_princ))) {
+ now, master_princ))) {
com_err(progname, retval, "while updating the master key principal modification time");
exit_status++;
return;
}
if (actkvno_list != NULL) {
- act_time = 0;
+ act_time = -1; /* assume actkvno entry not found */
for (cur_actkvno = actkvno_list; cur_actkvno != NULL;
cur_actkvno = cur_actkvno->next) {
if (cur_actkvno->act_kvno == cur_kb_node->kvno) {
retval = asprintf(&output_str, "KNVO: %d, Enctype: %s, Active on: %s *\n",
cur_kb_node->kvno, enctype, strdate(act_time));
} else {
- if (act_time) {
+ if (act_time != -1) {
retval = asprintf(&output_str, "KNVO: %d, Enctype: %s, Active on: %s\n",
cur_kb_node->kvno, enctype, strdate(act_time));
} else {
if (nprinc != 1) {
if (nprinc) {
krb5_db_free_principal(context, &entry, nprinc);
+ return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ } else {
+ return(KRB5_KDB_NOMASTERKEY);
}
- return(KRB5_KDB_NOMASTERKEY);
} else if (more) {
krb5_db_free_principal(context, &entry, nprinc);
return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
retval = krb5_dbe_lookup_actkvno(context, &entry, act_key_list);
if (*act_key_list == NULL) {
- krb5_actkvno_node *tmp_actkvno;
- krb5_timestamp now;
+ krb5_actkvno_node *tmp_actkvno;
/*
* for mkey princ entries without KRB5_TL_ACTKVNO data provide a default
*/
- if ((retval = krb5_timeofday(context, &now)))
- return (retval);
-
tmp_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node));
if (tmp_actkvno == NULL)
return (ENOMEM);
memset(tmp_actkvno, 0, sizeof(krb5_actkvno_node));
- tmp_actkvno->act_time = now;
+ tmp_actkvno->act_time = 0; /* earliest time possible */
/* use most current key */
tmp_actkvno->act_kvno = entry.key_data[0].key_data_kvno;
-
*act_key_list = tmp_actkvno;
}
/*
* Locates the "active" mkey used when encrypting a princ's keys. Note, the
- * caller must not free the output act_mkey.
+ * caller must NOT free the output act_mkey.
*/
krb5_error_code
/*
* The list should be sorted in time, early to later so if the first entry
- * is later than now, this is a problem
+ * is later than now, this is a problem. The fallback in this case is to
+ * return the earlist activation entry.
*/
if (act_mkey_list->act_time > now) {
- return (KRB5_KDB_NOACTMASTERKEY);
+ while (cur_keyblock && cur_keyblock->kvno != act_mkey_list->act_kvno)
+ cur_keyblock = cur_keyblock->next;
+ if (cur_keyblock) {
+ *act_mkey = &cur_keyblock->keyblock;
+ if (act_kvno != NULL)
+ *act_kvno = cur_keyblock->kvno;
+ return (0);
+ } else {
+ return (KRB5_KDB_NOACTMASTERKEY);
+ }
}
/* find the most current entry <= now */