From 43b33eccf9c294789cc6f7a8b67581d732b9b2d6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Nov 2012 12:49:16 +0100 Subject: [PATCH 1/1] TODO: s4:dsdb/descriptor: inherit nTSecurityDescriptor changes to children AND ON RENAME --- source4/dsdb/samdb/ldb_modules/descriptor.c | 309 +++++++++++++++++++- 1 file changed, 297 insertions(+), 12 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 0a262885d8c4..f27bc505edb9 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -578,9 +578,18 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, add_req); } +struct descriptor_modify_state { + struct ldb_module *module; + struct ldb_request *req; +}; + +static int descriptor_modify_callback(struct ldb_request *mod_req, + struct ldb_reply *ares); + static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) { - struct ldb_context *ldb; + struct descriptor_modify_state *state = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_control *sd_recalculate_control, *sd_flags_control, *show_deleted_control; struct ldb_request *mod_req; struct ldb_message *msg; @@ -599,7 +608,14 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) static const char * const current_attrs[] = { "nTSecurityDescriptor", "instanceType", "objectClass", NULL }; - ldb = ldb_module_get_ctx(module); + + state = talloc_zero(req, struct descriptor_modify_state); + if (state == NULL) { + return ldb_oom(ldb); + } + state->module = module; + state->req = req; + dn = req->op.mod.message->dn; user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); /* This control forces the recalculation of the SD also when @@ -622,7 +638,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (show_deleted_control) { flags |= DSDB_SEARCH_SHOW_DELETED; } - ret = dsdb_module_search_dn(module, req, ¤t_res, dn, + ret = dsdb_module_search_dn(module, state, ¤t_res, dn, current_attrs, flags, req); @@ -642,7 +658,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (parent_dn == NULL) { return ldb_oom(ldb); } - ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn, + ret = dsdb_module_search_dn(module, state, &parent_res, + parent_dn, parent_attrs, DSDB_FLAG_NEXT_MODULE, req); @@ -681,10 +698,10 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor"); } - sd = get_new_descriptor(module, dn, req, + sd = get_new_descriptor(module, dn, state, objectclass, parent_sd, user_sd, old_sd, sd_flags); - msg = ldb_msg_copy_shallow(req, req->op.mod.message); + msg = ldb_msg_copy_shallow(state, req->op.mod.message); if (sd != NULL) { struct ldb_message_element *sd_element; if (user_sd != NULL) { @@ -717,11 +734,11 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) sd_recalculate_control->critical = 0; } - ret = ldb_build_mod_req(&mod_req, ldb, req, + ret = ldb_build_mod_req(&mod_req, ldb, state, msg, req->controls, - req, - dsdb_next_callback, + state, + descriptor_modify_callback, req); LDB_REQ_SET_LOCATION(mod_req); if (ret != LDB_SUCCESS) { @@ -731,6 +748,130 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, mod_req); } +/* + used to chain to the callers callback + */ +static int descriptor_modify_callback(struct ldb_request *mod_req, + struct ldb_reply *ares) +{ + struct descriptor_modify_state *state = + talloc_get_type_abort(mod_req->context, + struct descriptor_modify_state); + struct ldb_module *module = state->module; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_request *req = state->req; + struct ldb_result *res = NULL; + const char * const no_attrs[] = { NULL }; + unsigned int i; + int ret; + + if (!ares) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = dsdb_module_search(module, ares, &res, + req->op.mod.message->dn, + LDB_SCOPE_ONELEVEL, no_attrs, + DSDB_FLAG_NEXT_MODULE | + DSDB_FLAG_AS_SYSTEM | + DSDB_SEARCH_SHOW_RECYCLED | + DSDB_SEARCH_SHOW_DELETED, + req, "(objectClass=*)"); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, ret); + } + + for (i=0; i < res->count; i++) { + struct ldb_request *sub_req; + struct ldb_result *mod_res; + + mod_res = talloc_zero(res, struct ldb_result); + if (!mod_res) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_build_mod_req(&sub_req, ldb, req, + res->msgs[i], + NULL, + mod_res, + ldb_modify_default_callback, + req); + LDB_REQ_SET_LOCATION(sub_req); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_request_add_control(sub_req, + LDB_CONTROL_RECALCULATE_SD_OID, + true, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + ret = ldb_request_add_control(sub_req, + LDB_CONTROL_AS_SYSTEM_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_request_add_control(sub_req, + LDB_CONTROL_SHOW_DELETED_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + ret = ldb_request_add_control(sub_req, + LDB_CONTROL_SHOW_RECYCLED_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = descriptor_modify(module, sub_req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL); + } + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + talloc_free(mod_res); + } + + return ldb_module_done(req, ares->controls, + ares->response, ares->error); +} + static int descriptor_search(struct ldb_module *module, struct ldb_request *req) { int ret; @@ -769,18 +910,162 @@ static int descriptor_search(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(ac->module, down_req); } -/* TODO */ + +struct descriptor_rename_state { + struct ldb_module *module; + struct ldb_request *req; +}; + +static int descriptor_rename_callback(struct ldb_request *req, + struct ldb_reply *reply); + static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); - ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)); + struct descriptor_rename_state *state; + int ret; + struct ldb_request *rename_req = NULL; + + ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", + ldb_dn_get_linearized(req->op.rename.olddn)); /* do not manipulate our control entries */ if (ldb_dn_is_special(req->op.rename.olddn)) { return ldb_next_request(module, req); } - return ldb_next_request(module, req); + state = talloc_zero(req, struct descriptor_rename_state); + if (state == NULL) { + return ldb_oom(ldb); + } + state->module = module; + state->req = req; + + ret = ldb_build_rename_req(&rename_req, ldb, state, + req->op.rename.olddn, + req->op.rename.newdn, + req->controls, + state, + descriptor_rename_callback, + req); + LDB_REQ_SET_LOCATION(rename_req); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(module, rename_req); +} + +static int descriptor_rename_callback(struct ldb_request *rename_req, + struct ldb_reply *ares) +{ + struct descriptor_rename_state *state = + talloc_get_type_abort(rename_req->context, + struct descriptor_rename_state); + struct ldb_module *module = state->module; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_request *req = state->req; + struct ldb_message *msg; + struct ldb_request *mod_req; + int ret; + struct ldb_result *mod_res; + + if (!ares) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + msg = ldb_msg_new(ares); + if (msg == NULL) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + msg->dn = req->op.rename.newdn; + + mod_res = talloc_zero(msg, struct ldb_result); + if (mod_res == NULL) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_build_mod_req(&mod_req, ldb, msg, + msg, + NULL, + mod_res, + ldb_modify_default_callback, + req); + LDB_REQ_SET_LOCATION(mod_req); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_request_add_control(mod_req, + LDB_CONTROL_RECALCULATE_SD_OID, + true, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + ret = ldb_request_add_control(mod_req, + LDB_CONTROL_AS_SYSTEM_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_request_add_control(mod_req, + LDB_CONTROL_SHOW_DELETED_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + ret = ldb_request_add_control(mod_req, + LDB_CONTROL_SHOW_RECYCLED_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ret = descriptor_modify(module, mod_req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL); + } + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + talloc_free(msg); + + return ldb_module_done(req, ares->controls, + ares->response, ares->error); } static int descriptor_init(struct ldb_module *module) -- 2.34.1