From 57c25d9828b8960eda8fcdec4417009d799423e7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 10 Jan 2019 15:18:10 +1100 Subject: [PATCH] kadm5: add chpass_with_key hook (#397) Add a hook for changing a password with a key. This hook should be consolidated into one shared with randkey and setkey, but for now I have continued to have the hooks follow the kadm5 APIs themselves in both signature and quantity. (This means the randkey one isn't actually very useful because it doesn't provide the hook with the keys.) --- lib/kadm5/chpass_s.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/kadm5/kadm5-hook.h | 9 ++++++ lib/kadm5/sample_hook.c | 15 ++++++++++ 3 files changed, 100 insertions(+) diff --git a/lib/kadm5/chpass_s.c b/lib/kadm5/chpass_s.c index d2bf5794e..8277886f5 100644 --- a/lib/kadm5/chpass_s.c +++ b/lib/kadm5/chpass_s.c @@ -292,6 +292,68 @@ kadm5_s_chpass_principal(void *server_handle, n_ks_tuple, ks_tuple, password, 0); } +struct chpass_principal_with_key_hook_ctx { + kadm5_server_context *context; + enum kadm5_hook_stage stage; + krb5_error_code code; + krb5_const_principal princ; + uint32_t flags; + size_t n_key_data; + krb5_key_data *key_data; +}; + +static krb5_error_code +chpass_principal_with_key_hook_cb(krb5_context context, + const void *hook, + void *hookctx, + void *userctx) +{ + krb5_error_code ret; + const struct kadm5_hook_ftable *ftable = hook; + struct chpass_principal_with_key_hook_ctx *ctx = userctx; + + ret = ftable->chpass_with_key(context, hookctx, + ctx->stage, ctx->code, ctx->princ, + ctx->flags, ctx->n_key_data, ctx->key_data); + if (ret != 0 && ret != KRB5_PLUGIN_NO_HANDLE) + _kadm5_s_set_hook_error_message(ctx->context, ret, "chpass_with_key", + hook, ctx->stage); + + /* only pre-commit plugins can abort */ + if (ret == 0 || ctx->stage == KADM5_HOOK_STAGE_POSTCOMMIT) + ret = KRB5_PLUGIN_NO_HANDLE; + + return ret; +} + +static kadm5_ret_t +chpass_principal_with_key_hook(kadm5_server_context *context, + enum kadm5_hook_stage stage, + krb5_error_code code, + krb5_const_principal princ, + uint32_t flags, + size_t n_key_data, + krb5_key_data *key_data) +{ + krb5_error_code ret; + struct chpass_principal_with_key_hook_ctx ctx; + + ctx.context = context; + ctx.stage = stage; + ctx.code = code; + ctx.princ = princ; + ctx.flags = flags; + ctx.n_key_data = n_key_data; + ctx.key_data = key_data; + + ret = _krb5_plugin_run_f(context->context, &kadm5_hook_plugin_data, + 0, &ctx, chpass_principal_with_key_hook_cb); + if (ret == KRB5_PLUGIN_NO_HANDLE) + ret = 0; + + return ret; +} + /* * change keys for `princ' to `keys' */ @@ -306,6 +368,7 @@ kadm5_s_chpass_principal_with_key(void *server_handle, kadm5_server_context *context = server_handle; hdb_entry_ex ent; kadm5_ret_t ret; + uint32_t hook_flags = 0; memset(&ent, 0, sizeof(ent)); if (!context->keep_open) { @@ -322,6 +385,15 @@ kadm5_s_chpass_principal_with_key(void *server_handle, HDB_F_GET_ANY|HDB_F_ADMIN_DATA, &ent); if (ret == HDB_ERR_NOENTRY) goto out2; + + if (keepold) + hook_flags |= KADM5_HOOK_FLAG_KEEPOLD; + ret = chpass_principal_with_key_hook(context, KADM5_HOOK_STAGE_PRECOMMIT, + 0, princ, hook_flags, + n_key_data, key_data); + if (ret) + goto out3; + if (keepold) { ret = hdb_add_current_keys_to_history(context->context, &ent.entry); if (ret) @@ -359,6 +431,10 @@ kadm5_s_chpass_principal_with_key(void *server_handle, KADM5_MOD_TIME | KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION | KADM5_TL_DATA); + (void) chpass_principal_with_key_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, + ret, princ, hook_flags, + n_key_data, key_data); + out3: hdb_free_entry(context->context, &ent); out2: diff --git a/lib/kadm5/kadm5-hook.h b/lib/kadm5/kadm5-hook.h index 2c767f109..78236a5ed 100644 --- a/lib/kadm5/kadm5-hook.h +++ b/lib/kadm5/kadm5-hook.h @@ -75,6 +75,15 @@ typedef struct kadm5_hook_ftable { krb5_key_salt_tuple *ks_tuple, const char *password); + krb5_error_code (KRB5_CALLCONV *chpass_with_key)(krb5_context context, + void *data, + enum kadm5_hook_stage stage, + krb5_error_code code, + krb5_const_principal princ, + uint32_t flags, + size_t n_key_data, + krb5_key_data *key_data); + krb5_error_code (KRB5_CALLCONV *create)(krb5_context context, void *data, enum kadm5_hook_stage stage, diff --git a/lib/kadm5/sample_hook.c b/lib/kadm5/sample_hook.c index 82d3f68b4..763258bb1 100644 --- a/lib/kadm5/sample_hook.c +++ b/lib/kadm5/sample_hook.c @@ -122,6 +122,19 @@ sample_chpass_hook(krb5_context context, } static krb5_error_code KRB5_CALLCONV +sample_chpass_with_key_hook(krb5_context context, + void *data, + enum kadm5_hook_stage stage, + krb5_error_code code, + krb5_const_principal princ, + uint32_t flags, + size_t n_key_data, + krb5_key_data *key_data) +{ + return sample_log(context, data, stage, "chpass_with_key", code, princ); +} + +static krb5_error_code KRB5_CALLCONV sample_create_hook(krb5_context context, void *data, enum kadm5_hook_stage stage, @@ -209,6 +222,7 @@ static const kadm5_hook_ftable sample_hook_1 = { "sample_hook_1", "Heimdal", sample_chpass_hook, + sample_chpass_with_key_hook, sample_create_hook, sample_modify_hook, sample_delete_hook, @@ -225,6 +239,7 @@ static const kadm5_hook_ftable sample_hook_2 = { "sample_hook_2", "Heimdal", sample_chpass_hook, + sample_chpass_with_key_hook, sample_create_hook, sample_modify_hook, sample_delete_hook, -- 2.11.4.GIT