summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/descriptor.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c
index dfbfdf6dec..51371798db 100644
--- a/source4/dsdb/samdb/ldb_modules/descriptor.c
+++ b/source4/dsdb/samdb/ldb_modules/descriptor.c
@@ -763,6 +763,113 @@ static int descriptor_do_add(struct descriptor_context *ac)
}
}
+static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ struct ldb_request *add_req;
+ struct ldb_message *msg;
+ struct ldb_result *parent_res;
+ const struct ldb_val *parent_sd = NULL;
+ const struct ldb_val *user_sd;
+ struct ldb_dn *parent_dn, *dn, *nc_root;
+ struct ldb_message_element *objectclass_element, *sd_element;
+ int ret;
+ const struct dsdb_schema *schema;
+ DATA_BLOB *sd;
+ const struct dsdb_class *objectclass;
+ static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
+
+ ldb = ldb_module_get_ctx(module);
+ dn = req->op.add.message->dn;
+ user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
+ sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
+ /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
+ if (user_sd == NULL && sd_element) {
+ return ldb_next_request(module, req);
+ }
+
+ ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(dn)) {
+ 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*/
+ parent_dn = ldb_dn_get_parent(req, dn);
+ if (parent_dn == NULL) {
+ return ldb_oom(ldb);
+ }
+
+ 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) {
+ /* we aren't any NC */
+ ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
+ parent_attrs,
+ DSDB_FLAG_NEXT_MODULE,
+ req);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
+ ldb_dn_get_linearized(parent_dn));
+ return ret;
+ }
+ if (parent_res->count != 1) {
+ return ldb_operr(ldb);
+ }
+ parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
+ }
+
+ schema = dsdb_get_schema(ldb, req);
+
+ objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
+ if (objectclass_element == NULL) {
+ return ldb_operr(ldb);
+ }
+
+ objectclass = get_last_structural_class(schema, objectclass_element, req);
+ if (objectclass == NULL) {
+ return ldb_operr(ldb);
+ }
+
+ sd = get_new_descriptor(module, dn, req,
+ objectclass, parent_sd,
+ user_sd, NULL, 0);
+ msg = ldb_msg_copy_shallow(req, req->op.add.message);
+ if (sd != NULL) {
+ if (sd_element != NULL) {
+ sd_element->values[0] = *sd;
+ } else {
+ ret = ldb_msg_add_steal_value(msg,
+ "nTSecurityDescriptor",
+ sd);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+ }
+
+ ret = ldb_build_add_req(&add_req, ldb, req,
+ msg,
+ req->controls,
+ req, dsdb_next_callback,
+ req);
+ LDB_REQ_SET_LOCATION(add_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_error(ldb, ret,
+ "descriptor_add: Error creating new add request.");
+ }
+
+ return ldb_next_request(module, add_req);
+}
+
static int descriptor_change(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
@@ -903,7 +1010,7 @@ static int descriptor_init(struct ldb_module *module)
static const struct ldb_module_ops ldb_descriptor_module_ops = {
.name = "descriptor",
.search = descriptor_search,
- .add = descriptor_change,
+ .add = descriptor_add,
.modify = descriptor_change,
.rename = descriptor_rename,
.init_context = descriptor_init