TODO: s4:dsdb/descriptor: inherit nTSecurityDescriptor changes to children AND ON...
authorStefan Metzmacher <metze@samba.org>
Fri, 16 Nov 2012 11:49:16 +0000 (12:49 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 19 Nov 2012 11:02:07 +0000 (12:02 +0100)
source4/dsdb/samdb/ldb_modules/descriptor.c

index 0a262885d8c4030ef2eba8a0286eceded8f10444..f27bc505edb96640d885caa60c95b44d579a7759 100644 (file)
@@ -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, &current_res, dn,
+       ret = dsdb_module_search_dn(module, state, &current_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)