[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu May 3 18:35:04 MDT 2012


The branch, master has been updated
       via  c8e6d8b s4-dsdb: Use data_blob_string_const and add explaination for open-coded function in samldb
       via  6250317 s4-dsdb: Use strcasecmp_m() to compare possibly multibyte strings in samldb
       via  d4391f7 s4:samldb LDB module - make sure to not add identical "servicePrincipalName"s more than once
      from  299c13b s3:passdb fix a compiler warning

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


- Log -----------------------------------------------------------------
commit c8e6d8b4875e7dc67734597b6db8e81806d94faa
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri May 4 08:47:29 2012 +1000

    s4-dsdb: Use data_blob_string_const and add explaination for open-coded function in samldb
    
    Autobuild-User: Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date: Fri May  4 02:34:41 CEST 2012 on sn-devel-104

commit 62503179b5f3e8efe22abcf3b30ddb795db5d8c9
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri May 4 08:46:57 2012 +1000

    s4-dsdb: Use strcasecmp_m() to compare possibly multibyte strings in samldb

commit d4391f77bf54ae94de9715bfbefcd545c556e55c
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Thu May 3 22:55:06 2012 +0200

    s4:samldb LDB module - make sure to not add identical "servicePrincipalName"s more than once
    
    The service principal names need to be case-insensitively unique, otherwise we
    end up in a LDB ERR_ATTRIBUTE_OR_VALUE_EXISTS error.
    This issue has been discovered on the technical mailing list (thread:
    cannot rename windows xp machine in samba4) when trying to rename a AD
    client workstation.

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/samldb.c |   63 +++++++++++++++++++++++--------
 source4/dsdb/tests/python/sam.py        |   51 +++++++++++++++++++++++--
 2 files changed, 94 insertions(+), 20 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 168e55b..41c97bf 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1816,7 +1816,7 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 	struct ldb_result *res;
 	const char *dns_hostname = NULL, *old_dns_hostname = NULL,
 		   *sam_accountname = NULL, *old_sam_accountname = NULL;
-	unsigned int i;
+	unsigned int i, j;
 	int ret;
 
 	el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
@@ -1895,7 +1895,7 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 		dns_hostname = NULL;
 	}
 	if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
-	    (strcasecmp(old_dns_hostname, dns_hostname) == 0)) {
+	    (strcasecmp_m(old_dns_hostname, dns_hostname) == 0)) {
 		/* The "dNSHostName" didn't change */
 		dns_hostname = NULL;
 	}
@@ -1905,7 +1905,7 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 		sam_accountname = NULL;
 	}
 	if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
-	    (strcasecmp(old_sam_accountname, sam_accountname) == 0)) {
+	    (strcasecmp_m(old_sam_accountname, sam_accountname) == 0)) {
 		/* The "sAMAccountName" didn't change */
 		sam_accountname = NULL;
 	}
@@ -1957,15 +1957,28 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 	}
 
 	if (res->msgs[0]->num_elements == 1) {
-		/* Yes, we do have "servicePrincipalName"s. First we update them
+		/*
+		 * Yes, we do have "servicePrincipalName"s. First we update them
 		 * locally, that means we do always substitute the current
 		 * "dNSHostName" with the new one and/or "sAMAccountName"
-		 * without "$" with the new one and then we append this to the
-		 * modification request (Windows behaviour). */
+		 * without "$" with the new one and then we append the
+		 * modified "servicePrincipalName"s as a message element
+		 * replace to the modification request (Windows behaviour). We
+		 * need also to make sure that the values remain case-
+		 * insensitively unique.
+		 */
+
+		ret = ldb_msg_add_empty(ac->msg, "servicePrincipalName",
+					LDB_FLAG_MOD_REPLACE, &el);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
 
 		for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
 			char *old_str, *new_str, *pos;
 			const char *tok;
+			struct ldb_val *vals;
+			bool found = false;
 
 			old_str = (char *)
 				res->msgs[0]->elements[0].values[i].data;
@@ -1978,11 +1991,11 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 
 			while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
 				if ((dns_hostname != NULL) &&
-				    (strcasecmp(tok, old_dns_hostname) == 0)) {
+				    (strcasecmp_m(tok, old_dns_hostname) == 0)) {
 					tok = dns_hostname;
 				}
 				if ((sam_accountname != NULL) &&
-				    (strcasecmp(tok, old_sam_accountname) == 0)) {
+				    (strcasecmp_m(tok, old_sam_accountname) == 0)) {
 					tok = sam_accountname;
 				}
 
@@ -1993,16 +2006,34 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 				}
 			}
 
-			ret = ldb_msg_add_string(ac->msg,
-						 "servicePrincipalName",
-						 new_str);
-			if (ret != LDB_SUCCESS) {
-				return ret;
+			/* Uniqueness check */
+			for (j = 0; (!found) && (j < el->num_values); j++) {
+				if (strcasecmp_m((char *)el->values[j].data,
+					       new_str) == 0) {
+					found = true;
+				}
+			}
+			if (found) {
+				continue;
 			}
-		}
 
-		el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
-		el->flags = LDB_FLAG_MOD_REPLACE;
+			/*
+			 * append the new "servicePrincipalName" -
+			 * code derived from ldb_msg_add_value().
+			 *
+			 * Open coded to make it clear that we must
+			 * append to the MOD_REPLACE el created above.
+			 */
+			vals = talloc_realloc(ac->msg, el->values,
+					      struct ldb_val,
+					      el->num_values + 1);
+			if (vals == NULL) {
+				return ldb_module_oom(ac->module);
+			}
+			el->values = vals;
+			el->values[el->num_values] = data_blob_string_const(new_str);
+			++(el->num_values);
+		}
 	}
 
 	talloc_free(res);
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 8417b26..c5727cd 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -2432,10 +2432,53 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(len(res) == 1)
         self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
         self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
-        self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2" or
-                        res[0]["servicePrincipalName"][1] == "HOST/testname2")
-        self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2.testdom" or
-                        res[0]["servicePrincipalName"][1] == "HOST/testname2.testdom")
+        self.assertTrue(len(res[0]["servicePrincipalName"]) == 2)
+        self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
+        self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+        m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom",
+                                                   FLAG_MOD_ADD, "servicePrincipalName")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+        m["servicePrincipalName"] = MessageElement("HOST/testname3",
+                                                   FLAG_MOD_ADD, "servicePrincipalName")
+        ldb.modify(m)
+
+        res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
+                         scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
+        self.assertTrue(len(res) == 1)
+        self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
+        self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
+        self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
+        self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
+        self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
+        self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+        m["dNSHostName"] = MessageElement("testname3.testdom",
+                                          FLAG_MOD_REPLACE, "dNSHostName")
+        m["servicePrincipalName"] = MessageElement("HOST/testname3.testdom",
+                                                   FLAG_MOD_ADD, "servicePrincipalName")
+        ldb.modify(m)
+
+        res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
+                         scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
+        self.assertTrue(len(res) == 1)
+        self.assertEquals(res[0]["dNSHostName"][0], "testname3.testdom")
+        self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
+        self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
+        self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
+        self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
+        self.assertTrue("HOST/testname3.testdom" in res[0]["servicePrincipalName"])
 
         delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list