s4:objectclass_attrs LDB module - move the single-valued attribute check into this...
authorMatthias Dieter Wallnöfer <mdw@samba.org>
Mon, 7 Jun 2010 18:46:59 +0000 (20:46 +0200)
committerMatthias Dieter Wallnöfer <mdw@samba.org>
Mon, 7 Jun 2010 18:54:10 +0000 (20:54 +0200)
It seems to me more consistent (and also to keep the same behaviour on all
backends).

Also the DRS hack should therefore not be needed anymore since the
"repl_meta_data" module launches requests behind "objectclass_attrs".

source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
source4/lib/ldb/ldb_tdb/ldb_tdb.c

index 042d26b981e5fd43e5d7d5ec57492c4575ff3474..5b76a0b9461f5f13857aee07390f2df21694078b 100644 (file)
@@ -180,7 +180,7 @@ static int attr_handler2(struct oc_context *ac)
        }
 
        /* Check if all specified attributes are valid in the given
-        * objectclasses. */
+        * objectclasses and if they meet additional schema restrictions. */
        msg = ac->search_res->message;
        for (i = 0; i < msg->num_elements; i++) {
                attr = dsdb_attribute_by_lDAPDisplayName(ac->schema,
@@ -189,6 +189,18 @@ static int attr_handler2(struct oc_context *ac)
                        return LDB_ERR_OPERATIONS_ERROR;
                }
 
+               /* Check if they're single-valued if this is requested */
+               if ((msg->elements[i].num_values > 1) && (attr->isSingleValued)) {
+                       ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' is single-valued!",
+                                              msg->elements[i].name,
+                                              ldb_dn_get_linearized(msg->dn));
+                       if (ac->req->operation == LDB_ADD) {
+                               return LDB_ERR_CONSTRAINT_VIOLATION;
+                       } else {
+                               return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+                       }
+               }
+
                /* We can use "str_list_check" with "strcmp" here since the
                 * attribute informations from the schema are always equal
                 * up-down-cased. */
index c80ecd0b4337fc53a239a4b8e7fb589d93928582..c421dda7910af203365ab05cac49044a67f818e7 100644 (file)
@@ -294,20 +294,12 @@ static int ltdb_add_internal(struct ldb_module *module,
 
        for (i=0;i<msg->num_elements;i++) {
                struct ldb_message_element *el = &msg->elements[i];
-               const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
 
                if (el->num_values == 0) {
                        ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)", 
                                               el->name, ldb_dn_get_linearized(msg->dn));
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
-               if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
-                       if (el->num_values > 1) {
-                               ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
-                                                      el->name, ldb_dn_get_linearized(msg->dn));
-                               return LDB_ERR_CONSTRAINT_VIOLATION;
-                       }
-               }
        }
 
        ret = ltdb_store(module, msg, TDB_INSERT);
@@ -649,7 +641,6 @@ int ltdb_modify_internal(struct ldb_module *module,
        for (i=0; i<msg->num_elements; i++) {
                struct ldb_message_element *el = &msg->elements[i], *el2;
                struct ldb_val *vals;
-               const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
                const char *dn;
 
                switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
@@ -685,15 +676,6 @@ int ltdb_modify_internal(struct ldb_module *module,
                                }
                        }
 
-                       if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
-                               if (el->num_values > 1) {
-                                       ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
-                                                              el->name, ldb_dn_get_linearized(msg2->dn));
-                                       ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
-                                       goto done;
-                               }
-                       }
-
                        /* Checks if element already exists */
                        idx = find_element(msg2, el->name);
                        if (idx == -1) {
@@ -706,15 +688,6 @@ int ltdb_modify_internal(struct ldb_module *module,
                                        goto done;
                                }
                        } else {
-                               /* We cannot add another value on a existing one
-                                  if the attribute is single-valued */
-                               if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
-                                       ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
-                                                              el->name, ldb_dn_get_linearized(msg2->dn));
-                                       ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
-                                       goto done;
-                               }
-
                                el2 = &(msg2->elements[idx]);
 
                                /* Check that values don't exist yet on multi-
@@ -772,23 +745,6 @@ int ltdb_modify_internal(struct ldb_module *module,
 
                case LDB_FLAG_MOD_REPLACE:
 
-                       if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
-                               /* the RELAX control overrides this
-                                  check for replace. This is needed as
-                                  DRS replication can produce multiple
-                                  values here for a single valued
-                                  attribute when the values are deleted
-                                  links
-                               */
-                               if (el->num_values > 1 &&
-                                   (!req || !ldb_request_get_control(req, LDB_CONTROL_RELAX_OID))) {
-                                       ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
-                                                              el->name, ldb_dn_get_linearized(msg2->dn));
-                                       ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
-                                       goto done;
-                               }
-                       }
-
                        /* TODO: This is O(n^2) - replace with more efficient check */
                        for (j=0; j<el->num_values; j++) {
                                if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {