diff options
Diffstat (limited to 'lib/kadm5/modify_s.c')
| -rw-r--r-- | lib/kadm5/modify_s.c | 91 |
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: |
