diff --git a/kadmin/server.c b/kadmin/server.c index 75bd214e7..3a8f68fff 100644 --- a/kadmin/server.c +++ b/kadmin/server.c @@ -47,6 +47,9 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, kadm5_principal_ent_rec ent; char *password, *expression; krb5_keyblock *new_keys; + krb5_key_salt_tuple *ks_tuple = NULL; + krb5_boolean keepold = FALSE; + int n_ks_tuple = 0; int n_keys; char **princs; int n_princs; @@ -355,9 +358,47 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, krb5_free_principal(contextp->context, princ); goto fail; } - ret = kadm5_randkey_principal(kadm_handlep, princ, - &new_keys, &n_keys); - krb5_free_principal(contextp->context, princ); + + /* + * See comments in kadm5_c_randkey_principal() regarding the + * protocol. + */ + ret = krb5_ret_int32(sp, &keepold); + if (ret != 0 && ret != HEIM_ERR_EOF) { + krb5_free_principal(contextp->context, princ); + goto fail; + } + + ret = krb5_ret_int32(sp, &n_ks_tuple); + if (ret != 0 && ret != HEIM_ERR_EOF) { + krb5_free_principal(contextp->context, princ); + goto fail; + } else if (ret == 0) { + size_t i; + + if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) { + ret = errno; + krb5_free_principal(contextp->context, princ); + goto fail; + } + + for (i = 0; i < n_ks_tuple; i++) { + ret = krb5_ret_int32(sp, &ks_tuple[i].ks_enctype); + if (ret != 0) { + krb5_free_principal(contextp->context, princ); + goto fail; + } + ret = krb5_ret_int32(sp, &ks_tuple[i].ks_salttype); + if (ret != 0) { + krb5_free_principal(contextp->context, princ); + goto fail; + } + } + } + ret = kadm5_randkey_principal_3(kadm_handle, princ, keepold, n_ks_tuple, + ks_tuple, &new_keys, &n_keys); + krb5_free_principal(context->context, princ); + krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); diff --git a/lib/hdb/keys.c b/lib/hdb/keys.c index f36ec8c41..94e4f487a 100644 --- a/lib/hdb/keys.c +++ b/lib/hdb/keys.c @@ -33,6 +33,7 @@ */ #include "hdb_locl.h" +#include /* * free all the memory used by (len, keys) @@ -328,6 +329,50 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset, } +static +krb5_error_code +ks_tuple2str(krb5_context context, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, char ***ks_tuple_strs) +{ + int i; + char **ksnames; + char *ename, *sname; + krb5_error_code rc = KRB5_PROG_ETYPE_NOSUPP; + + *ks_tuple_strs = NULL; + if (n_ks_tuple < 1) + return 0; + + if ((ksnames = calloc(n_ks_tuple, sizeof (*ksnames))) == NULL) + return (errno); + + for (i = 0; i < n_ks_tuple; i++) { + if (krb5_enctype_to_string(context, ks_tuple[i].ks_enctype, &ename)) + goto out; + if (krb5_salttype_to_string(context, ks_tuple[i].ks_enctype, + ks_tuple[i].ks_salttype, &sname)) + goto out; + + if (asprintf(&ksnames[i], "%s:%s", ename, sname) == -1) { + rc = errno; + free(ename); + free(sname); + goto out; + } + free(ename); + free(sname); + } + + *ks_tuple_strs = ksnames; + rc = 0; + +out: + for (i = 0; i < n_ks_tuple; i++) + free(ksnames[i]); + free(ksnames); + return (rc); +} + /* * Generate the `key_set' from the [kadmin]default_keys statement. If * `no_salt' is set, salt is not important (and will not be set) since @@ -336,12 +381,14 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset, krb5_error_code hdb_generate_key_set(krb5_context context, krb5_principal principal, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, Key **ret_key_set, size_t *nkeyset, int no_salt) { char **ktypes, **kp; krb5_error_code ret; Key *k, *key_set; size_t i, j; + char **ks_tuple_strs; static const char *default_keytypes[] = { "aes256-cts-hmac-sha1-96:pw-salt", "des3-cbc-sha1:pw-salt", @@ -349,16 +396,18 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal, NULL }; - ktypes = krb5_config_get_strings(context, NULL, "kadmin", - "default_keys", NULL); + if ((ret = ks_tuple2str(context, n_ks_tuple, ks_tuple, &ks_tuple_strs))) + return ret; + + if (ks_tuple_strs == NULL) + ktypes = krb5_config_get_strings(context, NULL, "kadmin", + "default_keys", NULL); if (ktypes == NULL) ktypes = (char **)(intptr_t)default_keytypes; *ret_key_set = key_set = NULL; *nkeyset = 0; - ret = 0; - for(kp = ktypes; kp && *kp; kp++) { const char *p; krb5_salt salt; @@ -451,7 +500,7 @@ hdb_generate_key_set_password(krb5_context context, krb5_error_code ret; size_t i; - ret = hdb_generate_key_set(context, principal, + ret = hdb_generate_key_set(context, principal, 0, NULL, keys, num_keys, 0); if (ret) return ret; diff --git a/lib/kadm5/ad.c b/lib/kadm5/ad.c index 4ea5cdb08..4b54a36bd 100644 --- a/lib/kadm5/ad.c +++ b/lib/kadm5/ad.c @@ -1224,9 +1224,13 @@ kadm5_ad_modify_principal(void *server_handle, #endif } +/*ARGSUSED*/ static kadm5_ret_t kadm5_ad_randkey_principal(void *server_handle, krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, krb5_keyblock **keys, int *n_keys) { diff --git a/lib/kadm5/admin.h b/lib/kadm5/admin.h index e3e6755c3..bc38c27e7 100644 --- a/lib/kadm5/admin.h +++ b/lib/kadm5/admin.h @@ -195,10 +195,6 @@ typedef struct _kadm5_policy_ent_t { #define KADM5_PRIV_CPW (1 << 5) #define KADM5_PRIV_ALL (KADM5_PRIV_GET | KADM5_PRIV_ADD | KADM5_PRIV_MODIFY | KADM5_PRIV_DELETE | KADM5_PRIV_LIST | KADM5_PRIV_CPW) -typedef struct { - int XXX; -}krb5_key_salt_tuple; - typedef struct _kadm5_config_params { uint32_t mask; diff --git a/lib/kadm5/common_glue.c b/lib/kadm5/common_glue.c index 595792233..87381a9ea 100644 --- a/lib/kadm5/common_glue.c +++ b/lib/kadm5/common_glue.c @@ -92,6 +92,16 @@ kadm5_get_principal(void *server_handle, return __CALL(get_principal, (server_handle, princ, out, mask)); } +kadm5_ret_t +kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, + int32_t ktype, int32_t stype, + int32_t kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop) +{ + +} + kadm5_ret_t kadm5_modify_principal(void *server_handle, kadm5_principal_ent_t princ, @@ -106,7 +116,21 @@ kadm5_randkey_principal(void *server_handle, krb5_keyblock **new_keys, int *n_keys) { - return __CALL(randkey_principal, (server_handle, princ, new_keys, n_keys)); + return __CALL(randkey_principal, (server_handle, princ, FALSE, 0, NULL, + new_keys, n_keys)); +} + +kadm5_ret_t +kadm5_randkey_principal_3(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock **new_keys, + int *n_keys) +{ + return __CALL(randkey_principal, (server_handle, princ, keepold, + n_ks_tuple, ks_tuple, new_keys, n_keys)); } kadm5_ret_t diff --git a/lib/kadm5/default_keys.c b/lib/kadm5/default_keys.c index 6719e3846..ff643bc11 100644 --- a/lib/kadm5/default_keys.c +++ b/lib/kadm5/default_keys.c @@ -85,7 +85,8 @@ parse_file(krb5_context context, krb5_principal principal, int no_salt) size_t nkeys; Key *keys; - ret = hdb_generate_key_set(context, principal, &keys, &nkeys, no_salt); + ret = hdb_generate_key_set(context, principal, 0, NULL, &keys, &nkeys, + no_salt); if (ret) krb5_err(context, 1, ret, "hdb_generate_key_set"); diff --git a/lib/kadm5/private.h b/lib/kadm5/private.h index 7c5b27f17..171d99d89 100644 --- a/lib/kadm5/private.h +++ b/lib/kadm5/private.h @@ -48,8 +48,9 @@ struct kadm_func { kadm5_ret_t (*get_principals) (void*, const char*, char***, int*); kadm5_ret_t (*get_privs) (void*, uint32_t*); kadm5_ret_t (*modify_principal) (void*, kadm5_principal_ent_t, uint32_t); - kadm5_ret_t (*randkey_principal) (void*, krb5_principal, - krb5_keyblock**, int*); + kadm5_ret_t (*randkey_principal) (void*, krb5_principal, krb5_boolean, int, + krb5_key_salt_tuple*, krb5_keyblock**, + int*); kadm5_ret_t (*rename_principal) (void*, krb5_principal, krb5_principal); kadm5_ret_t (*chpass_principal_with_key) (void *, krb5_principal, int, krb5_key_data *); diff --git a/lib/kadm5/randkey_c.c b/lib/kadm5/randkey_c.c index bfa12084f..4916cad64 100644 --- a/lib/kadm5/randkey_c.c +++ b/lib/kadm5/randkey_c.c @@ -38,14 +38,18 @@ RCSID("$Id$"); kadm5_ret_t kadm5_c_randkey_principal(void *server_handle, krb5_principal princ, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, krb5_keyblock **new_keys, int *n_keys) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; - unsigned char buf[1024]; + unsigned char buf[1536]; int32_t tmp; + int i; krb5_data reply; ret = _kadm5_connect(server_handle); @@ -57,12 +61,41 @@ kadm5_c_randkey_principal(void *server_handle, krb5_clear_error_message(context->context); return ENOMEM; } + + /* + * NOTE WELL: This message is extensible. It currently consists of: + * + * - opcode (kadm_randkey) + * - principal name (princ) + * + * followed by optional items, each of which must be present if + * there are any items following them that are also present: + * + * - keepold boolean (whether to delete old kvnos) + * - number of key/salt type tuples + * - array of {enctype, salttype} + * + * Eventually we may add: + * + * - opaque string2key parameters (salt, rounds, ...) + */ krb5_store_int32(sp, kadm_randkey); krb5_store_principal(sp, princ); ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; + + if (keepold == TRUE || n_ks_tuple > 0) + krb5_store_uint32(sp, keepold); + if (n_ks_tuple > 0) + krb5_store_uint32(sp, n_ks_tuple); + for (i = 0; i < n_ks_tuple; i++) { + krb5_store_int32(sp, ks_tuple[i].ks_enctype); + krb5_store_int32(sp, ks_tuple[i].ks_salttype); + } + + /* Future extensions go here */ ret = _kadm5_client_recv(context, &reply); if(ret) return ret; diff --git a/lib/kadm5/randkey_s.c b/lib/kadm5/randkey_s.c index adb3564be..4c546b05c 100644 --- a/lib/kadm5/randkey_s.c +++ b/lib/kadm5/randkey_s.c @@ -43,6 +43,9 @@ RCSID("$Id$"); kadm5_ret_t kadm5_s_randkey_principal(void *server_handle, krb5_principal princ, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, krb5_keyblock **new_keys, int *n_keys) { @@ -65,6 +68,8 @@ kadm5_s_randkey_principal(void *server_handle, ret = _kadm5_set_keys_randomly (context, &ent.entry, + n_ks_tuple, + ks_tuple, new_keys, n_keys); if (ret) diff --git a/lib/kadm5/set_keys.c b/lib/kadm5/set_keys.c index ea0b816c1..86bca8a29 100644 --- a/lib/kadm5/set_keys.c +++ b/lib/kadm5/set_keys.c @@ -196,6 +196,8 @@ is_des_key_p(int keytype) kadm5_ret_t _kadm5_set_keys_randomly (kadm5_server_context *context, hdb_entry *ent, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, krb5_keyblock **new_keys, int *n_keys) { @@ -206,7 +208,7 @@ _kadm5_set_keys_randomly (kadm5_server_context *context, Key *keys; ret = hdb_generate_key_set(context->context, ent->principal, - &keys, &num_keys, 1); + n_ks_tuple, ks_tuple, &keys, &num_keys, 1); if (ret) return ret; diff --git a/lib/kadm5/version-script.map b/lib/kadm5/version-script.map index 90bd6fee1..ec60eb89e 100644 --- a/lib/kadm5/version-script.map +++ b/lib/kadm5/version-script.map @@ -26,6 +26,7 @@ HEIMDAL_KAMD5_SERVER_1.0 { kadm5_init_with_skey_ctx; kadm5_modify_principal; kadm5_randkey_principal; + kadm5_randkey_principal_3; kadm5_rename_principal; kadm5_ret_key_data; kadm5_ret_principal_ent; diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index 2224b92e9..31f8a7c2f 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -876,6 +876,11 @@ typedef struct { typedef krb5_error_code (KRB5_CALLCONV * krb5_gic_process_last_req)(krb5_context, krb5_last_req_entry **, void *); +typedef struct { + krb5_enctype ks_enctype; + krb5int32 ks_salttype; +}krb5_key_salt_tuple; + /* * */