s4:objectclass LDB module - we should not simply ignore additional "objectClass"...
authorMatthias Dieter Wallnöfer <mdw@samba.org>
Fri, 12 Nov 2010 18:49:47 +0000 (19:49 +0100)
committerMatthias Dieter Wallnöfer <mdw@samba.org>
Fri, 12 Nov 2010 19:39:06 +0000 (19:39 +0000)
There first one we perform all other tentatives are terminated with
ERR_ATTRIBUTE_OR_VALUE_EXISTS (tested against Windows).

Autobuild-User: Matthias Dieter Wallnöfer <mdw@samba.org>
Autobuild-Date: Fri Nov 12 19:39:07 UTC 2010 on sn-devel-104

source4/dsdb/samdb/ldb_modules/objectclass.c
source4/dsdb/tests/python/ldap.py

index 2e95eb5e91a1c8af51d6b28abd672f905ca46132..d2b4f10838b65fe3fca24b41c4b1d1d15508c4b5 100644 (file)
@@ -1082,12 +1082,26 @@ static int objectclass_do_mod(struct oc_context *ac)
                break;
        }
 
                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;
+               }
+       }
+
        ret = ldb_msg_add_empty(msg, "objectClass",
                                LDB_FLAG_MOD_REPLACE, &oc_el_change);
        if (ret != LDB_SUCCESS) {
        ret = ldb_msg_add_empty(msg, "objectClass",
                                LDB_FLAG_MOD_REPLACE, &oc_el_change);
        if (ret != LDB_SUCCESS) {
-               ldb_oom(ldb);
                talloc_free(mem_ctx);
                talloc_free(mem_ctx);
-               return ret;
+               return ldb_oom(ldb);
        }
 
        /* Move from the linked list back into an ldb msg */
        }
 
        /* Move from the linked list back into an ldb msg */
index 26a0d720c58be9851c5901d6ef7279859e33d500..0ac57d52473c7455664db76322bbf86b1d6a51e6 100755 (executable)
@@ -310,6 +310,19 @@ class BasicTests(unittest.TestCase):
         except LdbError, (num, _):
             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
 
         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)
+
         # We cannot remove all object classes by an empty replace
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
         # We cannot remove all object classes by an empty replace
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)