From f436f27a5804d0be32a358b1cd18909ab3de7fe7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 14:07:04 +0100 Subject: [PATCH 01/33] s4:dsdb/descriptor: give SYSTEM the correct default owner (group) sid Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit c2c715f9c9e0d465857ad118d632493131a5f9c5) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 12186f2..fd08d49 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -87,6 +87,8 @@ static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); + } else if (security_token_is_system(token)) { + dag_sid = dom_sid_dup(mem_ctx, sa_sid); } else { dag_sid = NULL; } @@ -95,6 +97,8 @@ static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); + } else if (security_token_is_system(token)) { + dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else { dag_sid = NULL; } @@ -103,6 +107,8 @@ static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); + } else if (security_token_is_system(token)) { + dag_sid = dom_sid_dup(mem_ctx, da_sid); } else { dag_sid = NULL; } -- 1.7.9.5 From f330039a5cc9e4e00713c93df45cacbfec10f4d6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 15:53:14 +0100 Subject: [PATCH 02/33] s4:dsdb/descriptor: if the caller specifies no DACL/SACL the objects gets a default one Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 7a3e4d04c7e06379eddacb4f025a3c48a0a754a4) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index fd08d49..73acc2f 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -236,6 +236,11 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module, char *sddl_sd; struct dom_sid *default_owner; struct dom_sid *default_group; + struct security_descriptor *default_descriptor = NULL; + + if (objectclass != NULL) { + default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); + } if (object) { user_descriptor = talloc(mem_ctx, struct security_descriptor); @@ -251,7 +256,7 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module, return NULL; } } else { - user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); + user_descriptor = default_descriptor; } if (old_sd) { @@ -284,6 +289,28 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module, } } + if (user_descriptor && default_descriptor && + (user_descriptor->dacl == NULL)) + { + user_descriptor->dacl = default_descriptor->dacl; + user_descriptor->type |= default_descriptor->type & ( + SEC_DESC_DACL_PRESENT | + SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ | + SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED | + SEC_DESC_DACL_TRUSTED); + } + + if (user_descriptor && default_descriptor && + (user_descriptor->sacl == NULL)) + { + user_descriptor->sacl = default_descriptor->sacl; + user_descriptor->type |= default_descriptor->type & ( + SEC_DESC_SACL_PRESENT | + SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ | + SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED | + SEC_DESC_SERVER_SECURITY); + } + default_owner = get_default_ag(mem_ctx, dn, session_info->security_token, ldb); default_group = get_default_group(mem_ctx, ldb, default_owner); -- 1.7.9.5 From fc3944ce91dc1c7d7d00ee96f9ddd8428663534a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 14:09:34 +0100 Subject: [PATCH 03/33] s4:provision: add get_empty_descriptor() Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 118db4ca11bec17b8f5955f188c07f154b85c87b) --- .../scripting/python/samba/provision/__init__.py | 1 + .../scripting/python/samba/provision/descriptor.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py index 47bc6f9..c3713c9 100644 --- a/source4/scripting/python/samba/provision/__init__.py +++ b/source4/scripting/python/samba/provision/__init__.py @@ -77,6 +77,7 @@ from samba.provision.backend import ( OpenLDAPBackend, ) from samba.provision.descriptor import ( + get_empty_descriptor, get_config_descriptor, get_domain_descriptor ) diff --git a/source4/scripting/python/samba/provision/descriptor.py b/source4/scripting/python/samba/provision/descriptor.py index 69c1be7..3bb2468 100644 --- a/source4/scripting/python/samba/provision/descriptor.py +++ b/source4/scripting/python/samba/provision/descriptor.py @@ -31,6 +31,11 @@ from samba.ndr import ndr_pack # Descriptors of naming contexts and other important objects +def get_empty_descriptor(domain_sid): + sddl= "" + sec = security.descriptor.from_sddl(sddl, domain_sid) + return ndr_pack(sec) + # "get_schema_descriptor" is located in "schema.py" def get_config_descriptor(domain_sid): -- 1.7.9.5 From 3b9a282ba73f213797e826ddcc5167337e6ade14 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 16:22:30 +0100 Subject: [PATCH 04/33] s4:samba_upgradeprovision: use the sd_flags:1:15 control with an empty sd The sd_flags:1:15 control together with an empty security_descriptor has the same effect as the recalculate_sd:0 control (which is samba only). Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 4136d969cab5d4690f00c855bd98dc01253d73d9) --- source4/scripting/bin/samba_upgradeprovision | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source4/scripting/bin/samba_upgradeprovision b/source4/scripting/bin/samba_upgradeprovision index b3fb0b0..7060b73 100755 --- a/source4/scripting/bin/samba_upgradeprovision +++ b/source4/scripting/bin/samba_upgradeprovision @@ -46,11 +46,13 @@ from ldb import (SCOPE_SUBTREE, SCOPE_BASE, from samba import param, dsdb, Ldb from samba.common import confirm from samba.provision import (get_domain_descriptor, find_provision_key_parameters, - get_config_descriptor, + get_config_descriptor, get_empty_descriptor, ProvisioningError, get_last_provision_usn, get_max_usn, update_provision_usn, setup_path) from samba.schema import get_linked_attributes, Schema, get_schema_descriptor from samba.dcerpc import security, drsblobs +from samba.dcerpc.security import ( + SECINFO_OWNER, SECINFO_GROUP, SECINFO_DACL, SECINFO_SACL) from samba.ndr import ndr_unpack from samba.upgradehelpers import (dn_sort, get_paths, newprovision, get_ldbs, findprovisionrange, @@ -1032,7 +1034,8 @@ def update_present(ref_samdb, samdb, basedn, listPresent, usns): raise ProvisioningError(msg) changed = 0 - controls = ["search_options:1:2", "sd_flags:1:0"] + sd_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL + controls = ["search_options:1:2", "sd_flags:1:%d" % sd_flags] if usns is not None: message(CHANGE, "Using replPropertyMetadata for change selection") for dn in listPresent: @@ -1352,16 +1355,20 @@ def rebuild_sd(samdb, names): continue delta = Message() delta.dn = Dn(samdb, key) + sd_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL try: delta["whenCreated"] = MessageElement(hash[key], FLAG_MOD_REPLACE, "whenCreated" ) - samdb.modify(delta, ["recalculate_sd:0","relax:0"]) + descr = get_empty_descriptor(names.domainsid) + delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE, + "nTSecurityDescriptor") + samdb.modify(delta, ["sd_flags:1:%d" % sd_flags,"relax:0"]) except LdbError, e: samdb.transaction_cancel() - res = samdb.search(expression="objectClass=*", base=str(names.rootdn), - scope=SCOPE_SUBTREE, - attrs=["dn", "nTSecurityDescriptor"], - controls=["search_options:1:2"]) + res = samdb.search(expression="objectClass=*", base=str(delta.dn), + scope=SCOPE_BASE, + attrs=["nTSecurityDescriptor"], + controls=["sd_flags:1:%d" % sd_flags]) badsd = ndr_unpack(security.descriptor, str(res[0]["nTSecurityDescriptor"])) message(ERROR, "On %s bad stuff %s" % (str(delta.dn),badsd.as_sddl(names.domainsid))) -- 1.7.9.5 From 87bfbaff09df3080914d8672f9ec564a86fe7731 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 07:18:35 +0100 Subject: [PATCH 05/33] s4:dsdb/descriptor: move special dn check to the start of descriptor_{add,modify,rename} Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 74e3f0ea0aa0352bf15e92c70256fa9b4d291cd9) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 40 ++++++++++++++------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 73acc2f..d6d83fc 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -471,13 +471,14 @@ fail: static int descriptor_add(struct ldb_module *module, struct ldb_request *req) { - struct ldb_context *ldb; + struct ldb_context *ldb = ldb_module_get_ctx(module); 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_dn *dn = req->op.add.message->dn; + struct ldb_dn *parent_dn, *nc_root; struct ldb_message_element *objectclass_element, *sd_element; int ret; const struct dsdb_schema *schema; @@ -488,8 +489,11 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) bool isNC = false; uint32_t sd_flags = dsdb_request_sd_flags(req, NULL); - ldb = ldb_module_get_ctx(module); - dn = req->op.add.message->dn; + /* do not manipulate our control entries */ + if (ldb_dn_is_special(dn)) { + return ldb_next_request(module, req); + } + 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 */ @@ -499,11 +503,6 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *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); - } - instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0); if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) { @@ -607,7 +606,7 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) { - struct ldb_context *ldb; + struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_control *sd_recalculate_control; struct ldb_request *mod_req; struct ldb_message *msg; @@ -615,7 +614,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) const struct ldb_val *old_sd = NULL; const struct ldb_val *parent_sd = NULL; const struct ldb_val *user_sd; - struct ldb_dn *parent_dn, *dn; + struct ldb_dn *dn = req->op.mod.message->dn; + struct ldb_dn *parent_dn; struct ldb_message_element *objectclass_element; int ret; uint32_t instanceType; @@ -627,8 +627,12 @@ 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); - dn = req->op.mod.message->dn; + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(dn)) { + return ldb_next_request(module, req); + } + 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. */ @@ -640,11 +644,6 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %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); - } - ret = dsdb_module_search_dn(module, req, ¤t_res, dn, current_attrs, DSDB_FLAG_NEXT_MODULE | @@ -792,13 +791,16 @@ static int descriptor_search(struct ldb_module *module, struct ldb_request *req) 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 ldb_dn *olddn = 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); } + ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", + ldb_dn_get_linearized(olddn)); + return ldb_next_request(module, req); } -- 1.7.9.5 From e5bd782bc494bcdcb179a735a51e2bcff5bcd604 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 09:15:25 +0100 Subject: [PATCH 06/33] s4:dsdb/descriptor: remove support for unused LDB_CONTROL_RECALCULATE_SD_OID Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit b3486f4e1a2108bd3af7ce760c8410a560c5237d) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index d6d83fc..fb99ab3 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -607,7 +607,6 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); - struct ldb_control *sd_recalculate_control; struct ldb_request *mod_req; struct ldb_message *msg; struct ldb_result *current_res, *parent_res; @@ -634,11 +633,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) } 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. */ - sd_recalculate_control = ldb_request_get_control(req, - LDB_CONTROL_RECALCULATE_SD_OID); - if (!user_sd && !sd_recalculate_control) { + if (!user_sd) { return ldb_next_request(module, req); } @@ -708,29 +703,9 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) sd_element = ldb_msg_find_element(msg, "nTSecurityDescriptor"); sd_element->values[0] = *sd; - } else if (sd_recalculate_control != NULL) { - /* In this branch we really do force the recalculation - * of the SD */ - ldb_msg_remove_attr(msg, "nTSecurityDescriptor"); - - ret = ldb_msg_add_steal_value(msg, - "nTSecurityDescriptor", - sd); - if (ret != LDB_SUCCESS) { - return ldb_error(ldb, ret, - "descriptor_modify: Could not replace SD value in message."); - } - sd_element = ldb_msg_find_element(msg, - "nTSecurityDescriptor"); - sd_element->flags = LDB_FLAG_MOD_REPLACE; } } - /* mark the controls as non-critical since we've handled them */ - if (sd_recalculate_control != NULL) { - sd_recalculate_control->critical = 0; - } - ret = ldb_build_mod_req(&mod_req, ldb, req, msg, req->controls, -- 1.7.9.5 From 58d559260376269fd04f6bbb1cefd99042369857 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 09:19:11 +0100 Subject: [PATCH 07/33] s4:dsdb/descriptor: add some error checks to descriptor_{add,modify} Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 813492676c5b876d309bb2db12c794c513fab5c7) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index fb99ab3..21a559f 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -576,7 +576,13 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) sd = get_new_descriptor(module, dn, req, objectclass, parent_sd, user_sd, NULL, sd_flags); + if (sd == NULL) { + return ldb_operr(ldb); + } msg = ldb_msg_copy_shallow(req, req->op.add.message); + if (msg == NULL) { + return ldb_oom(ldb); + } if (sd != NULL) { if (sd_element != NULL) { sd_element->values[0] = *sd; @@ -696,7 +702,13 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) sd = get_new_descriptor(module, dn, req, objectclass, parent_sd, user_sd, old_sd, sd_flags); + if (sd == NULL) { + return ldb_operr(ldb); + } msg = ldb_msg_copy_shallow(req, req->op.mod.message); + if (msg == NULL) { + return ldb_oom(ldb); + } if (sd != NULL) { struct ldb_message_element *sd_element; if (user_sd != NULL) { -- 1.7.9.5 From b524b4f6e961f0c1f00878ed8d6dfe37f45b0517 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 09:20:50 +0100 Subject: [PATCH 08/33] s4:dsdb/descriptor: remove some unnecessary nesting sd == NULL is checked before. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 8d60ac19ed0bc70ec3763614147465c04f28e286) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 21a559f..9a4f3d3 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -583,16 +583,14 @@ static int descriptor_add(struct ldb_module *module, struct ldb_request *req) if (msg == NULL) { return ldb_oom(ldb); } - 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; - } + 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; } } -- 1.7.9.5 From 4d8a6b7c7f409f4ec614412e402847145acfa658 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 09:31:05 +0100 Subject: [PATCH 09/33] s4:dsdb/descriptor: remove some nesting from descriptor_modify If the nTSecurityDescriptor attribute is not specified, we have nothing to do. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 4ef36fda681409bf7050adb98bb4b3d574bc01a9) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 9a4f3d3..b41c0aa 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -619,7 +619,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) const struct ldb_val *user_sd; struct ldb_dn *dn = req->op.mod.message->dn; struct ldb_dn *parent_dn; - struct ldb_message_element *objectclass_element; + struct ldb_message_element *objectclass_element, *sd_element; int ret; uint32_t instanceType; uint32_t sd_flags = dsdb_request_sd_flags(req, NULL); @@ -636,8 +636,15 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + + sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor"); + if (sd_element == NULL) { + return ldb_next_request(module, req); + } + user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); - if (!user_sd) { + /* nTSecurityDescriptor without a value is an error, letting through so it is handled */ + if (user_sd == NULL) { return ldb_next_request(module, req); } @@ -707,14 +714,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (msg == NULL) { return ldb_oom(ldb); } - 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; - } - } + sd_element->values[0] = *sd; ret = ldb_build_mod_req(&mod_req, ldb, req, msg, -- 1.7.9.5 From 31f64ab751af89c241284149fd4e45cf6efbfccb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 09:55:17 +0100 Subject: [PATCH 10/33] s4:dsdb/descriptor: make explicit that we don't support MOD_DELETE on nTSecurityDescriptor Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 5aa7dbe546ff18e521e72c0af713a2509201e00d) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index b41c0aa..4b4704b 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -642,6 +642,17 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + /* + * nTSecurityDescriptor with DELETE is not supported yet. + * TODO: handle this correctly. + */ + if (LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE) { + return ldb_module_error(module, + LDB_ERR_UNWILLING_TO_PERFORM, + "MOD_DELETE for nTSecurityDescriptor " + "not supported yet"); + } + user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); /* nTSecurityDescriptor without a value is an error, letting through so it is handled */ if (user_sd == NULL) { -- 1.7.9.5 From 6f6638a7ff30702bbfe10acfa575db6f9ef544f9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 10:58:49 +0100 Subject: [PATCH 11/33] s4:dsdb/descriptor: the old nTSecurityDescriptor is always expected there on modify Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit f67f469ce101e48301de790b5c31f8d4e712e0ea) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 4b4704b..96bc356 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -714,6 +714,9 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) } old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor"); + if (old_sd == NULL) { + return ldb_operr(ldb); + } sd = get_new_descriptor(module, dn, req, objectclass, parent_sd, -- 1.7.9.5 From 87437489e552632f8a7866a157510a051e02b457 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 09:15:24 +0100 Subject: [PATCH 12/33] s4:dsdb/acl: also add DSDB_SECRET_ATTRIBUTES into the password attributes The @KLUDGEACL record might not be uptodate. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit b54d268e2042f36bc670cf8f4f33cddd957e1d34) --- source4/dsdb/samdb/ldb_modules/acl.c | 41 +++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 2cc028f..4a288f1 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -79,9 +79,12 @@ static int acl_module_init(struct ldb_module *module) struct ldb_context *ldb; struct acl_private *data; int ret; - unsigned int i; + unsigned int i, n, j; TALLOC_CTX *mem_ctx; - static const char *attrs[] = { "passwordAttribute", NULL }; + static const char * const attrs[] = { "passwordAttribute", NULL }; + static const char * const secret_attrs[] = { + DSDB_SECRET_ATTRIBUTES + }; struct ldb_result *res; struct ldb_message *msg; struct ldb_message_element *password_attributes; @@ -133,16 +136,44 @@ static int acl_module_init(struct ldb_module *module) if (!password_attributes) { goto done; } - data->password_attrs = talloc_array(data, const char *, password_attributes->num_values + 1); + data->password_attrs = talloc_array(data, const char *, + password_attributes->num_values + + ARRAY_SIZE(secret_attrs) + 1); if (!data->password_attrs) { talloc_free(mem_ctx); return ldb_oom(ldb); } + + n = 0; for (i=0; i < password_attributes->num_values; i++) { - data->password_attrs[i] = (const char *)password_attributes->values[i].data; + data->password_attrs[n] = (const char *)password_attributes->values[i].data; talloc_steal(data->password_attrs, password_attributes->values[i].data); + n++; + } + + for (i=0; i < ARRAY_SIZE(secret_attrs); i++) { + bool found = false; + + for (j=0; j < n; j++) { + if (strcasecmp(data->password_attrs[j], secret_attrs[i]) == 0) { + found = true; + break; + } + } + + if (found) { + continue; + } + + data->password_attrs[n] = talloc_strdup(data->password_attrs, + secret_attrs[i]); + if (data->password_attrs[n] == NULL) { + talloc_free(mem_ctx); + return ldb_oom(ldb); + } + n++; } - data->password_attrs[i] = NULL; + data->password_attrs[n] = NULL; done: talloc_free(mem_ctx); -- 1.7.9.5 From 93ad9678f29b5ea61cb7ccc06df60cfd78be7fb9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 09:17:27 +0100 Subject: [PATCH 13/33] s4:dsdb/common: add pekList and msDS-ExecuteScriptPassword to DSDB_SECRET_ATTRIBUTES_EX See [MS-ADTS] 3.1.1.4.4 Extended Access Checks. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 0c2c00e4b9afd72b4f4052e6b19e40096fd1e44c) --- source4/dsdb/common/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/dsdb/common/util.h b/source4/dsdb/common/util.h index c16ce81..0f9b442 100644 --- a/source4/dsdb/common/util.h +++ b/source4/dsdb/common/util.h @@ -46,6 +46,8 @@ bool is_attr_in_list(const char * const * attrs, const char *attr); #define DSDB_SECRET_ATTRIBUTES_EX(sep) \ + "pekList" sep \ + "msDS-ExecuteScriptPassword" sep \ "currentValue" sep \ "dBCSPwd" sep \ "initialAuthIncoming" sep \ -- 1.7.9.5 From 77a172198c04af18731bc25af08df683d2b9f820 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 09:19:52 +0100 Subject: [PATCH 14/33] s4:provision: add pekList and msDS-ExecuteScriptPassword to @KLUDGEACL Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit ffaf9bb98b5322cca31ef6a43f8c27ca4e5fe42e) --- source4/setup/provision_init.ldif | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif index 68b3d97..3d14578 100644 --- a/source4/setup/provision_init.ldif +++ b/source4/setup/provision_init.ldif @@ -17,6 +17,8 @@ passwordAttribute: trustAuthOutgoing passwordAttribute: trustAuthIncoming passwordAttribute: initialAuthOutgoing passwordAttribute: initialAuthIncoming +passwordAttribute: pekList +passwordAttribute: msDS-ExecuteScriptPassword dn: @OPTIONS checkBaseOnSearch: TRUE -- 1.7.9.5 From 263db9af9fbd960996641ef51b7c111527d98ea3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 09:20:37 +0100 Subject: [PATCH 15/33] s4:dsdb/dirsync: remove unused 'deletedattr' variable Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 60c29a51a062640bf23c85d0d2f650d35a9ab59c) --- source4/dsdb/samdb/ldb_modules/dirsync.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c index 662d0c3..f75ec52 100644 --- a/source4/dsdb/samdb/ldb_modules/dirsync.c +++ b/source4/dsdb/samdb/ldb_modules/dirsync.c @@ -75,7 +75,6 @@ static int dirsync_filter_entry(struct ldb_request *req, uint32_t n; int i; unsigned int size, j; - uint32_t deletedattr; struct ldb_val *replMetaData = NULL; struct replPropertyMetaDataBlob rmd; const struct dsdb_attribute *attr; @@ -118,7 +117,6 @@ static int dirsync_filter_entry(struct ldb_request *req, */ rdn = ldb_dn_get_rdn_name(msg->dn); - deletedattr = 0; /* * if objectGUID is asked and we are dealing for the referrals entries and * the usn searched is 0 then we didn't count the objectGUID as an automatically -- 1.7.9.5 From 86edcf6b5487a2a425d81524a7b8ea36f5e277d6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 10:06:13 +0100 Subject: [PATCH 16/33] s4:dsdb/acl: require SEC_ADS_DELETE_TREE if the TREE_DELETE control is given (bug #7711) Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 5838637b4218ecf88e7a650610da3be1a5a518c9) --- source4/dsdb/samdb/ldb_modules/acl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 4a288f1..9bf2612 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -1230,6 +1230,18 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req) } talloc_free(nc_root); + if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID)) { + ret = dsdb_module_check_access_on_dn(module, req, + req->op.del.dn, + SEC_ADS_DELETE_TREE, NULL, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(module, req); + } + /* First check if we have delete object right */ ret = dsdb_module_check_access_on_dn(module, req, req->op.del.dn, SEC_STD_DELETE, NULL, req); -- 1.7.9.5 From 4012a7ecfc7f0fa99496cdb4a6b243a19ba83b7f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 23:21:10 +0100 Subject: [PATCH 17/33] s4:dsdb/objectclass: do not pass the callers controls on helper searches We add AS_SYSTEM and SHOW_RECYCLED to the helper search, don't let the caller specify additional controls. This also fixes a problem when the caller also specified AS_SYSTEM. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit ff274bafeb223c7440f4d97e2225b954b1031259) --- source4/dsdb/samdb/ldb_modules/objectclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 590927a..de154ec 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -1264,7 +1264,7 @@ static int objectclass_delete(struct ldb_module *module, struct ldb_request *req ret = ldb_build_search_req(&search_req, ldb, ac, req->op.del.dn, LDB_SCOPE_BASE, "(objectClass=*)", - attrs, req->controls, + attrs, NULL, ac, get_search_callback, req); LDB_REQ_SET_LOCATION(search_req); -- 1.7.9.5 From 03fdf0f06232584f228ab9e1c9555a39165c5431 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 10:04:39 +0100 Subject: [PATCH 18/33] s4:dsdb/subtree_delete: do an early return and avoid some nesting Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 60192fd1004015b50e208b3da6a07bd67f9d7990) --- source4/dsdb/samdb/ldb_modules/subtree_delete.c | 52 ++++++++++++----------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c index d82c3ab..ce1b892 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c @@ -61,34 +61,38 @@ static int subtree_delete(struct ldb_module *module, struct ldb_request *req) talloc_free(res); return ret; } - if (res->count > 0) { - if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID) == NULL) { - /* Do not add any DN outputs to this error string! - * Some MMC consoles (eg release 2000) have a strange - * bug and prevent subtree deletes afterwards. */ - ldb_asprintf_errstring(ldb_module_get_ctx(module), - "subtree_delete: Unable to " - "delete a non-leaf node " - "(it has %u children)!", - res->count); - talloc_free(res); - return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; - } + if (res->count == 0) { + talloc_free(res); + return ldb_next_request(module, req); + } - /* we need to start from the top since other LDB modules could - * enforce constraints (eg "objectclass" and "samldb" do so). */ - flags = DSDB_FLAG_TOP_MODULE | DSDB_TREE_DELETE; - if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) { - flags |= DSDB_MODIFY_RELAX; - } + if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID) == NULL) { + /* Do not add any DN outputs to this error string! + * Some MMC consoles (eg release 2000) have a strange + * bug and prevent subtree deletes afterwards. */ + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "subtree_delete: Unable to " + "delete a non-leaf node " + "(it has %u children)!", + res->count); + talloc_free(res); + return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; + } - for (i = 0; i < res->count; i++) { - ret = dsdb_module_del(module, res->msgs[i]->dn, flags, req); - if (ret != LDB_SUCCESS) { - return ret; - } + /* we need to start from the top since other LDB modules could + * enforce constraints (eg "objectclass" and "samldb" do so). */ + flags = DSDB_FLAG_TOP_MODULE | DSDB_TREE_DELETE; + if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) { + flags |= DSDB_MODIFY_RELAX; + } + + for (i = 0; i < res->count; i++) { + ret = dsdb_module_del(module, res->msgs[i]->dn, flags, req); + if (ret != LDB_SUCCESS) { + return ret; } } + talloc_free(res); return ldb_next_request(module, req); -- 1.7.9.5 From f4db804d5268f544b1502d2b5c4e101cdc37af1e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 10:14:59 +0100 Subject: [PATCH 19/33] s4:dsdb/subtree_delete: do the recursive delete AS_SYSTEM/TRUSTED (bug #7711) Now that the acl module checks for SEC_ADS_DELETE_TREE, we can do the recursive delete AS_SYSTEM. We need to pass the TRUSTED flags as we operate from the TOP module. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 5dd4555f391d841b276e53e70eedde36f5190cdd) --- source4/dsdb/samdb/ldb_modules/subtree_delete.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c index ce1b892..f041b7e 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c @@ -79,9 +79,17 @@ static int subtree_delete(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; } - /* we need to start from the top since other LDB modules could - * enforce constraints (eg "objectclass" and "samldb" do so). */ - flags = DSDB_FLAG_TOP_MODULE | DSDB_TREE_DELETE; + /* + * we need to start from the top since other LDB modules could + * enforce constraints (eg "objectclass" and "samldb" do so). + * + * We pass DSDB_FLAG_AS_SYSTEM as the acl module above us + * has already checked for SEC_ADS_DELETE_TREE. + */ + flags = DSDB_FLAG_TOP_MODULE | + DSDB_FLAG_AS_SYSTEM | + DSDB_FLAG_TRUSTED | + DSDB_TREE_DELETE; if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) { flags |= DSDB_MODIFY_RELAX; } -- 1.7.9.5 From 5a06b9f0a9b22000dc6b1c1b371c5ff8e469beab Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 10:16:45 +0100 Subject: [PATCH 20/33] s4:dsdb/subtree_delete: delete from the leafs to the root (bug #7711) Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 7f88ad3efce5bc14de49b3d73a5dcb19499e1342) --- source4/dsdb/samdb/ldb_modules/subtree_delete.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c index f041b7e..b1f87f7 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c @@ -38,6 +38,19 @@ #include "dsdb/common/util.h" +static int subtree_delete_sort(struct ldb_message **m1, + struct ldb_message **m2, + void *private_data) +{ + struct ldb_dn *dn1 = (*m1)->dn; + struct ldb_dn *dn2 = (*m2)->dn; + + /* + * This sorts in tree order, children first + */ + return ldb_dn_compare(dn1, dn2); +} + static int subtree_delete(struct ldb_module *module, struct ldb_request *req) { static const char * const attrs[] = { NULL }; @@ -80,6 +93,12 @@ static int subtree_delete(struct ldb_module *module, struct ldb_request *req) } /* + * First we sort the results from the leaf to the root + */ + LDB_TYPESAFE_QSORT(res->msgs, res->count, NULL, + subtree_delete_sort); + + /* * we need to start from the top since other LDB modules could * enforce constraints (eg "objectclass" and "samldb" do so). * -- 1.7.9.5 From a3affc9cefcad0a092870db40536a87efe7d1934 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 17:42:32 +0100 Subject: [PATCH 21/33] s4:dsdb: define DSDB_CONTROL_SEC_DESC_PROPAGATION_OID Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 60f0e172e3ce182324c4573fc05197ba241def89) --- source4/dsdb/samdb/samdb.h | 7 +++++++ source4/setup/schema_samba4.ldif | 1 + 2 files changed, 8 insertions(+) diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 6946782..6ee97da 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -128,6 +128,13 @@ struct dsdb_control_password_change { /* passed when importing plain text password on upgrades */ #define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20" +/* + * passed from the descriptor module in order to + * store the recalucated nTSecurityDescriptor without + * modifying the replPropertyMetaData. + */ +#define DSDB_CONTROL_SEC_DESC_PROPAGATION_OID "1.3.6.1.4.1.7165.4.3.21" + #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1" struct dsdb_extended_replicated_object { struct ldb_message *msg; diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 0c5c787..38dba77 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -196,6 +196,7 @@ #Allocated: DSDB_CONTROL_DBCHECK 1.3.6.1.4.1.7165.4.3.19 #Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1 #Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20 +#Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21 # Extended 1.3.6.1.4.1.7165.4.4.x #Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1 -- 1.7.9.5 From c266adbc8e992863ae9429a233b9d43329425b57 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 24 Nov 2012 15:25:06 +0100 Subject: [PATCH 22/33] s4:dsdb/objectclass_attrs: allow DSDB_CONTROL_SEC_DESC_PROPAGATION_OID on modify Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit cb9c7ee79b2f4e8c875bd15c1fddee90648eec19) --- source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c index c521f33..316dcf8 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c @@ -600,6 +600,9 @@ static int objectclass_attrs_modify(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb; + struct ldb_control *sd_propagation_control; + int ret; + struct oc_context *ac; ldb = ldb_module_get_ctx(module); @@ -611,6 +614,21 @@ static int objectclass_attrs_modify(struct ldb_module *module, return ldb_next_request(module, req); } + sd_propagation_control = ldb_request_get_control(req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); + if (sd_propagation_control != NULL) { + if (req->op.mod.message->num_elements != 1) { + return ldb_module_operr(module); + } + ret = strcmp(req->op.mod.message->elements[0].name, + "nTSecurityDescriptor"); + if (ret != 0) { + return ldb_module_operr(module); + } + + return ldb_next_request(module, req); + } + ac = oc_init_context(module, req); if (ac == NULL) { return ldb_operr(ldb); -- 1.7.9.5 From 6ec65c0e5e149f5ab0b1fe2e4827ec1926a994f7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 11:18:05 +0100 Subject: [PATCH 23/33] s4:dsdb/repl_meta_data: allow DSDB_CONTROL_SEC_DESC_PROPAGATION_OID on modify The propagation of nTSecurityDescriptor doesn't change the replProperyMetaData. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 7f42a8b7b667c6a704ecd7bce1630971eb3f1e8c) --- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 6b5e121..7e1993c 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -2306,12 +2306,28 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) bool is_urgent = false, rodc = false; unsigned int functional_level; const DATA_BLOB *guid_blob; + struct ldb_control *sd_propagation_control; /* do not manipulate our control entries */ if (ldb_dn_is_special(req->op.mod.message->dn)) { return ldb_next_request(module, req); } + sd_propagation_control = ldb_request_get_control(req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); + if (sd_propagation_control != NULL) { + if (req->op.mod.message->num_elements != 1) { + return ldb_module_operr(module); + } + ret = strcmp(req->op.mod.message->elements[0].name, + "nTSecurityDescriptor"); + if (ret != 0) { + return ldb_module_operr(module); + } + + return ldb_next_request(module, req); + } + ldb = ldb_module_get_ctx(module); ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n"); -- 1.7.9.5 From c7211ccc62c3233656c2a54adad3e4ee81f9ba00 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 Nov 2012 16:12:54 +0100 Subject: [PATCH 24/33] s4:dsdb/schema_data: allow DSDB_CONTROL_SEC_DESC_PROPAGATION_OID on modify Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 1be4dbc0ca732bd2c35b6108331120a3f1a54ada) --- source4/dsdb/samdb/ldb_modules/schema_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/schema_data.c b/source4/dsdb/samdb/ldb_modules/schema_data.c index 223d698..bc9488b 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_data.c +++ b/source4/dsdb/samdb/ldb_modules/schema_data.c @@ -256,6 +256,7 @@ static int schema_data_modify(struct ldb_module *module, struct ldb_request *req int cmp; bool rodc = false; int ret; + struct ldb_control *sd_propagation_control; ldb = ldb_module_get_ctx(module); @@ -274,6 +275,21 @@ static int schema_data_modify(struct ldb_module *module, struct ldb_request *req return ldb_next_request(module, req); } + sd_propagation_control = ldb_request_get_control(req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); + if (sd_propagation_control != NULL) { + if (req->op.mod.message->num_elements != 1) { + return ldb_module_operr(module); + } + ret = strcmp(req->op.mod.message->elements[0].name, + "nTSecurityDescriptor"); + if (ret != 0) { + return ldb_module_operr(module); + } + + return ldb_next_request(module, req); + } + schema = dsdb_get_schema(ldb, req); if (!schema) { return ldb_next_request(module, req); -- 1.7.9.5 From 0428d44d4714076680003cf87578565b84a23855 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 10:45:02 +0100 Subject: [PATCH 25/33] s4:dsdb/descriptor: handle DSDB_CONTROL_SEC_DESC_PROPAGATION_OID This can only be triggered by ourself, that's why we expect control->data == module. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit ddea8564901f5aa1a25cd84713bf86a2ce95bc07) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 72 +++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 96bc356..50210fe 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -622,7 +622,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) struct ldb_message_element *objectclass_element, *sd_element; int ret; uint32_t instanceType; - uint32_t sd_flags = dsdb_request_sd_flags(req, NULL); + bool explicit_sd_flags = false; + uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags); const struct dsdb_schema *schema; DATA_BLOB *sd; const struct dsdb_class *objectclass; @@ -630,6 +631,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) static const char * const current_attrs[] = { "nTSecurityDescriptor", "instanceType", "objectClass", NULL }; + struct ldb_control *sd_propagation_control; /* do not manipulate our control entries */ if (ldb_dn_is_special(dn)) { @@ -637,8 +639,30 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) } + sd_propagation_control = ldb_request_get_control(req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); + if (sd_propagation_control != NULL) { + if (sd_propagation_control->data != module) { + return ldb_operr(ldb); + } + if (req->op.mod.message->num_elements != 0) { + return ldb_operr(ldb); + } + if (explicit_sd_flags) { + return ldb_operr(ldb); + } + if (sd_flags != 0xF) { + return ldb_operr(ldb); + } + if (sd_propagation_control->critical == 0) { + return ldb_operr(ldb); + } + + sd_propagation_control->critical = 0; + } + sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor"); - if (sd_element == NULL) { + if (sd_propagation_control == NULL && sd_element == NULL) { return ldb_next_request(module, req); } @@ -646,7 +670,9 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) * nTSecurityDescriptor with DELETE is not supported yet. * TODO: handle this correctly. */ - if (LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE) { + if (sd_propagation_control == NULL && + LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE) + { return ldb_module_error(module, LDB_ERR_UNWILLING_TO_PERFORM, "MOD_DELETE for nTSecurityDescriptor " @@ -655,7 +681,7 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); /* nTSecurityDescriptor without a value is an error, letting through so it is handled */ - if (user_sd == NULL) { + if (sd_propagation_control == NULL && user_sd == NULL) { return ldb_next_request(module, req); } @@ -718,6 +744,14 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) return ldb_operr(ldb); } + if (sd_propagation_control != NULL) { + /* + * This just triggers a recalculation of the + * inherited aces. + */ + user_sd = old_sd; + } + sd = get_new_descriptor(module, dn, req, objectclass, parent_sd, user_sd, old_sd, sd_flags); @@ -728,7 +762,35 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (msg == NULL) { return ldb_oom(ldb); } - sd_element->values[0] = *sd; + if (sd_propagation_control != NULL) { + ret = data_blob_cmp(old_sd, sd); + if (ret == 0) { + /* + * The nTSecurityDescriptor is unchanged, + * which means we can stop the processing. + * + * We mark the control as critical again, + * as we have not processed it, so the caller + * can tell that the descriptor was unchanged. + */ + sd_propagation_control->critical = 1; + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); + } + + ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", + LDB_FLAG_MOD_REPLACE, + &sd_element); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } + ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", + sd, NULL); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } + } else { + sd_element->values[0] = *sd; + } ret = ldb_build_mod_req(&mod_req, ldb, req, msg, -- 1.7.9.5 From ff4f97497bc403fdd9f499bd7c6375ecc26b932b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Nov 2012 17:42:32 +0100 Subject: [PATCH 26/33] s4:dsdb: define DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 2101400af2e5e1b72a5d51e83f005f62bec1f482) --- source4/dsdb/samdb/samdb.h | 12 ++++++++++++ source4/setup/schema_samba4.ldif | 1 + 2 files changed, 13 insertions(+) diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 6ee97da..7605c65 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -231,6 +231,18 @@ struct dsdb_fsmo_extended_op { struct GUID destination_dsa_guid; }; +/* + * passed from the descriptor module in order to + * store the recalucated nTSecurityDescriptor without + * modifying the replPropertyMetaData. + */ +#define DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID "1.3.6.1.4.1.7165.4.4.7" +struct dsdb_extended_sec_desc_propagation_op { + struct ldb_dn *nc_root; + struct ldb_dn *dn; + bool include_self; +}; + #define DSDB_ACL_CHECKS_DIRSYNC_FLAG 0x1 #define DSDB_METADATA_SCHEMA_SEQ_NUM "SCHEMA_SEQ_NUM" diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 38dba77..94aedb0 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -205,6 +205,7 @@ #Allocated: DSDB_EXTENDED_CREATE_PARTITION_OID 1.3.6.1.4.1.7165.4.4.4 #Allocated: DSDB_EXTENDED_ALLOCATE_RID_POOL 1.3.6.1.4.1.7165.4.4.5 #Allocated: DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID 1.3.6.1.4.1.7165.4.4.6 +#Allocated: DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.4.7 ############ -- 1.7.9.5 From 8a22f8c76133c1ae7736b9ac030a903b509a9ca4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 15:55:24 +0100 Subject: [PATCH 27/33] s4:dsdb/descriptor: implement DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit d6962f40caad861c7d240d80bd04070989c85a73) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 403 ++++++++++++++++++++++++++- 1 file changed, 395 insertions(+), 8 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 50210fe..9ffb6eb 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -42,9 +42,21 @@ #include "auth/auth.h" #include "param/param.h" #include "dsdb/samdb/ldb_modules/util.h" +#include "lib/util/binsearch.h" + +struct descriptor_changes { + struct descriptor_changes *prev, *next; + struct descriptor_changes *children; + struct ldb_dn *nc_root; + struct ldb_dn *dn; + bool force_self; + bool force_children; + struct ldb_dn *stopped_dn; +}; struct descriptor_data { - int _dummy; + TALLOC_CTX *trans_mem; + struct descriptor_changes *changes; }; struct descriptor_context { @@ -865,26 +877,401 @@ static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } +static int descriptor_extended_sec_desc_propagation(struct ldb_module *module, + struct ldb_request *req) +{ + struct descriptor_data *descriptor_private = + talloc_get_type_abort(ldb_module_get_private(module), + struct descriptor_data); + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct dsdb_extended_sec_desc_propagation_op *op; + TALLOC_CTX *parent_mem = NULL; + struct descriptor_changes *parent_change = NULL; + struct descriptor_changes *c; + int ret; + + op = talloc_get_type(req->op.extended.data, + struct dsdb_extended_sec_desc_propagation_op); + if (op == NULL) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "descriptor_extended_sec_desc_propagation: " + "invalid extended data\n"); + return LDB_ERR_PROTOCOL_ERROR; + } + + if (descriptor_private->trans_mem == NULL) { + return ldb_module_operr(module); + } + + parent_mem = descriptor_private->trans_mem; + + for (c = descriptor_private->changes; c; c = c->next) { + ret = ldb_dn_compare(c->nc_root, op->nc_root); + if (ret != 0) { + continue; + } + + ret = ldb_dn_compare(c->dn, op->dn); + if (ret == 0) { + if (op->include_self) { + c->force_self = true; + } else { + c->force_children = true; + } + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); + } + + ret = ldb_dn_compare_base(c->dn, op->dn); + if (ret != 0) { + continue; + } + + parent_mem = c; + parent_change = c; + break; + } + + c = talloc_zero(parent_mem, struct descriptor_changes); + if (c == NULL) { + return ldb_module_oom(module); + } + c->nc_root = ldb_dn_copy(c, op->nc_root); + if (c->nc_root == NULL) { + return ldb_module_oom(module); + } + c->dn = ldb_dn_copy(c, op->dn); + if (c->dn == NULL) { + return ldb_module_oom(module); + } + if (op->include_self) { + c->force_self = true; + } else { + c->force_children = true; + } + + if (parent_change != NULL) { + DLIST_ADD_END(parent_change->children, c, NULL); + } else { + DLIST_ADD_END(descriptor_private->changes, c, NULL); + } + + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); +} + +static int descriptor_extended(struct ldb_module *module, struct ldb_request *req) +{ + if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) { + return descriptor_extended_sec_desc_propagation(module, req); + } + + return ldb_next_request(module, req); +} + static int descriptor_init(struct ldb_module *module) { - int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret; + struct descriptor_data *descriptor_private; + + ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor: Unable to register control with rootdse!\n"); return ldb_operr(ldb); } + + descriptor_private = talloc_zero(module, struct descriptor_data); + if (descriptor_private == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ldb_module_set_private(module, descriptor_private); + return ldb_next_init(module); } +static int descriptor_sd_propagation_object(struct ldb_module *module, + struct ldb_message *msg, + bool *stop) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_request *sub_req; + struct ldb_result *mod_res; + struct ldb_control *sd_propagation_control; + int ret; + + *stop = false; + + mod_res = talloc_zero(msg, struct ldb_result); + if (mod_res == NULL) { + return ldb_module_oom(module); + } + + ret = ldb_build_mod_req(&sub_req, ldb, mod_res, + msg, + NULL, + mod_res, + ldb_modify_default_callback, + NULL); + LDB_REQ_SET_LOCATION(sub_req); + if (ret != LDB_SUCCESS) { + return ldb_module_operr(module); + } + + ldb_req_mark_trusted(sub_req); + + ret = ldb_request_add_control(sub_req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID, + true, module); + if (ret != LDB_SUCCESS) { + return ldb_module_operr(module); + } + + sd_propagation_control = ldb_request_get_control(sub_req, + DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); + if (sd_propagation_control == NULL) { + return ldb_module_operr(module); + } + + ret = dsdb_request_add_controls(sub_req, + DSDB_FLAG_AS_SYSTEM | + DSDB_SEARCH_SHOW_RECYCLED); + if (ret != LDB_SUCCESS) { + return ldb_module_operr(module); + } + + ret = descriptor_modify(module, sub_req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL); + } + if (ret != LDB_SUCCESS) { + return ldb_module_operr(module); + } + + if (sd_propagation_control->critical != 0) { + *stop = true; + } + + talloc_free(mod_res); + + return LDB_SUCCESS; +} + +static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1, + struct ldb_message **m2) +{ + struct ldb_dn *dn1 = (*m1)->dn; + struct ldb_dn *dn2 = (*m2)->dn; + + /* + * This sorts in tree order, parents first + */ + return ldb_dn_compare(dn2, dn1); +} + +static int descriptor_sd_propagation_dn_sort(struct ldb_dn *dn1, + struct ldb_dn *dn2) +{ + /* + * This sorts in tree order, parents first + */ + return ldb_dn_compare(dn2, dn1); +} + +static int descriptor_sd_propagation_recursive(struct ldb_module *module, + struct descriptor_changes *change) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_result *res = NULL; + unsigned int i; + const char * const no_attrs[] = { "@__NONE__", NULL }; + struct descriptor_changes *c; + struct descriptor_changes *stopped_stack = NULL; + int ret; + + /* + * Note: that we do not search for deleted/recycled objects + */ + ret = dsdb_module_search(module, + change, + &res, + change->dn, + LDB_SCOPE_SUBTREE, + no_attrs, + DSDB_FLAG_NEXT_MODULE | + DSDB_FLAG_AS_SYSTEM, + NULL, /* parent_req */ + "(objectClass=*)"); + if (ret != LDB_SUCCESS) { + return ret; + } + + TYPESAFE_QSORT(res->msgs, res->count, + descriptor_sd_propagation_msg_sort); + + for (c = change->children; c; c = c->next) { + struct ldb_message *msg = NULL; + + BINARY_ARRAY_SEARCH_P(res->msgs, res->count, dn, c->dn, + descriptor_sd_propagation_dn_sort, + msg); + + if (msg == NULL) { + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "descriptor_sd_propagation_recursive: " + "%s not found under %s", + ldb_dn_get_linearized(c->dn), + ldb_dn_get_linearized(change->dn)); + return LDB_ERR_OPERATIONS_ERROR; + } + + msg->elements = (struct ldb_message_element *)c; + } + + DLIST_ADD(stopped_stack, change); + + if (change->force_self) { + i = 0; + } else { + i = 1; + } + + for (; i < res->count; i++) { + struct descriptor_changes *cur; + bool stop = false; + + cur = talloc_get_type(res->msgs[i]->elements, + struct descriptor_changes); + res->msgs[i]->elements = NULL; + res->msgs[i]->num_elements = 0; + + if (cur != NULL) { + DLIST_REMOVE(change->children, cur); + } + + for (c = stopped_stack; c; c = stopped_stack) { + ret = ldb_dn_compare_base(c->dn, + res->msgs[i]->dn); + if (ret == 0) { + break; + } + + c->stopped_dn = NULL; + DLIST_REMOVE(stopped_stack, c); + } + + if (cur != NULL) { + DLIST_ADD(stopped_stack, cur); + } + + if (stopped_stack->stopped_dn != NULL) { + ret = ldb_dn_compare_base(stopped_stack->stopped_dn, + res->msgs[i]->dn); + if (ret == 0) { + continue; + } + stopped_stack->stopped_dn = NULL; + } + + ret = descriptor_sd_propagation_object(module, res->msgs[i], + &stop); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (cur != NULL && cur->force_children) { + continue; + } + + if (stop) { + stopped_stack->stopped_dn = res->msgs[i]->dn; + continue; + } + } + + TALLOC_FREE(res); + return LDB_SUCCESS; +} + +static int descriptor_start_transaction(struct ldb_module *module) +{ + struct descriptor_data *descriptor_private = + talloc_get_type_abort(ldb_module_get_private(module), + struct descriptor_data); + + if (descriptor_private->trans_mem != NULL) { + return ldb_module_operr(module); + } + + descriptor_private->trans_mem = talloc_new(descriptor_private); + if (descriptor_private->trans_mem == NULL) { + return ldb_module_oom(module); + } + descriptor_private->changes = NULL; + + return ldb_next_start_trans(module); +} + +static int descriptor_prepare_commit(struct ldb_module *module) +{ + struct descriptor_data *descriptor_private = + talloc_get_type_abort(ldb_module_get_private(module), + struct descriptor_data); + struct descriptor_changes *c, *n; + int ret; + + for (c = descriptor_private->changes; c; c = n) { + n = c->next; + DLIST_REMOVE(descriptor_private->changes, c); + + ret = descriptor_sd_propagation_recursive(module, c); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + continue; + } + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return ldb_next_prepare_commit(module); +} + +static int descriptor_end_transaction(struct ldb_module *module) +{ + struct descriptor_data *descriptor_private = + talloc_get_type_abort(ldb_module_get_private(module), + struct descriptor_data); + + TALLOC_FREE(descriptor_private->trans_mem); + descriptor_private->changes = NULL; + + return ldb_next_end_trans(module); +} + +static int descriptor_del_transaction(struct ldb_module *module) +{ + struct descriptor_data *descriptor_private = + talloc_get_type_abort(ldb_module_get_private(module), + struct descriptor_data); + + TALLOC_FREE(descriptor_private->trans_mem); + descriptor_private->changes = NULL; + + return ldb_next_del_trans(module); +} static const struct ldb_module_ops ldb_descriptor_module_ops = { - .name = "descriptor", - .search = descriptor_search, - .add = descriptor_add, - .modify = descriptor_modify, - .rename = descriptor_rename, - .init_context = descriptor_init + .name = "descriptor", + .search = descriptor_search, + .add = descriptor_add, + .modify = descriptor_modify, + .rename = descriptor_rename, + .init_context = descriptor_init, + .extended = descriptor_extended, + .start_transaction = descriptor_start_transaction, + .prepare_commit = descriptor_prepare_commit, + .end_transaction = descriptor_end_transaction, + .del_transaction = descriptor_del_transaction, }; int ldb_descriptor_module_init(const char *version) -- 1.7.9.5 From b5a6442d9dcd97b628e7bc5ea9751e1d544ceda2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 16:46:51 +0100 Subject: [PATCH 28/33] s4:dsdb/acl_util: add dsdb_module_schedule_sd_propagation() Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit dae1b0d85207040fed873d4232a45206b0162f53) --- source4/dsdb/samdb/ldb_modules/acl_util.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/acl_util.c b/source4/dsdb/samdb/ldb_modules/acl_util.c index aa7e1aa..fc6a55a 100644 --- a/source4/dsdb/samdb/ldb_modules/acl_util.c +++ b/source4/dsdb/samdb/ldb_modules/acl_util.c @@ -239,3 +239,32 @@ uint32_t dsdb_request_sd_flags(struct ldb_request *req, bool *explicit) return sd_flags; } + +int dsdb_module_schedule_sd_propagation(struct ldb_module *module, + struct ldb_dn *nc_root, + struct ldb_dn *dn, + bool include_self) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct dsdb_extended_sec_desc_propagation_op *op; + int ret; + + op = talloc_zero(module, struct dsdb_extended_sec_desc_propagation_op); + if (op == NULL) { + return ldb_oom(ldb); + } + + op->nc_root = nc_root; + op->dn = dn; + op->include_self = include_self; + + ret = dsdb_module_extended(module, op, NULL, + DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID, + op, + DSDB_FLAG_TOP_MODULE | + DSDB_FLAG_AS_SYSTEM | + DSDB_FLAG_TRUSTED, + NULL); + TALLOC_FREE(op); + return ret; +} -- 1.7.9.5 From e698d0cea9876d7e5913803b4297ac8ffddc50fe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Nov 2012 12:49:16 +0100 Subject: [PATCH 29/33] s4:dsdb/descriptor: recalculate nTSecurityDescriptor after a rename (bug #8621) Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit f8c0ad65ad783b3c82ec8ab120d18ad454fe2665) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 9ffb6eb..36a64d0 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -860,11 +860,13 @@ static int descriptor_search(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(ac->module, down_req); } -/* TODO */ + static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_dn *olddn = req->op.rename.olddn; + struct ldb_dn *newdn = req->op.rename.newdn; + int ret; /* do not manipulate our control entries */ if (ldb_dn_is_special(req->op.rename.olddn)) { @@ -874,6 +876,21 @@ static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(olddn)); + if (ldb_dn_compare(olddn, newdn) != 0) { + struct ldb_dn *nc_root; + + ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } + + ret = dsdb_module_schedule_sd_propagation(module, nc_root, + newdn, true); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } + } + return ldb_next_request(module, req); } -- 1.7.9.5 From 2ceeafcc94aca6a40e27c2321aa883f70b1bf149 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Nov 2012 12:49:16 +0100 Subject: [PATCH 30/33] s4:dsdb/descriptor: inherit nTSecurityDescriptor changes to children (bug #8621) Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit fb2a41d9453d94860104b7b96a75bf8fa96996d6) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 36a64d0..18caa38 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -644,13 +644,13 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) "instanceType", "objectClass", NULL }; struct ldb_control *sd_propagation_control; + int cmp_ret = -1; /* do not manipulate our control entries */ if (ldb_dn_is_special(dn)) { return ldb_next_request(module, req); } - sd_propagation_control = ldb_request_get_control(req, DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); if (sd_propagation_control != NULL) { @@ -774,9 +774,9 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (msg == NULL) { return ldb_oom(ldb); } + cmp_ret = data_blob_cmp(old_sd, sd); if (sd_propagation_control != NULL) { - ret = data_blob_cmp(old_sd, sd); - if (ret == 0) { + if (cmp_ret == 0) { /* * The nTSecurityDescriptor is unchanged, * which means we can stop the processing. @@ -800,6 +800,20 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) if (ret != LDB_SUCCESS) { return ldb_oom(ldb); } + } else if (cmp_ret != 0) { + struct ldb_dn *nc_root; + + ret = dsdb_find_nc_root(ldb, msg, dn, &nc_root); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } + + ret = dsdb_module_schedule_sd_propagation(module, nc_root, + dn, false); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } + sd_element->values[0] = *sd; } else { sd_element->values[0] = *sd; } -- 1.7.9.5 From 93066094612a375ca1a4678ebccbb5845e058a02 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Nov 2012 17:10:38 +0100 Subject: [PATCH 31/33] s4:dsdb/repl_meta_data: call dsdb_module_schedule_sd_propagation() for replicated changes We only do so if the replicated object is not deleted. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit d31742641fb117e4249dcc317dac662bb5e1a690) --- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 72 ++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 7e1993c..3ac1e6a 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -3654,6 +3654,7 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar) struct ldb_val md_value; unsigned int i; int ret; + bool remote_isDeleted = false; /* * TODO: check if the parent object exist @@ -3707,6 +3708,9 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar) } } + remote_isDeleted = ldb_msg_find_attr_as_bool(msg, + "isDeleted", false); + /* * the meta data array is already sorted by the caller */ @@ -3726,6 +3730,15 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar) replmd_ldb_message_sort(msg, ar->schema); + if (!remote_isDeleted) { + ret = dsdb_module_schedule_sd_propagation(ar->module, + ar->objs->partition_dn, + msg->dn, true); + if (ret != LDB_SUCCESS) { + return replmd_replicated_request_error(ar, ret); + } + } + if (DEBUGLVL(4)) { char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_ADD, msg); DEBUG(4, ("DRS replication add message:\n%s\n", s)); @@ -3920,11 +3933,14 @@ static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar, struct ldb_message *msg, struct replPropertyMetaDataBlob *rmd, struct replPropertyMetaDataBlob *omd, - struct ldb_request *parent) + struct ldb_request *parent, + bool *renamed) { struct replPropertyMetaData1 *md_remote; struct replPropertyMetaData1 *md_local; + *renamed = true; + if (ldb_dn_compare(msg->dn, ar->search_msg->dn) == 0) { /* no rename */ return LDB_SUCCESS; @@ -4012,6 +4028,12 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) unsigned int removed_attrs = 0; int ret; int (*callback)(struct ldb_request *req, struct ldb_reply *ares) = replmd_op_callback; + bool isDeleted = false; + bool local_isDeleted = false; + bool remote_isDeleted = false; + bool take_remote_isDeleted = false; + bool sd_updated = false; + bool renamed = false; ldb = ldb_module_get_ctx(ar->module); msg = ar->objs->objects[ar->index_current].msg; @@ -4035,8 +4057,14 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) } } + local_isDeleted = ldb_msg_find_attr_as_bool(ar->search_msg, + "isDeleted", false); + remote_isDeleted = ldb_msg_find_attr_as_bool(msg, + "isDeleted", false); + /* handle renames that come in over DRS */ - ret = replmd_replicated_handle_rename(ar, msg, rmd, &omd, ar->req); + ret = replmd_replicated_handle_rename(ar, msg, rmd, &omd, + ar->req, &renamed); /* * This particular error code means that we already tried the @@ -4075,6 +4103,7 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) /* Set the callback to one that will fix up the name to be a conflict DN */ callback = replmd_op_name_modify_callback; msg->dn = new_dn; + renamed = true; } else if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_replicated_request rename %s => %s failed - %s\n", @@ -4132,6 +4161,16 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) } } nmd.ctr.ctr1.array[j].local_usn = ar->seq_num; + switch (nmd.ctr.ctr1.array[j].attid) { + case DRSUAPI_ATTID_ntSecurityDescriptor: + sd_updated = true; + break; + case DRSUAPI_ATTID_isDeleted: + take_remote_isDeleted = true; + break; + default: + break; + } found = true; break; } @@ -4161,6 +4200,16 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) } } nmd.ctr.ctr1.array[ni].local_usn = ar->seq_num; + switch (nmd.ctr.ctr1.array[ni].attid) { + case DRSUAPI_ATTID_ntSecurityDescriptor: + sd_updated = true; + break; + case DRSUAPI_ATTID_isDeleted: + take_remote_isDeleted = true; + break; + default: + break; + } ni++; } @@ -4195,6 +4244,25 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_apply_merge[%u]: replace %u attributes\n", ar->index_current, msg->num_elements); + if (take_remote_isDeleted) { + isDeleted = remote_isDeleted; + } else { + isDeleted = local_isDeleted; + } + + if (renamed) { + sd_updated = true; + } + + if (sd_updated && !isDeleted) { + ret = dsdb_module_schedule_sd_propagation(ar->module, + ar->objs->partition_dn, + msg->dn, true); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } + } + /* create the meta data value */ ndr_err = ndr_push_struct_blob(&nmd_value, msg, &nmd, (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); -- 1.7.9.5 From e3f51a318a24c67364fed16d59595f5a480f5d36 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Nov 2012 12:51:44 +0100 Subject: [PATCH 32/33] s4:dsdb/tests: add SdAutoInheritTests Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam Autobuild-User(master): Michael Adam Autobuild-Date(master): Fri Nov 30 18:59:50 CET 2012 on sn-devel-104 (cherry picked from commit 057c56ac2443abffbe169b06a72a93f41096fb67) --- source4/dsdb/tests/python/sec_descriptor.py | 84 ++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/tests/python/sec_descriptor.py b/source4/dsdb/tests/python/sec_descriptor.py index 087ce5e..aff6040 100755 --- a/source4/dsdb/tests/python/sec_descriptor.py +++ b/source4/dsdb/tests/python/sec_descriptor.py @@ -19,7 +19,7 @@ import samba.getopt as options from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError, ERR_NO_SUCH_OBJECT # For running the test unit -from samba.ndr import ndr_pack +from samba.ndr import ndr_pack, ndr_unpack from samba.dcerpc import security from samba import gensec, sd_utils @@ -1960,6 +1960,86 @@ class RightsAttributesTests(DescriptorTests): self.assertTrue("displayName" in res[0]["allowedAttributesEffective"]) self.assertTrue("managedBy" in res[0]["allowedAttributesEffective"]) +class SdAutoInheritTests(DescriptorTests): + def deleteAll(self): + delete_force(self.ldb_admin, self.sub_dn) + delete_force(self.ldb_admin, self.ou_dn) + + def setUp(self): + super(SdAutoInheritTests, self).setUp() + self.ou_dn = "OU=test_SdAutoInherit_ou," + self.base_dn + self.sub_dn = "OU=test_sub," + self.ou_dn + self.deleteAll() + + def test_301(self): + """ Modify a descriptor with OWNER_SECURITY_INFORMATION set. + See that only the owner has been changed. + """ + attrs = ["nTSecurityDescriptor", "replPropertyMetaData", "uSNChanged"] + controls=["sd_flags:1:%d" % (SECINFO_DACL)] + ace = "(A;CI;CC;;;NU)" + sub_ace = "(A;CIID;CC;;;NU)" + sd_sddl = "O:BAG:BAD:P(A;CI;0x000f01ff;;;AU)" + sd = security.descriptor.from_sddl(sd_sddl, self.domain_sid) + + self.ldb_admin.create_ou(self.ou_dn,sd=sd) + self.ldb_admin.create_ou(self.sub_dn) + + ou_res0 = self.sd_utils.ldb.search(self.ou_dn, SCOPE_BASE, + None, attrs, controls=controls) + sub_res0 = self.sd_utils.ldb.search(self.sub_dn, SCOPE_BASE, + None, attrs, controls=controls) + + ou_sd0 = ndr_unpack(security.descriptor, ou_res0[0]["nTSecurityDescriptor"][0]) + sub_sd0 = ndr_unpack(security.descriptor, sub_res0[0]["nTSecurityDescriptor"][0]) + + ou_sddl0 = ou_sd0.as_sddl(self.domain_sid) + sub_sddl0 = sub_sd0.as_sddl(self.domain_sid) + + self.assertFalse(ace in ou_sddl0) + self.assertFalse(ace in sub_sddl0) + + ou_sddl1 = (ou_sddl0[:ou_sddl0.index("(")] + ace + + ou_sddl0[ou_sddl0.index("("):]) + + sub_sddl1 = (sub_sddl0[:sub_sddl0.index("(")] + ace + + sub_sddl0[sub_sddl0.index("("):]) + + self.sd_utils.modify_sd_on_dn(self.ou_dn, ou_sddl1, controls=controls) + + sub_res2 = self.sd_utils.ldb.search(self.sub_dn, SCOPE_BASE, + None, attrs, controls=controls) + ou_res2 = self.sd_utils.ldb.search(self.ou_dn, SCOPE_BASE, + None, attrs, controls=controls) + + ou_sd2 = ndr_unpack(security.descriptor, ou_res2[0]["nTSecurityDescriptor"][0]) + sub_sd2 = ndr_unpack(security.descriptor, sub_res2[0]["nTSecurityDescriptor"][0]) + + ou_sddl2 = ou_sd2.as_sddl(self.domain_sid) + sub_sddl2 = sub_sd2.as_sddl(self.domain_sid) + + self.assertFalse(ou_sddl2 == ou_sddl0) + self.assertFalse(sub_sddl2 == sub_sddl0) + + if ace not in ou_sddl2: + print "ou0: %s" % ou_sddl0 + print "ou2: %s" % ou_sddl2 + + if sub_ace not in sub_sddl2: + print "sub0: %s" % sub_sddl0 + print "sub2: %s" % sub_sddl2 + + self.assertTrue(ace in ou_sddl2) + self.assertTrue(sub_ace in sub_sddl2) + + ou_usn0 = int(ou_res0[0]["uSNChanged"][0]) + ou_usn2 = int(ou_res2[0]["uSNChanged"][0]) + self.assertTrue(ou_usn2 > ou_usn0) + + sub_usn0 = int(sub_res0[0]["uSNChanged"][0]) + sub_usn2 = int(sub_res2[0]["uSNChanged"][0]) + self.assertTrue(sub_usn2 == sub_usn0) + if not "://" in host: if os.path.isfile(host): host = "tdb://%s" % host @@ -1986,4 +2066,6 @@ if not runner.run(unittest.makeSuite(SdFlagsDescriptorTests)).wasSuccessful(): rc = 1 if not runner.run(unittest.makeSuite(RightsAttributesTests)).wasSuccessful(): rc = 1 +if not runner.run(unittest.makeSuite(SdAutoInheritTests)).wasSuccessful(): + rc = 1 sys.exit(rc) -- 1.7.9.5 From 0f6a08cdde02b362d655be972fd18d6242fba722 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 1 Dec 2012 15:10:38 +0100 Subject: [PATCH 33/33] s4:dsdb/descriptor: NULL out user_descriptor elements depending on the sd_flags A client can send a full security_descriptor while just passing sd_flags of SECINFO_DACL. We need to NULL out elements which will be ignored depending on the sd_flags and may set the old owner/group sids. Otherwise the calculation of the DACL/SACL can replace CREATOR_OWNER with the wrong sid. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 8ababf4367eb4faaeeda6cf66191aaf66a3a69da) --- source4/dsdb/samdb/ldb_modules/descriptor.c | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 18caa38..95204b3 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -323,6 +323,50 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module, SEC_DESC_SERVER_SECURITY); } + + if (!(sd_flags & SECINFO_OWNER) && user_descriptor) { + user_descriptor->owner_sid = NULL; + + /* + * We need the correct owner sid + * when calculating the DACL or SACL + */ + if (old_descriptor) { + user_descriptor->owner_sid = old_descriptor->owner_sid; + } + } + if (!(sd_flags & SECINFO_GROUP) && user_descriptor) { + user_descriptor->group_sid = NULL; + + /* + * We need the correct group sid + * when calculating the DACL or SACL + */ + if (old_descriptor) { + user_descriptor->group_sid = old_descriptor->group_sid; + } + } + if (!(sd_flags & SECINFO_DACL) && user_descriptor) { + user_descriptor->dacl = NULL; + + /* + * We add SEC_DESC_DACL_PROTECTED so that + * create_security_descriptor() skips + * the unused inheritance calculation + */ + user_descriptor->type |= SEC_DESC_DACL_PROTECTED; + } + if (!(sd_flags & SECINFO_SACL) && user_descriptor) { + user_descriptor->sacl = NULL; + + /* + * We add SEC_DESC_SACL_PROTECTED so that + * create_security_descriptor() skips + * the unused inheritance calculation + */ + user_descriptor->type |= SEC_DESC_SACL_PROTECTED; + } + default_owner = get_default_ag(mem_ctx, dn, session_info->security_token, ldb); default_group = get_default_group(mem_ctx, ldb, default_owner); -- 1.7.9.5