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 */