[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Sat Nov 13 05:38:02 MST 2010


The branch, master has been updated
       via  7d2260c s4:password_hash LDB module - return "ERR_CONSTRAINT_VIOLATION" on password conversion errors
       via  ac0dcd1 s4:upgradeprovision - why not directly use "provision:0"?
       via  113a9c1 s4:objectclass LDB module - multiple "objectClass" change elements are unfortunately still allowed
      from  b9cfe10 s4-drs: fixed a crash in writspn

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


- Log -----------------------------------------------------------------
commit 7d2260cdd18b7354c372d6e8833d1554ab7894d0
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Nov 13 12:47:53 2010 +0100

    s4:password_hash LDB module - return "ERR_CONSTRAINT_VIOLATION" on password conversion errors
    
    This errors can happen also on a regular basis - then we shouldn't return
    ERR_OPERATIONS_ERROR (this error code is reserved for very serious failures).
    
    Autobuild-User: Matthias Dieter Wallnöfer <mdw at samba.org>
    Autobuild-Date: Sat Nov 13 12:37:36 UTC 2010 on sn-devel-104

commit ac0dcd1e07e8f2642c01912d9dfbc457a18fdfae
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Nov 13 12:33:26 2010 +0100

    s4:upgradeprovision - why not directly use "provision:0"?

commit 113a9c1806863f9794c3a611ed4c4d910c3bf11b
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Nov 13 12:25:40 2010 +0100

    s4:objectclass LDB module - multiple "objectClass" change elements are unfortunately still allowed
    
    The test message has been compressed - therefore I've now used "modify_ldif".

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/objectclass.c   |  330 ++++++++++++------------
 source4/dsdb/samdb/ldb_modules/password_hash.c |   15 +-
 source4/dsdb/tests/python/ldap.py              |   21 +-
 source4/scripting/bin/upgradeprovision         |    8 +-
 4 files changed, 191 insertions(+), 183 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index d2b4f10..e863d48 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -921,7 +921,7 @@ static int objectclass_do_mod(struct oc_context *ac)
 	TALLOC_CTX *mem_ctx;
 	struct class_list *sorted, *current;
 	const struct dsdb_class *objectclass;
-	unsigned int i, j;
+	unsigned int i, j, k;
 	bool found, replace = false;
 	int ret;
 
@@ -939,13 +939,6 @@ static int objectclass_do_mod(struct oc_context *ac)
 		return ldb_operr(ldb);
 	}
 
-	oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
-					    "objectClass");
-	if (oc_el_change == NULL) {
-		/* we should have an objectclass change operation */
-		return ldb_operr(ldb);
-	}
-
 	/* use a new message structure */
 	msg = ldb_msg_new(ac);
 	if (msg == NULL) {
@@ -959,195 +952,210 @@ static int objectclass_do_mod(struct oc_context *ac)
 		return ldb_oom(ldb);
 	}
 
-	switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
-	case LDB_FLAG_MOD_ADD:
-		/* Merge the two message elements */
-		for (i = 0; i < oc_el_change->num_values; i++) {
-			for (j = 0; j < oc_el_entry->num_values; j++) {
-				if (strcasecmp((char *)oc_el_change->values[i].data,
-					       (char *)oc_el_entry->values[j].data) == 0) {
-					/* we cannot add an already existing object class */
+	/* We've to walk over all "objectClass" message elements */
+	for (k = 0; k < ac->req->op.mod.message->num_elements; k++) {
+		if (ldb_attr_cmp(ac->req->op.mod.message->elements[k].name,
+				 "objectClass") != 0) {
+			continue;
+		}
+
+		oc_el_change = &ac->req->op.mod.message->elements[k];
+
+		switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
+		case LDB_FLAG_MOD_ADD:
+			/* Merge the two message elements */
+			for (i = 0; i < oc_el_change->num_values; i++) {
+				for (j = 0; j < oc_el_entry->num_values; j++) {
+					if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
+							 (char *)oc_el_entry->values[j].data) == 0) {
+						ldb_asprintf_errstring(ldb,
+								       "objectclass: cannot re-add an existing objectclass: '%.*s'!",
+								       (int)oc_el_change->values[i].length,
+								       (const char *)oc_el_change->values[i].data);
+						talloc_free(mem_ctx);
+						return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+					}
+				}
+				/* append the new object class value - code was
+				 * copied from "ldb_msg_add_value" */
+				vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
+						      struct ldb_val,
+						      oc_el_entry->num_values + 1);
+				if (vals == NULL) {
 					talloc_free(mem_ctx);
-					return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+					return ldb_oom(ldb);
 				}
+				oc_el_entry->values = vals;
+				oc_el_entry->values[oc_el_entry->num_values] =
+							oc_el_change->values[i];
+				++(oc_el_entry->num_values);
 			}
-			/* append the new object class value - code was copied
-			 * from "ldb_msg_add_value" */
-			vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
-					      struct ldb_val,
-					      oc_el_entry->num_values + 1);
-			if (vals == NULL) {
+
+			objectclass = get_last_structural_class(ac->schema,
+								oc_el_change);
+			if (objectclass != NULL) {
+				ldb_asprintf_errstring(ldb,
+						       "objectclass: cannot add a new top-most structural objectclass '%s'!",
+						       objectclass->lDAPDisplayName);
 				talloc_free(mem_ctx);
-				return ldb_oom(ldb);
+				return LDB_ERR_OBJECT_CLASS_VIOLATION;
 			}
-			oc_el_entry->values = vals;
-			oc_el_entry->values[oc_el_entry->num_values] =
-				oc_el_change->values[i];
-			++(oc_el_entry->num_values);
-		}
 
-		objectclass = get_last_structural_class(ac->schema,
-							oc_el_change);
-		if (objectclass != NULL) {
-			/* we cannot add a new structural object class */
-			talloc_free(mem_ctx);
-			return LDB_ERR_OBJECT_CLASS_VIOLATION;
-		}
+			/* Now do the sorting */
+			ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
+					       oc_el_entry, &sorted);
+			if (ret != LDB_SUCCESS) {
+				talloc_free(mem_ctx);
+				return ret;
+			}
 
-		/* Now do the sorting */
-		ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
-				       oc_el_entry, &sorted);
-		if (ret != LDB_SUCCESS) {
-			talloc_free(mem_ctx);
-			return ret;
-		}
+			break;
 
-		break;
+		case LDB_FLAG_MOD_REPLACE:
+			/* Do the sorting for the change message element */
+			ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
+					       oc_el_change, &sorted);
+			if (ret != LDB_SUCCESS) {
+				talloc_free(mem_ctx);
+				return ret;
+			}
 
-	case LDB_FLAG_MOD_REPLACE:
-		/* Do the sorting for the change message element */
-		ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
-				       oc_el_change, &sorted);
-		if (ret != LDB_SUCCESS) {
-			talloc_free(mem_ctx);
-			return ret;
-		}
+			/* this is a replace */
+			replace = true;
 
-		/* this is a replace */
-		replace = true;
+			break;
 
-		break;
+		case LDB_FLAG_MOD_DELETE:
+			/* get the actual top-most structural objectclass */
+			objectclass = get_last_structural_class(ac->schema,
+								oc_el_entry);
+			if (objectclass == NULL) {
+				talloc_free(mem_ctx);
+				return ldb_operr(ldb);
+			}
 
-	case LDB_FLAG_MOD_DELETE:
-		/* get the actual top-most structural objectclass */
-		objectclass = get_last_structural_class(ac->schema,
-							oc_el_entry);
-		if (objectclass == NULL) {
-			talloc_free(mem_ctx);
-			return ldb_operr(ldb);
-		}
+			/* Merge the two message elements */
+			for (i = 0; i < oc_el_change->num_values; i++) {
+				found = false;
+				for (j = 0; j < oc_el_entry->num_values; j++) {
+					if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
+							 (char *)oc_el_entry->values[j].data) == 0) {
+						found = true;
+						/* delete the object class value
+						 * - code was copied from
+						 * "ldb_msg_remove_element" */
+						if (j != oc_el_entry->num_values - 1) {
+							memmove(&oc_el_entry->values[j],
+								&oc_el_entry->values[j+1],
+								((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
+						}
+						--(oc_el_entry->num_values);
+						break;
+					}
+				}
+				if (!found) {
+					/* we cannot delete a not existing
+					 * object class */
+					ldb_asprintf_errstring(ldb,
+							       "objectclass: cannot delete this objectclass: '%.*s'!",
+							       (int)oc_el_change->values[i].length,
+							       (const char *)oc_el_change->values[i].data);
+					talloc_free(mem_ctx);
+					return LDB_ERR_NO_SUCH_ATTRIBUTE;
+				}
+			}
 
-		/* Merge the two message elements */
-		for (i = 0; i < oc_el_change->num_values; i++) {
+			/* Make sure that the top-most structural object class
+			 * hasn't been deleted */
 			found = false;
-			for (j = 0; j < oc_el_entry->num_values; j++) {
-				if (strcasecmp((char *)oc_el_change->values[i].data,
-					       (char *)oc_el_entry->values[j].data) == 0) {
+			for (i = 0; i < oc_el_entry->num_values; i++) {
+				if (ldb_attr_cmp(objectclass->lDAPDisplayName,
+						 (char *)oc_el_entry->values[i].data) == 0) {
 					found = true;
-					/* delete the object class value -
-					 * code was copied from
-					 * "ldb_msg_remove_element" */
-					if (j != oc_el_entry->num_values - 1) {
-						memmove(&oc_el_entry->values[j],
-							&oc_el_entry->values[j+1],
-							((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
-					}
-					--(oc_el_entry->num_values);
 					break;
 				}
 			}
 			if (!found) {
-				/* we cannot delete a not existing object class */
-				ldb_asprintf_errstring(ldb, "Cannot delete this %.*s ",
-					       (int)oc_el_change->values[i].length, (const char *)oc_el_change->values[i].data);
-
+				ldb_asprintf_errstring(ldb,
+						       "objectclass: cannot delete the top-most structural objectclass '%s'!",
+						       objectclass->lDAPDisplayName);
 				talloc_free(mem_ctx);
-				return LDB_ERR_NO_SUCH_ATTRIBUTE;
+				return LDB_ERR_OBJECT_CLASS_VIOLATION;
 			}
-		}
 
-		/* Make sure that the top-most structural objectclass wasn't
-		 * deleted */
-		found = false;
-		for (i = 0; i < oc_el_entry->num_values; i++) {
-			if (strcasecmp(objectclass->lDAPDisplayName,
-			    (char *)oc_el_entry->values[i].data) == 0) {
-				found = true; break;
+			/* Now do the sorting */
+			ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
+					       oc_el_entry, &sorted);
+			if (ret != LDB_SUCCESS) {
+				talloc_free(mem_ctx);
+				return ret;
 			}
-		}
-		if (!found) {
-			talloc_free(mem_ctx);
-			return LDB_ERR_OBJECT_CLASS_VIOLATION;
-		}
 
+			break;
+		}
 
-		/* Now do the sorting */
-		ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
-				       oc_el_entry, &sorted);
+		/* (Re)-add an empty "objectClass" attribute on the object
+		 * classes change message "msg". */
+		ldb_msg_remove_attr(msg, "objectClass");
+		ret = ldb_msg_add_empty(msg, "objectClass",
+					LDB_FLAG_MOD_REPLACE, &oc_el_change);
 		if (ret != LDB_SUCCESS) {
 			talloc_free(mem_ctx);
-			return ret;
+			return ldb_oom(ldb);
 		}
 
-		break;
-	}
-
-	/* Only one "objectclass" attribute change element per modify request
-	 * allowed! */
-	for (i = 0; i < ac->req->op.mod.message->num_elements; i++) {
-		if (ldb_attr_cmp(ac->req->op.mod.message->elements[i].name,
-				 "objectClass") != 0) continue;
-
-		if (ldb_msg_element_compare(&ac->req->op.mod.message->elements[i],
-					    oc_el_change) != 0) {
-			ldb_set_errstring(ldb,
-					  "objectclass: only one 'objectClass' attribute change per modify request allowed!");
-			talloc_free(mem_ctx);
-			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+		/* Move from the linked list back into an ldb msg */
+		for (current = sorted; current; current = current->next) {
+			value = talloc_strdup(msg,
+					      current->objectclass->lDAPDisplayName);
+			if (value == NULL) {
+				talloc_free(mem_ctx);
+				return ldb_oom(ldb);
+			}
+			ret = ldb_msg_add_string(msg, "objectClass", value);
+			if (ret != LDB_SUCCESS) {
+				ldb_set_errstring(ldb,
+						  "objectclass: could not re-add sorted objectclasses!");
+				talloc_free(mem_ctx);
+				return ret;
+			}
 		}
-	}
 
-	ret = ldb_msg_add_empty(msg, "objectClass",
-				LDB_FLAG_MOD_REPLACE, &oc_el_change);
-	if (ret != LDB_SUCCESS) {
-		talloc_free(mem_ctx);
-		return ldb_oom(ldb);
-	}
-
-	/* Move from the linked list back into an ldb msg */
-	for (current = sorted; current; current = current->next) {
-		value = talloc_strdup(msg,
-				      current->objectclass->lDAPDisplayName);
-		if (value == NULL) {
-			talloc_free(mem_ctx);
-			return ldb_oom(ldb);
-		}
-		ret = ldb_msg_add_string(msg, "objectClass", value);
-		if (ret != LDB_SUCCESS) {
-			ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
-			talloc_free(mem_ctx);
-			return ret;
+		if (replace) {
+			/* Well, on replace we are nearly done: we have to test
+			 * if the change and entry message element are identical
+			 * ly. We can use "ldb_msg_element_compare" since now
+			 * the specified objectclasses match for sure in case.
+			 */
+			ret = ldb_msg_element_compare(oc_el_entry,
+						      oc_el_change);
+			if (ret == 0) {
+				ret = ldb_msg_element_compare(oc_el_change,
+							      oc_el_entry);
+			}
+			if (ret == 0) {
+				/* they are the same so we are done in this
+				 * case */
+				talloc_free(mem_ctx);
+				return ldb_module_done(ac->req, NULL, NULL,
+						       LDB_SUCCESS);
+			} else {
+				ldb_set_errstring(ldb,
+						  "objectclass: the specified objectclasses are not exactly the same as on the entry!");
+				talloc_free(mem_ctx);
+				return LDB_ERR_OBJECT_CLASS_VIOLATION;
+			}
 		}
-	}
-
-	talloc_free(mem_ctx);
 
-	if (replace) {
-		/* Well, on replace we are nearly done: we have to test if
-		 * the change and entry message element are identically. We
-		 * can use "ldb_msg_element_compare" since now the specified
-		 * objectclasses match for sure in case. */
-		ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
-		if (ret == 0) {
-			ret = ldb_msg_element_compare(oc_el_change,
-						      oc_el_entry);
-		}
-		if (ret == 0) {
-			/* they are the same so we are done in this case */
-			return ldb_module_done(ac->req, NULL, NULL,
-					       LDB_SUCCESS);
-		} else {
-			/* they're not exactly the same */
-			return LDB_ERR_OBJECT_CLASS_VIOLATION;
-		}
+		/* Now we've applied all changes from "oc_el_change" to
+		 * "oc_el_entry" therefore the new "oc_el_entry" will be
+		 * "oc_el_change". */
+		oc_el_entry = oc_el_change;
 	}
 
-	/* in the other cases we have the real change left to do */
+	talloc_free(mem_ctx);
 
-	ret = ldb_msg_sanity_check(ldb, msg);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
+	/* Now we have the real and definitive change left to do */
 
 	ret = ldb_build_mod_req(&mod_req, ldb, ac,
 				msg,
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 1d09f4d..b218a57 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -1301,12 +1301,14 @@ static int setup_given_passwords(struct setup_password_fields_io *io,
 					   (void *)&cleartext_utf16_blob->data,
 					   &cleartext_utf16_blob->length,
 					   false)) {
+			talloc_free(cleartext_utf16_blob);
 			ldb_asprintf_errstring(ldb,
-				"setup_password_fields: "
-				"failed to generate UTF16 password from cleartext UTF8 password");
-			return LDB_ERR_OPERATIONS_ERROR;
+					       "setup_password_fields: "
+					       "failed to generate UTF16 password from cleartext UTF8 password for user %s", io->u.sAMAccountName);
+			return LDB_ERR_CONSTRAINT_VIOLATION;
+		} else {
+			g->cleartext_utf16 = cleartext_utf16_blob;
 		}
-		g->cleartext_utf16 = cleartext_utf16_blob;
 	} else if (g->cleartext_utf16) {
 		char *cleartext_utf8_str;
 		struct ldb_val *cleartext_utf8_blob;
@@ -1322,12 +1324,13 @@ static int setup_given_passwords(struct setup_password_fields_io *io,
 					   g->cleartext_utf16->length,
 					   (void *)&cleartext_utf8_str,
 					   &converted_pw_len, false)) {
-			/* We must bail out here, the input wasn't even a multiple of 2 bytes */
+			/* We must bail out here, the input wasn't even a
+			 * multiple of 2 bytes */
 			talloc_free(cleartext_utf8_blob);
 			ldb_asprintf_errstring(ldb,
 					       "setup_password_fields: "
 					       "UTF16 password for user %s had odd length (length must be a multiple of 2)", io->u.sAMAccountName);
-			return LDB_ERR_OPERATIONS_ERROR;
+			return LDB_ERR_CONSTRAINT_VIOLATION;
 		} else {
 			*cleartext_utf8_blob = data_blob_const(cleartext_utf8_str,
 							       converted_pw_len);
diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py
index 0ac57d5..00cc450 100755
--- a/source4/dsdb/tests/python/ldap.py
+++ b/source4/dsdb/tests/python/ldap.py
@@ -310,18 +310,15 @@ class BasicTests(unittest.TestCase):
         except LdbError, (num, _):
             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
 
-        # More than one change operation is not allowed
-        m = Message()
-        m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-        m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
-          "objectClass")
-        m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
-          "objectClass")
-        try:
-            ldb.modify(m)
-            self.fail()
-        except LdbError, (num, _):
-            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+        # More than one change operation is allowed
+        ldb.modify_ldif("""
+dn: cn=ldaptestuser,cn=users, """ + self.base_dn + """
+changetype: modify
+delete: objectClass
+objectClass: bootableDevice
+add: objectClass
+objectClass: bootableDevice
+""")
 
         # We cannot remove all object classes by an empty replace
         m = Message()
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index 5d217ab..27e142b 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -490,7 +490,7 @@ def handle_special_add(samdb, dn, names):
         if len(res) > 0 and len(res2) == 0:
             message(CHANGE, "Existing object %s must be replaced by %s,"
                             "Renaming old object" % (str(oldDn), str(dn)))
-            samdb.rename(oldDn, objDn, ["relax:0", "local_oid:1.3.6.1.4.1.7165.4.3.16:0"])
+            samdb.rename(oldDn, objDn, ["relax:0", "provision:0"])
 
         return 0
 
@@ -602,7 +602,7 @@ def add_missing_object(ref_samdb, samdb, dn, names, basedn, hash, index):
         delta.dn = dn
         if not skip:
             message(CHANGE,"Object %s will be added" % dn)
-            samdb.add(delta, ["relax:0", "local_oid:1.3.6.1.4.1.7165.4.3.16:0"])
+            samdb.add(delta, ["relax:0", "provision:0"])
         else:
             message(CHANGE,"Object %s was skipped" % dn)
 
@@ -655,7 +655,7 @@ def add_deletedobj_containers(ref_samdb, samdb, names):
             for att in hashAttrNotCopied.keys():
                 delta.remove(att)
 
-            modcontrols = ["relax:0", "local_oid:1.3.6.1.4.1.7165.4.3.16:0"]
+            modcontrols = ["relax:0", "provision:0"]
             samdb.add(delta, modcontrols)
 
             listwko = []
@@ -992,7 +992,7 @@ def update_present(ref_samdb, samdb, basedn, listPresent, usns, invocationid):
             #for checkedatt in relaxedatt:
             for attr in delta.keys():
                 if attr.lower() in relaxedatt:
-                    modcontrols = ["relax:0", "local_oid:1.3.6.1.4.1.7165.4.3.16:0"]
+                    modcontrols = ["relax:0", "provision:0"]
             message(CHANGE, "%s is different from the reference one, changed"


-- 
Samba Shared Repository


More information about the samba-cvs mailing list