*
* $Header$
*/
-#include <assert.h>
-#include <sys/types.h>
+#include "k5-int.h"
#include <sys/time.h>
-#include <errno.h>
#include <kadm5/admin.h>
#include <kdb.h>
-#include <stdio.h>
-#include <string.h>
#include "server_internal.h"
-#include <stdarg.h>
-#include <stdlib.h>
#ifdef USE_PASSWORD_SERVER
#include <sys/wait.h>
#include <signal.h>
-
#endif
#include <krb5/kadm5_hook_plugin.h>
extern krb5_principal master_princ;
extern krb5_principal hist_princ;
extern krb5_keyblock master_keyblock;
-extern krb5_keylist_node *master_keylist;
extern krb5_actkvno_node *active_mkey_list;
extern krb5_db_entry master_db;
*/
if(!(mask & KADM5_PRINCIPAL) || (mask & KADM5_MOD_NAME) ||
(mask & KADM5_MOD_TIME) || (mask & KADM5_LAST_PWD_CHANGE) ||
- (mask & KADM5_MKVNO) || (mask & KADM5_POLICY_CLR) ||
- (mask & KADM5_AUX_ATTRIBUTES) || (mask & KADM5_KEY_DATA) ||
- (mask & KADM5_LAST_SUCCESS) || (mask & KADM5_LAST_FAILED) ||
- (mask & KADM5_FAIL_AUTH_COUNT))
+ (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) ||
+ (mask & KADM5_KEY_DATA) || (mask & KADM5_LAST_SUCCESS) ||
+ (mask & KADM5_LAST_FAILED) || (mask & KADM5_FAIL_AUTH_COUNT))
+ return KADM5_BAD_MASK;
+ if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR))
return KADM5_BAD_MASK;
if((mask & ~ALL_PRINC_MASK))
return KADM5_BAD_MASK;
/* initialize the keys */
- ret = krb5_dbe_find_act_mkey(handle->context, master_keylist,
- active_mkey_list, &act_kvno, &act_mkey);
+ ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, &act_kvno,
+ &act_mkey);
if (ret)
goto cleanup;
kadm5_rename_principal(void *server_handle,
krb5_principal source, krb5_principal target)
{
- krb5_db_entry *kdb;
- osa_princ_ent_rec adb;
- int ret, i;
+ krb5_db_entry *kdb;
+ osa_princ_ent_rec adb;
+ krb5_error_code ret;
kadm5_server_handle_t handle = server_handle;
+ krb5_int16 stype, i;
+ krb5_data *salt = NULL;
CHECK_HANDLE(server_handle);
if ((ret = kdb_get_entry(handle, source, &kdb, &adb)))
return ret;
- /* this is kinda gross, but unavoidable */
-
- for (i=0; i<kdb->n_key_data; i++) {
- if ((kdb->key_data[i].key_data_ver == 1) ||
- (kdb->key_data[i].key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)) {
+ /* Transform salts as necessary. */
+ for (i = 0; i < kdb->n_key_data; i++) {
+ ret = krb5_dbe_compute_salt(handle->context, &kdb->key_data[i],
+ kdb->princ, &stype, &salt);
+ if (ret == KRB5_KDB_BAD_SALTTYPE)
ret = KADM5_NO_RENAME_SALT;
+ if (ret)
goto done;
- }
+ kdb->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
+ free(kdb->key_data[i].key_data_contents[1]);
+ kdb->key_data[i].key_data_contents[1] = (krb5_octet *)salt->data;
+ kdb->key_data[i].key_data_length[1] = salt->length;
+ kdb->key_data[i].key_data_ver = 2;
+ free(salt);
+ salt = NULL;
}
kadm5_free_principal(handle->context, kdb->princ);
ret = kdb_delete_entry(handle, source);
done:
+ krb5_free_data(handle->context, salt);
kdb_free_entry(handle, kdb, &adb);
return ret;
}
entry->kvno = kdb->key_data[i].key_data_kvno;
if (mask & KADM5_MKVNO) {
- ret = krb5_dbe_get_mkvno(handle->context, kdb, master_keylist,
- &entry->mkvno);
+ ret = krb5_dbe_get_mkvno(handle->context, kdb, &entry->mkvno);
if (ret)
goto done;
}
*/
static kadm5_ret_t
check_pw_reuse(krb5_context context,
- krb5_keyblock *hist_keyblock,
+ krb5_keyblock *hist_keyblocks,
int n_new_key_data, krb5_key_data *new_key_data,
unsigned int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data)
{
unsigned int x, y, z;
- krb5_keyblock newkey, histkey;
+ krb5_keyblock newkey, histkey, *kb;
+ krb5_key_data *key_data;
krb5_error_code ret;
assert (n_new_key_data >= 0);
for (x = 0; x < (unsigned) n_new_key_data; x++) {
+ /* Check only entries with the most recent kvno. */
+ if (new_key_data[x].key_data_kvno != new_key_data[0].key_data_kvno)
+ break;
ret = krb5_dbe_decrypt_key_data(context, NULL, &(new_key_data[x]),
&newkey, NULL);
if (ret)
return(ret);
for (y = 0; y < n_pw_hist_data; y++) {
for (z = 0; z < (unsigned int) pw_hist_data[y].n_key_data; z++) {
- ret = krb5_dbe_decrypt_key_data(context, hist_keyblock,
- &pw_hist_data[y].key_data[z],
- &histkey, NULL);
- if (ret)
- return(ret);
-
- if ((newkey.length == histkey.length) &&
- (newkey.enctype == histkey.enctype) &&
- (memcmp(newkey.contents, histkey.contents,
- histkey.length) == 0)) {
+ for (kb = hist_keyblocks; kb->enctype != 0; kb++) {
+ key_data = &pw_hist_data[y].key_data[z];
+ ret = krb5_dbe_decrypt_key_data(context, kb, key_data,
+ &histkey, NULL);
+ if (ret)
+ continue;
+ if (newkey.length == histkey.length &&
+ newkey.enctype == histkey.enctype &&
+ memcmp(newkey.contents, histkey.contents,
+ histkey.length) == 0) {
+ krb5_free_keyblock_contents(context, &histkey);
+ krb5_free_keyblock_contents(context, &newkey);
+ return KADM5_PASS_REUSE;
+ }
krb5_free_keyblock_contents(context, &histkey);
- krb5_free_keyblock_contents(context, &newkey);
-
- return(KADM5_PASS_REUSE);
}
- krb5_free_keyblock_contents(context, &histkey);
}
}
krb5_free_keyblock_contents(context, &newkey);
krb5_int32 now;
kadm5_policy_ent_rec pol;
osa_princ_ent_rec adb;
- krb5_db_entry *kdb, *kdb_save;
+ krb5_db_entry *kdb;
int ret, ret2, last_pwd, hist_added;
int have_pol = 0;
kadm5_server_handle_t handle = server_handle;
osa_pw_hist_ent hist;
- krb5_keyblock *act_mkey, hist_keyblock;
+ krb5_keyblock *act_mkey, *hist_keyblocks = NULL;
krb5_kvno act_kvno, hist_kvno;
CHECK_HANDLE(server_handle);
hist_added = 0;
memset(&hist, 0, sizeof(hist));
- memset(&hist_keyblock, 0, sizeof(hist_keyblock));
if (principal == NULL || password == NULL)
return EINVAL;
if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
return(ret);
- /* we are going to need the current keys after the new keys are set */
- if ((ret = kdb_get_entry(handle, principal, &kdb_save, NULL))) {
- kdb_free_entry(handle, kdb, &adb);
- return(ret);
- }
-
if ((adb.aux_attributes & KADM5_POLICY)) {
if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, &pol)))
goto done;
have_pol = 1;
+
+ /* Create a password history entry before we change kdb's key_data. */
+ ret = kdb_get_hist_key(handle, &hist_keyblocks, &hist_kvno);
+ if (ret)
+ goto done;
+ ret = create_history_entry(handle->context, &hist_keyblocks[0],
+ kdb->n_key_data, kdb->key_data, &hist);
+ if (ret)
+ goto done;
}
if ((ret = passwd_check(handle, password, have_pol ? &pol : NULL,
principal)))
goto done;
- ret = krb5_dbe_find_act_mkey(handle->context, master_keylist,
- active_mkey_list, &act_kvno, &act_mkey);
+ ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, &act_kvno,
+ &act_mkey);
if (ret)
goto done;
}
#endif
- ret = kdb_get_hist_key(handle, &hist_keyblock, &hist_kvno);
- if (ret)
- goto done;
-
- ret = create_history_entry(handle->context,
- &hist_keyblock,
- kdb_save->n_key_data,
- kdb_save->key_data, &hist);
- if (ret)
- goto done;
-
- ret = check_pw_reuse(handle->context, &hist_keyblock,
+ ret = check_pw_reuse(handle->context, hist_keyblocks,
kdb->n_key_data, kdb->key_data,
1, &hist);
if (ret)
/* If hist_kvno has changed since the last password change, we
* can't check the history. */
if (adb.admin_history_kvno == hist_kvno) {
- ret = check_pw_reuse(handle->context, &hist_keyblock,
+ ret = check_pw_reuse(handle->context, hist_keyblocks,
kdb->n_key_data, kdb->key_data,
adb.old_key_len, adb.old_keys);
if (ret)
if (!hist_added && hist.key_data)
free_history_entry(handle->context, &hist);
kdb_free_entry(handle, kdb, &adb);
- kdb_free_entry(handle, kdb_save, NULL);
- krb5_free_keyblock_contents(handle->context, &hist_keyblock);
+ kdb_free_keyblocks(handle, hist_keyblocks);
if (have_pol && (ret2 = kadm5_free_policy_ent(handle->lhandle, &pol))
&& !ret)
if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
return(ret);
- ret = krb5_dbe_find_act_mkey(handle->context, master_keylist,
- active_mkey_list, NULL, &act_mkey);
+ ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, NULL,
+ &act_mkey);
if (ret)
goto done;
keysalt.data.length = 0;
keysalt.data.data = NULL;
- ret = krb5_dbe_find_act_mkey(handle->context, master_keylist,
- active_mkey_list, NULL, &act_mkey);
+ ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, NULL,
+ &act_mkey);
if (ret)
goto done;
}
memset (&tmp_key_data, 0, sizeof(tmp_key_data));
- ret = krb5_dbe_find_act_mkey(handle->context, master_keylist,
- active_mkey_list, NULL, &act_mkey);
+ ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, NULL,
+ &act_mkey);
if (ret)
goto done;
/* find_mkey only uses this field */
dbent.tl_data = entry->tl_data;
- if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, &dbent,
- &mkey_ptr))) {
- krb5_keylist_node *tmp_mkey_list;
+ if ((ret = krb5_dbe_find_mkey(handle->context, &dbent, &mkey_ptr))) {
/* try refreshing master key list */
/* XXX it would nice if we had the mkvno here for optimization */
if (krb5_db_fetch_mkey_list(handle->context, master_princ,
- &master_keyblock, 0, &tmp_mkey_list) == 0) {
- krb5_dbe_free_key_list(handle->context, master_keylist);
- master_keylist = tmp_mkey_list;
- if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist,
- &dbent, &mkey_ptr))) {
+ &master_keyblock) == 0) {
+ if ((ret = krb5_dbe_find_mkey(handle->context, &dbent,
+ &mkey_ptr))) {
return ret;
}
} else {
kdb_free_entry(handle, kdb, &adb);
return ret;
}
+
+kadm5_ret_t
+kadm5_get_strings(void *server_handle, krb5_principal principal,
+ krb5_string_attr **strings_out, int *count_out)
+{
+ kadm5_server_handle_t handle = server_handle;
+ kadm5_ret_t ret;
+ krb5_db_entry *kdb = NULL;
+
+ *strings_out = NULL;
+ *count_out = 0;
+ CHECK_HANDLE(server_handle);
+ if (principal == NULL)
+ return EINVAL;
+
+ ret = kdb_get_entry(handle, principal, &kdb, NULL);
+ if (ret)
+ return ret;
+
+ ret = krb5_dbe_get_strings(handle->context, kdb, strings_out, count_out);
+ kdb_free_entry(handle, kdb, NULL);
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_set_string(void *server_handle, krb5_principal principal,
+ const char *key, const char *value)
+{
+ kadm5_server_handle_t handle = server_handle;
+ kadm5_ret_t ret;
+ krb5_db_entry *kdb;
+ osa_princ_ent_rec adb;
+
+ CHECK_HANDLE(server_handle);
+ if (principal == NULL || key == NULL)
+ return EINVAL;
+
+ ret = kdb_get_entry(handle, principal, &kdb, &adb);
+ if (ret)
+ return ret;
+
+ ret = krb5_dbe_set_string(handle->context, kdb, key, value);
+ if (ret)
+ goto done;
+
+ kdb->mask = KADM5_TL_DATA;
+ ret = kdb_put_entry(handle, kdb, &adb);
+
+done:
+ kdb_free_entry(handle, kdb, &adb);
+ return ret;
+}