summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/schema/schema_init.c4
-rw-r--r--source4/lib/ldb/include/ldb.h5
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c49
3 files changed, 56 insertions, 2 deletions
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index fa1953a14f..8bb54f47f4 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -653,6 +653,10 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
if (dsdb_schema_unique_attribute(a->name)) {
a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
}
+ if (attr->isSingleValued) {
+ a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
+ }
+
return LDB_SUCCESS;
}
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 0378697f4b..fa531b26f2 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -392,6 +392,11 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
*/
#define LDB_ATTR_FLAG_UNIQUE_INDEX (1<<3)
+/*
+ when this is set, attempts to create two attribute values for this attribute on a single DN will return LDB_ERR_CONSTRAINT_VIOLATION
+ */
+#define LDB_ATTR_FLAG_SINGLE_VALUE (1<<4)
+
/**
LDAP attribute syntax for a DN
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index d4f7b452cb..e569a5a2a8 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -254,7 +254,7 @@ static int ltdb_add_internal(struct ldb_module *module,
const struct ldb_message *msg)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
- int ret;
+ int ret, i;
ret = ltdb_check_special_dn(module, msg);
if (ret != LDB_SUCCESS) {
@@ -265,6 +265,24 @@ static int ltdb_add_internal(struct ldb_module *module,
return LDB_ERR_OPERATIONS_ERROR;
}
+ 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 speicified, but with 0 values (illigal)",
+ 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 speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
+ }
+
ret = ltdb_store(module, msg, TDB_INSERT);
if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
@@ -602,15 +620,28 @@ int ltdb_modify_internal(struct ldb_module *module,
struct ldb_message_element *el2;
struct ldb_val *vals;
const char *dn;
-
+ const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
case LDB_FLAG_MOD_ADD:
+
/* add this element to the message. fail if it
already exists */
idx = find_element(msg2, el->name);
+ if (el->num_values == 0) {
+ ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
if (idx == -1) {
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ if (el->num_values > 1) {
+ ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
if (msg_add_element(ldb, msg2, el) != 0) {
ret = LDB_ERR_OTHER;
goto failed;
@@ -618,6 +649,13 @@ int ltdb_modify_internal(struct ldb_module *module,
continue;
}
+ /* If this is an add, then if it already
+ * exists in the object, then we violoate the
+ * single-value rule */
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
el2 = &msg2->elements[idx];
/* An attribute with this name already exists,
@@ -657,6 +695,13 @@ int ltdb_modify_internal(struct ldb_module *module,
break;
case LDB_FLAG_MOD_REPLACE:
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ if (el->num_values > 1) {
+ ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
/* replace all elements of this attribute name with the elements
listed. The attribute not existing is not an error */
msg_delete_attribute(module, ldb, msg2, el->name);