/** * This function adds a key to an HDB entry's key history. * * @param context Context * @param entry HDB entry * @param kvno Key version number of the key to add to the history * @param key The Key to add */ krb5_error_code hdb_add_history_key(krb5_context context, hdb_entry *entry, krb5_kvno kvno, Key *key) { size_t i; hdb_keyset keyset; HDB_Ext_KeySet *hist_keys; HDB_extension ext; HDB_extension *extp; krb5_error_code ret; memset(&keyset, 0, sizeof (keyset)); memset(&ext, 0, sizeof (ext)); extp = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); if (extp == NULL) { ext.data.element = choice_HDB_extension_data_hist_keys; extp = &ext; } extp->mandatory = FALSE; hist_keys = &extp->data.u.hist_keys; for (i = 0; i < hist_keys->len; i++) { if (hist_keys->val[i].kvno == kvno) { ret = add_Keys(&hist_keys->val[i].keys, key); goto out; } } keyset.kvno = kvno; ret = add_Keys(&keyset.keys, key); if (ret) goto out; ret = add_HDB_Ext_KeySet(hist_keys, &keyset); if (ret) goto out; if (extp == &ext) { ret = hdb_replace_extension(context, entry, &ext); if (ret) goto out; } out: free_hdb_keyset(&keyset); free_HDB_extension(&ext); return ret; }
/** * Server-side function to set new keys for a principal. */ kadm5_ret_t kadm5_s_setkey_principal_3(void *server_handle, krb5_principal princ, krb5_boolean keepold, int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, krb5_keyblock *keyblocks, int n_keys) { kadm5_server_context *context = server_handle; hdb_entry_ex ent; kadm5_ret_t ret = 0; memset(&ent, 0, sizeof(ent)); if (!context->keep_open) ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); if (ret) return ret; ret = kadm5_log_init(context); if (ret) { if (!context->keep_open) context->db->hdb_close(context->context, context->db); return ret; } ret = context->db->hdb_fetch_kvno(context->context, context->db, princ, HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent); if (ret) { (void) kadm5_log_end(context); if (!context->keep_open) context->db->hdb_close(context->context, context->db); return ret; } if (keepold) { ret = hdb_add_current_keys_to_history(context->context, &ent.entry); } else ret = hdb_clear_extension(context->context, &ent.entry, choice_HDB_extension_data_hist_keys); /* * Though in practice all real calls to this function will pass an empty * ks_tuple, and cannot in any case employ any salts that require * additional data, we go the extra mile to set any requested salt type * along with a zero length salt value. While we're at it we check that * each ks_tuple's enctype matches the corresponding key enctype. */ if (ret == 0) { int i; free_Keys(&ent.entry.keys); for (i = 0; i < n_keys; ++i) { Key k; Salt s; k.mkvno = 0; k.key = keyblocks[i]; if (n_ks_tuple == 0) k.salt = 0; else { if (ks_tuple[i].ks_enctype != keyblocks[i].keytype) { ret = KADM5_SETKEY3_ETYPE_MISMATCH; break; } s.type = ks_tuple[i].ks_salttype; s.salt.data = 0; s.opaque = 0; k.salt = &s; } if ((ret = add_Keys(&ent.entry.keys, &k)) != 0) break; } } if (ret == 0) { ent.entry.kvno++; ent.entry.flags.require_pwchange = 0; hdb_entry_set_pw_change_time(context->context, &ent.entry, 0); hdb_entry_clear_password(context->context, &ent.entry); if ((ret = hdb_seal_keys(context->context, context->db, &ent.entry)) == 0 && (ret = _kadm5_set_modifier(context, &ent.entry)) == 0 && (ret = _kadm5_bump_pw_expire(context, &ent.entry)) == 0) ret = kadm5_log_modify(context, &ent.entry, KADM5_ATTRIBUTES | KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME | KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION | KADM5_TL_DATA); } hdb_free_entry(context->context, &ent); (void) kadm5_log_end(context); if (!context->keep_open) context->db->hdb_close(context->context, context->db); return _kadm5_error_code(ret); }