[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Mon Nov 8 05:10:02 MST 2010


The branch, master has been updated
       via  58cfa5a s4:passwords.py - test empty password attributes behaviour
       via  0bfbf6d s4:password_hash LDB module - deleting password attributes is a little more complicated
       via  9154d4d s4:samdb_msg_find_old_and_new_ldb_val - rework
       via  6041ef7 s4:password_hash LDB module - clear the fact that a delete of password attributes isn't possible
       via  d4c9a34 s4:acl LDB module - define the delete passwords special case a bit better
       via  acffe25 s4:passwords.py - add another two failure cases
      from  9aa0ed2 ldb:pyldb.c - "py_ldb_msg_element_get" - here we can safely use "unsigned int" for the element reference

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


- Log -----------------------------------------------------------------
commit 58cfa5a82519e2850cb400bb9f1e76d3dbfd3ff2
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Mon Nov 1 19:54:07 2010 +0100

    s4:passwords.py - test empty password attributes behaviour
    
    Autobuild-User: Matthias Dieter Wallnöfer <mdw at samba.org>
    Autobuild-Date: Mon Nov  8 12:09:56 UTC 2010 on sn-devel-104

commit 0bfbf6d5264fb45d9b788a9dabad18826db1a875
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Mon Nov 8 11:33:53 2010 +0100

    s4:password_hash LDB module - deleting password attributes is a little more complicated

commit 9154d4dcfc142c0a549993f2e1083eb52a759213
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sun Nov 7 22:08:19 2010 +0100

    s4:samdb_msg_find_old_and_new_ldb_val - rework
    
    - don't crash when no values where specified
    - return ERR_CONSTRAINT_VIOLATION on malformed messages
    - only check for flags when we are involved in a LDB modify operation

commit 6041ef7442fda2f96c416d333f1dfc6dabd0d252
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Mon Nov 8 11:31:16 2010 +0100

    s4:password_hash LDB module - clear the fact that a delete of password attributes isn't possible

commit d4c9a34cf82abea5497dc2a8072ed2a67894e0ea
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sun Nov 7 22:37:39 2010 +0100

    s4:acl LDB module - define the delete passwords special case a bit better

commit acffe258960c261903eefce630bbf02acbef1348
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sun Nov 7 22:35:29 2010 +0100

    s4:passwords.py - add another two failure cases

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

Summary of changes:
 source4/dsdb/common/util.c                     |   33 ++++-
 source4/dsdb/samdb/ldb_modules/acl.c           |    7 +-
 source4/dsdb/samdb/ldb_modules/password_hash.c |   29 +++--
 source4/dsdb/tests/python/passwords.py         |  176 +++++++++++++++++++++++-
 4 files changed, 224 insertions(+), 21 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 3fa6774..79a4c14 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -709,12 +709,13 @@ struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
  * for entries). The latter (old value) has always specified
  * LDB_FLAG_MOD_DELETE.
  *
- * Returns LDB_ERR_NO_SUCH_ATTRIBUTE if the attribute which should be deleted
- * doesn't contain only one value (this is the Windows Server behaviour)
- * otherwise LDB_SUCCESS.
+ * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
+ * matching message elements are malformed in respect to the set/change rules.
+ * Otherwise it returns LDB_SUCCESS.
  */
 int samdb_msg_find_old_and_new_ldb_val(const struct ldb_message *msg,
 				       const char *name,
+				       enum ldb_request_type operation,
 				       const struct ldb_val **new_val,
 				       const struct ldb_val **old_val)
 {
@@ -728,11 +729,31 @@ int samdb_msg_find_old_and_new_ldb_val(const struct ldb_message *msg,
 	}
 
 	for (i = 0; i < msg->num_elements; i++) {
-		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
-			if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE) {
+		if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
+			continue;
+		}
+
+		if ((operation == LDB_MODIFY) &&
+		    (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
+			/* 0 values are allowed */
+			if (msg->elements[i].num_values == 1) {
 				*old_val = &msg->elements[i].values[0];
+			} else if (msg->elements[i].num_values > 1) {
+				return LDB_ERR_CONSTRAINT_VIOLATION;
+			}
+		} else if ((operation == LDB_MODIFY) &&
+			   (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
+			if (msg->elements[i].num_values > 0) {
+				*new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
+			} else {
+				return LDB_ERR_UNWILLING_TO_PERFORM;
+			}
+		} else {
+			/* Add operations and LDB_FLAG_MOD_ADD */
+			if (msg->elements[i].num_values > 0) {
+				*new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
 			} else {
-				*new_val = &msg->elements[i].values[0];
+				return LDB_ERR_CONSTRAINT_VIOLATION;
 			}
 		}
 	}
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 0a7f431..3cf768e 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -570,9 +570,10 @@ static int acl_check_password_rights(TALLOC_CTX *mem_ctx,
 			ldb_msg_remove_element(msg, el);
 		}
 	}
-	/* a single delete will be handled by password hash
-	   later in the stack, so we let it though here */
-	if (del_attr_cnt > 0 && add_attr_cnt == 0) {
+
+	/* single deletes will be handled by the "password_hash" LDB module
+	 * later in the stack, so we let it though here */
+	if ((del_attr_cnt > 0) && (add_attr_cnt == 0) && (rep_attr_cnt == 0)) {
 		talloc_free(tmp_ctx);
 		return LDB_SUCCESS;
 	}
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 7b02479..731b8e9 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -1687,7 +1687,9 @@ static int setup_io(struct ph_context *ac,
 	}
 
 	ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "userPassword",
-		&io->n.cleartext_utf8, &io->og.cleartext_utf8);
+						 ac->req->operation,
+						 &io->n.cleartext_utf8,
+						 &io->og.cleartext_utf8);
 	if (ret != LDB_SUCCESS) {
 		ldb_asprintf_errstring(ldb,
 			"setup_io: "
@@ -1696,7 +1698,9 @@ static int setup_io(struct ph_context *ac,
 	}
 
 	ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "clearTextPassword",
-		&io->n.cleartext_utf16, &io->og.cleartext_utf16);
+						 ac->req->operation,
+						 &io->n.cleartext_utf16,
+						 &io->og.cleartext_utf16);
 	if (ret != LDB_SUCCESS) {
 		ldb_asprintf_errstring(ldb,
 			"setup_io: "
@@ -1718,7 +1722,9 @@ static int setup_io(struct ph_context *ac,
 	   a nthash */
 
 	ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "unicodePwd",
-		&quoted_utf16, &old_quoted_utf16);
+						 ac->req->operation,
+						 &quoted_utf16,
+						 &old_quoted_utf16);
 	if (ret != LDB_SUCCESS) {
 		ldb_asprintf_errstring(ldb,
 			"setup_io: "
@@ -1833,7 +1839,8 @@ static int setup_io(struct ph_context *ac,
 	/* Handles the "dBCSPwd" attribute (LM hash) */
 	io->n.lm_hash = NULL; io->og.lm_hash = NULL;
 	ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "dBCSPwd",
-		&lm_hash, &old_lm_hash);
+						 ac->req->operation,
+						 &lm_hash, &old_lm_hash);
 	if (ret != LDB_SUCCESS) {
 		ldb_asprintf_errstring(ldb,
 			"setup_io: "
@@ -1908,7 +1915,13 @@ static int setup_io(struct ph_context *ac,
 	    && (!io->n.nt_hash) && (!io->n.lm_hash)) {
 		ldb_asprintf_errstring(ldb,
 			"setup_io: "
-			"The password change/set operations performed using the LAN Manager hash alone are deactivated!");
+			"It' not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
+		/* on "userPassword" and "clearTextPassword" we've to return
+		 * something different, since these are virtual attributes */
+		if ((ldb_msg_find_element(orig_msg, "userPassword") != NULL) ||
+		    (ldb_msg_find_element(orig_msg, "clearTextPassword") != NULL)) {
+			return LDB_ERR_CONSTRAINT_VIOLATION;
+		}
 		return LDB_ERR_UNWILLING_TO_PERFORM;
 	}
 
@@ -2507,12 +2520,6 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
 			ldb_msg_remove_element(msg, passwordAttr);
 		}
 	}
-	if ((del_attr_cnt > 0) && (add_attr_cnt == 0)) {
-		talloc_free(ac);
-		ldb_set_errstring(ldb,
-				  "Only the delete action for a password change specified!");
-		return LDB_ERR_CONSTRAINT_VIOLATION;
-	}
 	if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
 		talloc_free(ac);
 		ldb_set_errstring(ldb,
diff --git a/source4/dsdb/tests/python/passwords.py b/source4/dsdb/tests/python/passwords.py
index 66a6cf9..bb2fbd5 100755
--- a/source4/dsdb/tests/python/passwords.py
+++ b/source4/dsdb/tests/python/passwords.py
@@ -28,7 +28,7 @@ from ldb import ERR_UNWILLING_TO_PERFORM, ERR_INSUFFICIENT_ACCESS_RIGHTS
 from ldb import ERR_NO_SUCH_ATTRIBUTE
 from ldb import ERR_CONSTRAINT_VIOLATION
 from ldb import Message, MessageElement, Dn
-from ldb import FLAG_MOD_REPLACE, FLAG_MOD_DELETE
+from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
 from samba import gensec
 from samba.samdb import SamDB
 import samba.tests
@@ -402,6 +402,27 @@ userPassword: thatsAcomplPASS1
 dn: cn=testuser,cn=users,""" + self.base_dn + """
 changetype: modify
 delete: userPassword
+userPassword: thatsAcomplPASS1
+""")
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        try:
+            ldb.modify_ldif("""
+dn: cn=testuser,cn=users,""" + self.base_dn + """
+changetype: modify
+delete: userPassword
+""")
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        try:
+            self.ldb2.modify_ldif("""
+dn: cn=testuser,cn=users,""" + self.base_dn + """
+changetype: modify
+delete: userPassword
 """)
             self.fail()
         except LdbError, (num, _):
@@ -647,6 +668,159 @@ userPassword: thatsAcomplPASS4
              "objectclass": "user",
              "userPassword": ["thatsAcomplPASS1", "thatsAcomplPASS1"] })
 
+    def test_empty_passwords(self):
+        print "Performs some empty passwords testing"
+
+        try:
+            self.ldb.add({
+                 "dn": "cn=testuser2,cn=users," + self.base_dn,
+                 "objectclass": "user",
+                 "unicodePwd": [] })
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        try:
+            self.ldb.add({
+                 "dn": "cn=testuser2,cn=users," + self.base_dn,
+                 "objectclass": "user",
+                 "dBCSPwd": [] })
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        try:
+            self.ldb.add({
+                 "dn": "cn=testuser2,cn=users," + self.base_dn,
+                 "objectclass": "user",
+                 "userPassword": [] })
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        try:
+            self.ldb.add({
+                 "dn": "cn=testuser2,cn=users," + self.base_dn,
+                 "objectclass": "user",
+                 "clearTextPassword": [] })
+            self.fail()
+        except LdbError, (num, _):
+            self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or
+                            num == ERR_NO_SUCH_ATTRIBUTE) # for Windows
+
+        self.delete_force(self.ldb, "cn=testuser2,cn=users," + self.base_dn)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["unicodePwd"] = MessageElement([], FLAG_MOD_ADD, "unicodePwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["dBCSPwd"] = MessageElement([], FLAG_MOD_ADD, "dBCSPwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["userPassword"] = MessageElement([], FLAG_MOD_ADD, "userPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["clearTextPassword"] = MessageElement([], FLAG_MOD_ADD, "clearTextPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or
+                            num == ERR_NO_SUCH_ATTRIBUTE) # for Windows
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["unicodePwd"] = MessageElement([], FLAG_MOD_REPLACE, "unicodePwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["dBCSPwd"] = MessageElement([], FLAG_MOD_REPLACE, "dBCSPwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["userPassword"] = MessageElement([], FLAG_MOD_REPLACE, "userPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["clearTextPassword"] = MessageElement([], FLAG_MOD_REPLACE, "clearTextPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertTrue(num == ERR_UNWILLING_TO_PERFORM or
+                            num == ERR_NO_SUCH_ATTRIBUTE) # for Windows
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["unicodePwd"] = MessageElement([], FLAG_MOD_DELETE, "unicodePwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["dBCSPwd"] = MessageElement([], FLAG_MOD_DELETE, "dBCSPwd")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["userPassword"] = MessageElement([], FLAG_MOD_DELETE, "userPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn)
+        m["clearTextPassword"] = MessageElement([], FLAG_MOD_DELETE, "clearTextPassword")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or
+                            num == ERR_NO_SUCH_ATTRIBUTE) # for Windows
+
     def tearDown(self):
         super(PasswordTests, self).tearDown()
         self.delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list