[SCM] Samba Shared Repository - branch master updated

Nadezhda Ivanova nivanova at samba.org
Fri Nov 20 04:26:15 MST 2009


The branch, master has been updated
       via  7c8b346... Implementation of LDAP_SERVER_SD_FLAGS_OID on modify requests.
      from  a760f16... Some changes to allow processing of ldap controls on modify requests.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 7c8b34657a19c96bbeb2181cd194f323a6827365
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date:   Fri Nov 20 13:25:13 2009 +0200

    Implementation of LDAP_SERVER_SD_FLAGS_OID on modify requests.

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/samdb/ldb_modules/descriptor.c    |  149 +++++++++++++++++++++---
 source4/lib/ldb/tests/python/sec_descriptor.py |  112 +++++++++++++++++-
 2 files changed, 240 insertions(+), 21 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c
index 6a57560..98e54b1 100644
--- a/source4/dsdb/samdb/ldb_modules/descriptor.c
+++ b/source4/dsdb/samdb/ldb_modules/descriptor.c
@@ -154,15 +154,85 @@ static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
 	return NULL;
 }
 
+static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
+							 struct security_descriptor *new_sd,
+							 struct security_descriptor *old_sd,
+							 uint32_t sd_flags)
+{
+	struct security_descriptor *final_sd; 
+	/* if there is no control or contlol == 0 modify everything */
+	if (!sd_flags) {
+		return new_sd;
+	}
+
+	final_sd = talloc_zero(mem_ctx, struct security_descriptor);
+	final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
+	final_sd->type = SEC_DESC_SELF_RELATIVE;
+
+	if (sd_flags & (SECINFO_OWNER)) {
+		final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
+		final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
+	}
+	else if (old_sd) {
+		final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
+		final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
+	}
+
+	if (sd_flags & (SECINFO_GROUP)) {
+		final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
+		final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
+	} 
+	else if (old_sd) {
+		final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
+		final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
+	}
+
+	if (sd_flags & (SECINFO_SACL)) {
+		final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
+		final_sd->type |= new_sd->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);
+	} 
+	else if (old_sd) {
+		final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
+		final_sd->type |= old_sd->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);
+	}
+
+	if (sd_flags & (SECINFO_DACL)) {
+		final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
+		final_sd->type |= new_sd->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);
+	} 
+	else if (old_sd) {
+		final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
+		final_sd->type |= old_sd->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);
+	}
+	/* not so sure about this */
+	final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
+	return final_sd;
+}
+
 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
 				     struct ldb_dn *dn,
 				     TALLOC_CTX *mem_ctx,
 				     const struct dsdb_class *objectclass,
 				     const struct ldb_val *parent,
-				     struct ldb_val *object)
+				     struct ldb_val *object,
+				     struct ldb_val *old_sd,
+				     uint32_t sd_flags)
 {
 	struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
-	struct security_descriptor *new_sd;
+	struct security_descriptor *old_descriptor = NULL;
+	struct security_descriptor *new_sd, *final_sd;
 	DATA_BLOB *linear_sd;
 	enum ndr_err_code ndr_err;
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
@@ -175,13 +245,14 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
 
 	if (object) {
 		user_descriptor = talloc(mem_ctx, struct security_descriptor);
-		if(!user_descriptor)
+		if (!user_descriptor) {
 			return NULL;
+		}
 		ndr_err = ndr_pull_struct_blob(object, user_descriptor, NULL,
 					       user_descriptor,
 					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
 
-		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 			talloc_free(user_descriptor);
 			return NULL;
 		}
@@ -189,19 +260,36 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
 		user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
 	}
 
-	if (parent){
+	if (old_sd) {
+		old_descriptor = talloc(mem_ctx, struct security_descriptor);
+		if (!old_descriptor) {
+			return NULL;
+		}
+		ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor, NULL,
+					       old_descriptor,
+					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			talloc_free(old_descriptor);
+			return NULL;
+		}
+	}
+
+	if (parent) {
 		parent_descriptor = talloc(mem_ctx, struct security_descriptor);
-		if(!parent_descriptor)
+		if (!parent_descriptor) {
 			return NULL;
+		}
 		ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, NULL,
 					       parent_descriptor,
 					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
 
-		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 			talloc_free(parent_descriptor);
 			return NULL;
 		}
 	}
+
 	default_owner = get_default_ag(mem_ctx, dn,
 				       session_info->security_token, ldb);
 	default_group = get_default_group(mem_ctx, ldb, default_owner);
@@ -210,11 +298,15 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
 					    session_info->security_token,
 					    default_owner, default_group,
 					    map_generic_rights_ds);
-	if (!new_sd)
+	if (!new_sd) {
 		return NULL;
+	}
+	final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
 
-
-	sddl_sd = sddl_encode(mem_ctx, new_sd, domain_sid);
+	if (!final_sd) {
+		return NULL;
+	}
+	sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
 	DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
 
 	linear_sd = talloc(mem_ctx, DATA_BLOB);
