aboutsummaryrefslogtreecommitdiff
path: root/lib/kadm5/modify_s.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kadm5/modify_s.c')
-rw-r--r--lib/kadm5/modify_s.c91
1 files changed, 82 insertions, 9 deletions
diff --git a/lib/kadm5/modify_s.c b/lib/kadm5/modify_s.c
index 78f26734f0f7..2159caf5517c 100644
--- a/lib/kadm5/modify_s.c
+++ b/lib/kadm5/modify_s.c
@@ -35,6 +35,61 @@
RCSID("$Id$");
+struct modify_principal_hook_ctx {
+ kadm5_server_context *context;
+ enum kadm5_hook_stage stage;
+ krb5_error_code code;
+ kadm5_principal_ent_t princ;
+ uint32_t mask;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+modify_principal_hook_cb(krb5_context context,
+ const void *hook,
+ void *hookctx,
+ void *userctx)
+{
+ krb5_error_code ret;
+ const struct kadm5_hook_ftable *ftable = hook;
+ struct modify_principal_hook_ctx *ctx = userctx;
+
+ ret = ftable->modify(context, hookctx, ctx->stage,
+ ctx->code, ctx->princ, ctx->mask);
+ if (ret != 0 && ret != KRB5_PLUGIN_NO_HANDLE)
+ _kadm5_s_set_hook_error_message(ctx->context, ret, "modify",
+ 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
+modify_principal_hook(kadm5_server_context *context,
+ enum kadm5_hook_stage stage,
+ krb5_error_code code,
+ kadm5_principal_ent_t princ,
+ uint32_t mask)
+{
+ krb5_error_code ret;
+ struct modify_principal_hook_ctx ctx;
+
+ ctx.context = context;
+ ctx.stage = stage;
+ ctx.code = code;
+ ctx.princ = princ;
+ ctx.mask = mask;
+
+ ret = _krb5_plugin_run_f(context->context, &kadm5_hook_plugin_data,
+ 0, &ctx, modify_principal_hook_cb);
+ if (ret == KRB5_PLUGIN_NO_HANDLE)
+ ret = 0;
+
+ return ret;
+}
+
static kadm5_ret_t
modify_principal(void *server_handle,
kadm5_principal_ent_t princ,
@@ -42,14 +97,14 @@ modify_principal(void *server_handle,
uint32_t forbidden_mask)
{
kadm5_server_context *context = server_handle;
- hdb_entry_ex ent;
+ hdb_entry ent;
kadm5_ret_t ret;
memset(&ent, 0, sizeof(ent));
if((mask & forbidden_mask))
return KADM5_BAD_MASK;
- if((mask & KADM5_POLICY) && strcmp(princ->policy, "default"))
+ if((mask & KADM5_POLICY) && strcmp(princ->policy, "default") != 0)
return KADM5_UNK_POLICY;
if (!context->keep_open) {
@@ -62,14 +117,29 @@ modify_principal(void *server_handle,
if (ret)
goto out;
+ /*
+ * NOTE: We do not use hdb_fetch_kvno() here, which means we'll
+ * automatically reject modifications of would-be virtual principals.
+ */
ret = context->db->hdb_fetch_kvno(context->context, context->db,
- princ->principal, HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
+ princ->principal,
+ HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA,
+ 0, &ent);
if (ret)
goto out2;
+
+ ret = modify_principal_hook(context, KADM5_HOOK_STAGE_PRECOMMIT,
+ 0, princ, mask);
+ if (ret)
+ goto out3;
+ /*
+ * XXX Make sure that _kadm5_setup_entry() checks that the time of last
+ * change in `ent' matches the one in `princ'.
+ */
ret = _kadm5_setup_entry(context, &ent, mask, princ, mask, NULL, 0);
if (ret)
goto out3;
- ret = _kadm5_set_modifier(context, &ent.entry);
+ ret = _kadm5_set_modifier(context, &ent);
if (ret)
goto out3;
@@ -87,7 +157,7 @@ modify_principal(void *server_handle,
goto out3;
}
- ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+ ret = hdb_seal_keys(context->context, context->db, &ent);
if (ret)
goto out3;
@@ -100,22 +170,25 @@ modify_principal(void *server_handle,
ext.data.element = choice_HDB_extension_data_policy;
ext.data.u.policy = strdup(princ->policy);
if (ext.data.u.policy == NULL) {
- ret = ENOMEM;
+ ret = krb5_enomem(context->context);
goto out3;
}
/* This calls free_HDB_extension(), freeing ext.data.u.policy */
- ret = hdb_replace_extension(context->context, &ent.entry, &ext);
+ ret = hdb_replace_extension(context->context, &ent, &ext);
free(ext.data.u.policy);
if (ret)
goto out3;
}
/* This logs the change for iprop and writes to the HDB */
- ret = kadm5_log_modify(context, &ent.entry,
+ ret = kadm5_log_modify(context, &ent,
mask | KADM5_MOD_NAME | KADM5_MOD_TIME);
+ (void) modify_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
+ ret, princ, mask);
+
out3:
- hdb_free_entry(context->context, &ent);
+ hdb_free_entry(context->context, context->db, &ent);
out2:
(void) kadm5_log_end(context);
out: