[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Apr 29 18:05:04 MDT 2012


The branch, master has been updated
       via  773304e s4:samldb LDB module - implement "fSMORoleOwner" attribute protection
       via  cd5d282 s4:dsdb/common/util.c - samdb_is_pdc() - fail if the "fSMORoleOwner" attribute has not been set
      from  b019248 Add some debug for FOOBAR return case as they are hard to diagnose

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


- Log -----------------------------------------------------------------
commit 773304ec8b52d718bd3ca9e1b2543a50d7f4843e
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Apr 21 18:16:43 2012 +0200

    s4:samldb LDB module - implement "fSMORoleOwner" attribute protection
    
    This is a very essential attribute since it references to various domain
    master roles (PDC emulator, schema...) depending on which entry it has
    been set. Incautious modifications can cause severe problems.
    
    Autobuild-User: Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date: Mon Apr 30 02:04:24 CEST 2012 on sn-devel-104

commit cd5d282a466981ce87f180e4828fdef678409194
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Fri Apr 20 18:15:23 2012 +0200

    s4:dsdb/common/util.c - samdb_is_pdc() - fail if the "fSMORoleOwner" attribute has not been set

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

Summary of changes:
 source4/dsdb/common/util.c              |    6 ++-
 source4/dsdb/samdb/ldb_modules/samldb.c |   76 ++++++++++++++++++++++++++++++
 source4/dsdb/tests/python/sam.py        |   77 +++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 1 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 67589ab..6614507 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -1792,7 +1792,11 @@ bool samdb_is_pdc(struct ldb_context *ldb)
 		goto failed;
 	}
 
-	pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner");
+	pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0],
+				      "fSMORoleOwner");
+	if (pdc == NULL) {
+		goto failed;
+	}
 
 	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) {
 		is_pdc = true;
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 390d921..3aa0c23 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -2010,12 +2010,72 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 	return LDB_SUCCESS;
 }
 
+/* This checks the "fSMORoleOwner" attributes */
+static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+	const char * const no_attrs[] = { NULL };
+	struct ldb_message_element *el;
+	struct ldb_message *tmp_msg;
+	struct ldb_dn *res_dn;
+	struct ldb_result *res;
+	int ret;
+
+	el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner",
+					 ac->req->operation);
+	if (el == NULL) {
+		/* we are not affected */
+		return LDB_SUCCESS;
+	}
+
+	/* Create a temporary message for fetching the "fSMORoleOwner" */
+	tmp_msg = ldb_msg_new(ac->msg);
+	if (tmp_msg == NULL) {
+		return ldb_module_oom(ac->module);
+	}
+	ret = ldb_msg_add(tmp_msg, el, 0);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
+	talloc_free(tmp_msg);
+
+	if (res_dn == NULL) {
+		ldb_set_errstring(ldb,
+				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
+		if (ac->req->operation == LDB_ADD) {
+			return LDB_ERR_CONSTRAINT_VIOLATION;
+		} else {
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
+	}
+
+	/* Fetched DN has to reference a "nTDSDSA" entry */
+	ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
+				 no_attrs,
+				 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
+				 ac->req, "(objectClass=nTDSDSA)");
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	if (res->count != 1) {
+		ldb_set_errstring(ldb,
+				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	}
+
+	talloc_free(res);
+
+	return LDB_SUCCESS;
+}
+
 
 /* add */
 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
 {
 	struct ldb_context *ldb;
 	struct samldb_ctx *ac;
+	struct ldb_message_element *el;
 	int ret;
 
 	ldb = ldb_module_get_ctx(module);
@@ -2040,6 +2100,14 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
 		return ldb_operr(ldb);
 	}
 
+	el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
+	if (el != NULL) {
+		ret = samldb_fsmo_role_owner_check(ac);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
+
 	if (samdb_find_attribute(ldb, ac->msg,
 				 "objectclass", "user") != NULL) {
 		ac->type = SAMLDB_TYPE_USER;
@@ -2231,6 +2299,14 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 		}
 	}
 
+	el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
+	if (el != NULL) {
+		ret = samldb_fsmo_role_owner_check(ac);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
+
 	if (modified) {
 		struct ldb_request *child_req;
 
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 7f5b74d..8417b26 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -2607,6 +2607,83 @@ class SamTests(samba.tests.TestCase):
         delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
 
 
+    def test_fSMORoleOwner_attribute(self):
+        """Test fSMORoleOwner attribute"""
+        print "Test fSMORoleOwner attribute"""
+
+        ds_service_name = self.ldb.get_dsServiceName()
+
+        # The "fSMORoleOwner" attribute can only be set to "nTDSDSA" entries,
+        # invalid DNs return ERR_UNWILLING_TO_PERFORM
+
+        try:
+            self.ldb.add({
+                "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+                "objectclass": "group",
+                "fSMORoleOwner": self.base_dn})
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        try:
+            self.ldb.add({
+                "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+                "objectclass": "group",
+                "fSMORoleOwner": [] })
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        # We are able to set it to a valid "nTDSDSA" entry if the server is
+        # capable of handling the role
+
+        self.ldb.add({
+            "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+            "objectclass": "group",
+            "fSMORoleOwner": ds_service_name })
+
+        delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
+        self.ldb.add({
+            "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+            "objectclass": "group" })
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+        m.add(MessageElement(self.base_dn, FLAG_MOD_REPLACE, "fSMORoleOwner"))
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+        m.add(MessageElement([], FLAG_MOD_REPLACE, "fSMORoleOwner"))
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        # We are able to set it to a valid "nTDSDSA" entry if the server is
+        # capable of handling the role
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+        m.add(MessageElement(ds_service_name, FLAG_MOD_REPLACE, "fSMORoleOwner"))
+        ldb.modify(m)
+
+        # A clean-out works on plain entries, not master (schema, PDC...) DNs
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+        m.add(MessageElement([], FLAG_MOD_DELETE, "fSMORoleOwner"))
+        ldb.modify(m)
+
+        delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
+
 if not "://" in host:
     if os.path.isfile(host):
         host = "tdb://%s" % host


-- 
Samba Shared Repository


More information about the samba-cvs mailing list