Revert "debug"
[metze/samba/wip.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
index 9763c8ee493afc73cf99a0c65578f51154405918..e6668bfee6d0cc96f1d1e278030f76e1455a146b 100644 (file)
@@ -39,7 +39,6 @@
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "libcli/security/security.h"
-#include "dsdb/samdb/ldb_modules/schema.h"
 #include "auth/auth.h"
 #include "param/param.h"
 #include "dsdb/samdb/ldb_modules/util.h"
@@ -467,6 +466,8 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
        DATA_BLOB *sd;
        const struct dsdb_class *objectclass;
        static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
+       uint32_t instanceType;
+       bool isNC = false;
 
        ldb = ldb_module_get_ctx(module);
        dn = req->op.add.message->dn;
@@ -484,22 +485,39 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
                return ldb_next_request(module, req);
        }
 
-       /* if the object has a parent, retrieve its SD to
-        * use for calculation. Unfortunately we do not yet have
-        * instanceType, so we use dsdb_find_nc_root. */
-       parent_dn = ldb_dn_get_parent(req, dn);
-       if (parent_dn == NULL) {
-               return ldb_oom(ldb);
+       instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
+
+       if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
+               isNC = true;
        }
 
-       ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
-       if (ret != LDB_SUCCESS) {
-               ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
-                         ldb_dn_get_linearized(dn));
-               return ret;
+       if (!isNC) {
+               ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
+               if (ret != LDB_SUCCESS) {
+                       ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
+                               ldb_dn_get_linearized(dn));
+                       return ret;
+               }
+
+               if (ldb_dn_compare(dn, nc_root) == 0) {
+                       DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
+                       isNC = true;
+               }
+       }
+
+       if (isNC) {
+               DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
        }
+       if (!isNC) {
+               /* if the object has a parent, retrieve its SD to
+                * use for calculation. Unfortunately we do not yet have
+                * instanceType, so we use dsdb_find_nc_root. */
+
+               parent_dn = ldb_dn_get_parent(req, dn);
+               if (parent_dn == NULL) {
+                       return ldb_oom(ldb);
+               }
 
-       if (ldb_dn_compare(dn, nc_root) != 0) {
                /* we aren't any NC */
                ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
                                            parent_attrs,
@@ -523,7 +541,8 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
                return ldb_operr(ldb);
        }
 
-       objectclass = get_last_structural_class(schema, objectclass_element, req);
+       objectclass = dsdb_get_last_structural_class(schema,
+                                                    objectclass_element);
        if (objectclass == NULL) {
                return ldb_operr(ldb);
        }
@@ -559,10 +578,19 @@ 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 ldb_control *sd_recalculate_control, *sd_flags_control;
+       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;
        struct ldb_result *current_res, *parent_res;
@@ -572,7 +600,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
        struct ldb_dn *parent_dn, *dn;
        struct ldb_message_element *objectclass_element;
        int ret;
-       uint32_t instanceType, sd_flags = 0;
+       uint32_t instanceType, sd_flags = 0, flags;
        const struct dsdb_schema *schema;
        DATA_BLOB *sd;
        const struct dsdb_class *objectclass;
@@ -580,11 +608,20 @@ 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
         * no modification is performed. */
+       show_deleted_control = ldb_request_get_control(req,
+                                            LDB_CONTROL_SHOW_DELETED_OID);
        sd_recalculate_control = ldb_request_get_control(req,
                                             LDB_CONTROL_RECALCULATE_SD_OID);
        if (!user_sd && !sd_recalculate_control) {
@@ -597,10 +634,13 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
        if (ldb_dn_is_special(dn)) {
                return ldb_next_request(module, req);
        }
-
-       ret = dsdb_module_search_dn(module, req, &current_res, dn,
+       flags = DSDB_FLAG_NEXT_MODULE;
+       if (show_deleted_control) {
+               flags |= DSDB_SEARCH_SHOW_DELETED;
+       }
+       ret = dsdb_module_search_dn(module, state, &current_res, dn,
                                    current_attrs,
-                                   DSDB_FLAG_NEXT_MODULE,
+                                   flags,
                                    req);
        if (ret != LDB_SUCCESS) {
                ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
@@ -618,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);
@@ -641,7 +682,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
                return ldb_operr(ldb);
        }
 
-       objectclass = get_last_structural_class(schema, objectclass_element, req);
+       objectclass = dsdb_get_last_structural_class(schema,
+                                                    objectclass_element);
        if (objectclass == NULL) {
                return ldb_operr(ldb);
        }
@@ -656,17 +698,27 @@ 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,
+       if ((sd_recalculate_control != NULL) &&
+           (sd_recalculate_control->data != NULL))
+       {
+               if (user_sd != NULL) {
+                       return ldb_error(ldb, ret,
+                                "descriptor_modify: RECALCULATE_SD with given value rejected");
+               }
+
+               sd_flags = 0x0000000F;
+               old_sd = NULL;
+               user_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
+       }
+
+       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) {
-                       sd_element = ldb_msg_find_element(msg,
-                                                         "nTSecurityDescriptor");
-                       sd_element->values[0] = *sd;
-               } else if (sd_recalculate_control != NULL) {
+
+               if (sd_recalculate_control != NULL) {
                        /* In this branch we really do force the recalculation
                         * of the SD */
                        ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
@@ -681,6 +733,10 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
                        sd_element = ldb_msg_find_element(msg,
                                                          "nTSecurityDescriptor");
                        sd_element->flags = LDB_FLAG_MOD_REPLACE;
+               } else if (user_sd != NULL) {
+                       sd_element = ldb_msg_find_element(msg,
+                                                         "nTSecurityDescriptor");
+                       sd_element->values[0] = *sd;
                }
        }
 
@@ -692,11 +748,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) {
@@ -706,6 +762,132 @@ 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);
+               }
+
+               ldb_req_mark_trusted(sub_req);
+
+               ret = ldb_request_add_control(sub_req,
+                                             LDB_CONTROL_RECALCULATE_SD_OID,
+                                             true, 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_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;
@@ -744,18 +926,164 @@ 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);
+       }
+
+       ldb_req_mark_trusted(mod_req);
+
+       ret = ldb_request_add_control(mod_req,
+                                     LDB_CONTROL_RECALCULATE_SD_OID,
+                                     true, 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_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)