From b80b21c8a8edb864afedb83dd249498e408fe201 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Tue, 25 Mar 2014 21:45:10 -0500 Subject: [PATCH] Make kadmin ext work when lacking get-keys priv When we added the get-keys privilege we lost the ability to setup keytabs with the kadmin ext command. The fix is to note that we got bogus key data and randkey (as we used to). --- kadmin/ext.c | 28 ++++++++++++++++++++-------- lib/kadm5/admin.h | 4 ++++ lib/kadm5/marshall.c | 6 ++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/kadmin/ext.c b/kadmin/ext.c index cce38bc17..7f4ec3e18 100644 --- a/kadmin/ext.c +++ b/kadmin/ext.c @@ -46,15 +46,16 @@ do_ext_keytab(krb5_principal principal, void *data) struct ext_keytab_data *e = data; krb5_keytab_entry *keys = NULL; krb5_keyblock *k = NULL; - int i, n_k; + int i; + int n_k = 0; ret = kadm5_get_principal(kadm_handle, principal, &princ, KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA); - if(ret) + if (ret) return ret; if (princ.n_key_data) { - keys = malloc(sizeof(*keys) * princ.n_key_data); + keys = calloc(sizeof(*keys), princ.n_key_data); if (keys == NULL) { kadm5_free_principal_ent(kadm_handle, &princ); krb5_clear_error_message(context); @@ -63,22 +64,33 @@ do_ext_keytab(krb5_principal principal, void *data) for (i = 0; i < princ.n_key_data; i++) { krb5_key_data *kd = &princ.key_data[i]; + /* + * If the kadm5 client princ lacks get-keys then it may get + * bogus keys four bytes long. + */ + if (kd->key_data_length[0] == sizeof (KADM5_BOGUS_KEY_DATA) - 1 && + memcmp(kd->key_data_contents[0], KADM5_BOGUS_KEY_DATA, + kd->key_data_length[0]) == 0) + continue; + keys[i].principal = princ.principal; keys[i].vno = kd->key_data_kvno; keys[i].keyblock.keytype = kd->key_data_type[0]; keys[i].keyblock.keyvalue.length = kd->key_data_length[0]; keys[i].keyblock.keyvalue.data = kd->key_data_contents[0]; keys[i].timestamp = time(NULL); + n_k++; } + } - n_k = princ.n_key_data; - } else { + if (n_k == 0) { + /* Probably lack get-keys privilege, but we may be able to set keys */ ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k); if (ret) { kadm5_free_principal_ent(kadm_handle, &princ); return ret; } - keys = malloc(sizeof(*keys) * n_k); + keys = calloc(sizeof(*keys), n_k); if (keys == NULL) { kadm5_free_principal_ent(kadm_handle, &princ); krb5_clear_error_message(context); @@ -92,9 +104,9 @@ do_ext_keytab(krb5_principal principal, void *data) } } - for(i = 0; i < n_k; i++) { + for (i = 0; i < n_k; i++) { ret = krb5_kt_add_entry(context, e->keytab, &keys[i]); - if(ret) + if (ret) krb5_warn(context, ret, "krb5_kt_add_entry(%d)", i); } diff --git a/lib/kadm5/admin.h b/lib/kadm5/admin.h index 1ddb4d41c..0fe4e03b4 100644 --- a/lib/kadm5/admin.h +++ b/lib/kadm5/admin.h @@ -201,8 +201,12 @@ typedef struct _kadm5_policy_ent_t { #define KADM5_PRIV_LIST (1 << 4) #define KADM5_PRIV_CPW (1 << 5) #define KADM5_PRIV_GET_KEYS (1 << 6) + +/* Note: KADM5_PRIV_GET_KEYS not included */ #define KADM5_PRIV_ALL (KADM5_PRIV_GET | KADM5_PRIV_ADD | KADM5_PRIV_MODIFY | KADM5_PRIV_DELETE | KADM5_PRIV_LIST | KADM5_PRIV_CPW) +#define KADM5_BOGUS_KEY_DATA "\xe5\xe5\xe5\xe5" + typedef struct _kadm5_config_params { uint32_t mask; diff --git a/lib/kadm5/marshall.c b/lib/kadm5/marshall.c index d203af237..4a726dbaf 100644 --- a/lib/kadm5/marshall.c +++ b/lib/kadm5/marshall.c @@ -57,7 +57,6 @@ kadm5_ret_t kadm5_store_fake_key_data(krb5_storage *sp, krb5_key_data *key) { - char buf[4] = {0}; krb5_data c; krb5_store_int32(sp, key->key_data_ver); @@ -72,9 +71,8 @@ kadm5_store_fake_key_data(krb5_storage *sp, * did want keys will either fail or they'll, say, create bogus * keytab entries that will subsequently fail to be useful. */ - c.length = sizeof (buf); - c.data = buf; - memset(buf, 0xdeadcee5, sizeof (buf)); /* bad bad hexspeak for deadkeys */ + c.length = sizeof (KADM5_BOGUS_KEY_DATA) - 1; + c.data = KADM5_BOGUS_KEY_DATA; krb5_store_data(sp, c); /* This is the salt -- no need to send garbage */