@@ -224,7 +316,7 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
 
 	ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
 				       lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
-				       new_sd,
+				       final_sd,
 				       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		return NULL;
@@ -383,12 +475,16 @@ static int descriptor_do_mod(struct descriptor_context *ac)
 	struct ldb_context *ldb;
 	const struct dsdb_schema *schema;
 	struct ldb_request *mod_req;
-	struct ldb_message_element *objectclass_element, *tmp_element;
+	struct ldb_message_element *objectclass_element, *tmp_element, *oldsd_el;
+	struct ldb_val *oldsd_val = NULL;
 	int ret;
 	DATA_BLOB *sd;
 	const struct dsdb_class *objectclass;
 	struct ldb_message *msg;
+	struct ldb_control *sd_control;
+	struct ldb_control **saved_controls;
 	int flags = 0;
+	uint32_t sd_flags = 0;
 
 	ldb = ldb_module_get_ctx(ac->module);
 	schema = dsdb_get_schema(ldb);
@@ -402,9 +498,21 @@ static int descriptor_do_mod(struct descriptor_context *ac)
 				       ldb_dn_get_linearized(ac->search_oc_res->message->dn));
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
-
+	sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID);
+	if (sd_control) {
+		struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data;
+		sd_flags = sdctr->secinfo_flags;
+		/* we only care for the last 4 bits */
+		sd_flags = sd_flags & 0x0000000F;
+	}
+	if (sd_flags != 0) {
+		oldsd_el = ldb_msg_find_element(ac->search_oc_res->message, "nTSecurityDescriptor");
+		if (oldsd_el) {
+			oldsd_val = oldsd_el->values;
+		}
+	}
 	sd = get_new_descriptor(ac->module, msg->dn, ac, objectclass,
-				ac->parentsd_val, ac->sd_val);
+				ac->parentsd_val, ac->sd_val, oldsd_val, sd_flags);
 	if (ac->sd_val) {
 		tmp_element = ldb_msg_find_element(msg, "ntSecurityDescriptor");
 		flags = tmp_element->flags;
@@ -427,6 +535,15 @@ static int descriptor_do_mod(struct descriptor_context *ac)
 	if (ret != LDB_SUCCESS) {
 		return ret;
 	}
+	/* save it locally and remove it from the list */
+	/* we do not need to replace them later as we
+	 * are keeping the original req intact */
+	if (sd_control) {
+		if (!save_controls(sd_control, mod_req, &saved_controls)) {
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+	}
+
 	return ldb_next_request(ac->module, mod_req);
 }
 
@@ -441,7 +558,7 @@ static int descriptor_do_add(struct descriptor_context *ac)
 	int ret;
 	DATA_BLOB *sd;
 	const struct dsdb_class *objectclass;
-	static const char *const attrs[] = { "objectClass", NULL };
+	static const char *const attrs[] = { "objectClass", "nTSecurityDescriptor", NULL };
 	struct ldb_request *search_req;
 
 	ldb = ldb_module_get_ctx(ac->module);
@@ -491,7 +608,7 @@ static int descriptor_do_add(struct descriptor_context *ac)
 	/* get the parent descriptor and the one provided. If not provided, get the default.*/
 	/* convert to security descriptor and calculate */
 		sd = get_new_descriptor(ac->module, msg->dn, mem_ctx, objectclass,
-					ac->parentsd_val, ac->sd_val);
+					ac->parentsd_val, ac->sd_val, NULL, 0);
 		if (ac->sd_val) {
 			ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
 		}
diff --git a/source4/lib/ldb/tests/python/sec_descriptor.py b/source4/lib/ldb/tests/python/sec_descriptor.py
index 2770176..8763579 100755
--- a/source4/lib/ldb/tests/python/sec_descriptor.py
+++ b/source4/lib/ldb/tests/python/sec_descriptor.py
@@ -25,7 +25,8 @@ from samba.ndr import ndr_pack, ndr_unpack
 from samba.dcerpc import security
 
 from samba.auth import system_session
-from samba import Ldb, DS_DOMAIN_FUNCTION_2008
+from samba import Ldb, DS_DOMAIN_FUNCTION_2008, SECINFO_OWNER, \
+    SECINFO_GROUP, SECINFO_DACL, SECINFO_SACL
 from subunit import SubunitTestRunner
 import unittest
 
@@ -83,7 +84,7 @@ class DescriptorTests(unittest.TestCase):
     def get_users_domain_dn(self, name):
         return "CN=%s,CN=Users,%s" % (name, self.base_dn)
 
-    def modify_desc(self, _ldb, object_dn, desc):
+    def modify_desc(self, _ldb, object_dn, desc, controls=None):
         assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
         mod = """
 dn: """ + object_dn + """
@@ -94,9 +95,9 @@ replace: nTSecurityDescriptor
             mod += "nTSecurityDescriptor: %s" % desc
         elif isinstance(desc, security.descriptor):
             mod += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
-        _ldb.modify_ldif(mod)
+        _ldb.modify_ldif(mod, controls)
 
-    def create_domain_ou(self, _ldb, ou_dn, desc=None):
+    def create_domain_ou(self, _ldb, ou_dn, desc=None, controls=None):
         ldif = """
 dn: """ + ou_dn + """
 ou: """ + ou_dn.split(",")[0][3:] + """
@@ -109,7 +110,7 @@ url: www.example.com
                 ldif += "nTSecurityDescriptor: %s" % desc
             elif isinstance(desc, security.descriptor):
                 ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
-        _ldb.add_ldif(ldif)
+        _ldb.add_ldif(ldif, controls)
 
     def create_domain_user(self, _ldb, user_dn, desc=None):
         ldif = """
@@ -1683,6 +1684,105 @@ class DaclDescriptorTests(DescriptorTests):
 
     ########################################################################################
 
+
+class SdFlagsDescriptorTests(DescriptorTests):
+    def setUp(self):
+        DescriptorTests.setUp(self)
+        self.test_descr = "O:AUG:AUD:(D;;CC;;;LG)S:(OU;;WP;;;AU)"
+
+    def tearDown(self):
+        self.delete_force(self.ldb_admin, "OU=test_sdflags_ou," + self.base_dn)
+
+    def test_301(self):
+        """ Modify a descriptor with OWNER_SECURITY_INFORMATION set.
+            See that only the owner has been changed.
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:%d" % (SECINFO_OWNER)])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the owner
+        self.assertTrue("O:AU" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertFalse("G:AU" in desc_sddl)
+        self.assertFalse("D:(D;;CC;;;LG)" in desc_sddl)
+        self.assertFalse("(OU;;WP;;;AU)" in desc_sddl)
+
+    def test_302(self):
+        """ Modify a descriptor with GROUP_SECURITY_INFORMATION set.
+            See that only the owner has been changed.
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:%d" % (SECINFO_GROUP)])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the group
+        self.assertTrue("G:AU" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertFalse("O:AU" in desc_sddl)
+        self.assertFalse("D:(D;;CC;;;LG)" in desc_sddl)
+        self.assertFalse("(OU;;WP;;;AU)" in desc_sddl)
+
+    def test_303(self):
+        """ Modify a descriptor with SACL_SECURITY_INFORMATION set.
+            See that only the owner has been changed.
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:%d" % (SECINFO_DACL)])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the DACL
+        self.assertTrue("(D;;CC;;;LG)" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertFalse("O:AU" in desc_sddl)
+        self.assertFalse("G:AU" in desc_sddl)
+        self.assertFalse("(OU;;WP;;;AU)" in desc_sddl)
+
+    def test_304(self):
+        """ Modify a descriptor with SACL_SECURITY_INFORMATION set.
+            See that only the owner has been changed.
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:%d" % (SECINFO_SACL)])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the DACL
+        self.assertTrue("(OU;;WP;;;AU)" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertFalse("O:AU" in desc_sddl)
+        self.assertFalse("G:AU" in desc_sddl)
+        self.assertFalse("(D;;CC;;;LG)" in desc_sddl)
+
+    def test_305(self):
+        """ Modify a descriptor with 0x0 set.
+            Contrary to logic this is interpreted as no control,
+            which is the same as 0xF
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:0"])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the DACL
+        self.assertTrue("(OU;;WP;;;AU)" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertTrue("O:AU" in desc_sddl)
+        self.assertTrue("G:AU" in desc_sddl)
+        self.assertTrue("(D;;CC;;;LG)" in desc_sddl)
+
+    def test_306(self):
+        """ Modify a descriptor with 0xF set.
+        """
+        ou_dn = "OU=test_sdflags_ou," + self.base_dn
+        self.create_domain_ou(self.ldb_admin, ou_dn)
+        self.modify_desc(self.ldb_admin, ou_dn, self.test_descr, controls=["sd_flags:1:15"])
+        desc_sddl = self.get_desc_sddl(ou_dn)
+        # make sure we have modified the DACL
+        self.assertTrue("(OU;;WP;;;AU)" in desc_sddl)
+        # make sure nothing else has been modified
+        self.assertTrue("O:AU" in desc_sddl)
+        self.assertTrue("G:AU" in desc_sddl)
+        self.assertTrue("(D;;CC;;;LG)" in desc_sddl)
+
 if not "://" in host:
     host = "ldap://%s" % host
 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp, options=["modules:paged_searches"])
@@ -1693,5 +1793,7 @@ if not runner.run(unittest.makeSuite(OwnerGroupDescriptorTests)).wasSuccessful()
     rc = 1
 if not runner.run(unittest.makeSuite(DaclDescriptorTests)).wasSuccessful():
     rc = 1
+if not runner.run(unittest.makeSuite(SdFlagsDescriptorTests)).wasSuccessful():
+    rc = 1
 
 sys.exit(rc)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list