diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 12 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 44 |
2 files changed, 44 insertions, 12 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c index 62bc9ae8b2..ed193491d1 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c @@ -296,18 +296,6 @@ static int attr_handler2(struct oc_context *ac) return ldb_operr(ldb); } - /* 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. */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index d9547c98c4..b7432ab4d2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -294,12 +294,20 @@ 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); @@ -650,6 +658,7 @@ 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) { @@ -686,6 +695,15 @@ 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) { @@ -702,6 +720,15 @@ int ltdb_modify_internal(struct ldb_module *module, j = (unsigned int) idx; el2 = &(msg2->elements[j]); + /* 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; + } + /* Check that values don't exist yet on multi- valued attributes or aren't provided twice */ for (j = 0; j < el->num_values; j++) { @@ -761,6 +788,23 @@ 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]) { |