From b34db0840de701b4d42918a8da952959a6955453 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 19 Dec 2009 20:55:11 +1100 Subject: s4-ldb: use the RELAX control to disable single value checking on replace When using w2k3 linked attributes we are allowed to have multiple values on a single valued attribute. This happens when the other values are deleted. Setting the RELAX control tell the ldb-tdb backend to not check for this on replace, which means the caller has to check for single valued violations. --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 17 ++++++++++++++--- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index cd2249d4a2..aa19f75e9c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -463,7 +463,7 @@ int ltdb_increase_sequence_number(struct ldb_module *module) val_time.data = (uint8_t *)s; val_time.length = strlen(s); - ret = ltdb_modify_internal(module, msg); + ret = ltdb_modify_internal(module, msg, NULL); talloc_free(msg); diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 227a202a6f..a146b96b20 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -592,9 +592,12 @@ static int msg_delete_element(struct ldb_module *module, yuck - this is O(n^2). Luckily n is usually small so we probably get away with it, but if we ever have really large attribute lists then we'll need to look at this again + + 'req' is optional, and is used to specify controls if supplied */ int ltdb_modify_internal(struct ldb_module *module, - const struct ldb_message *msg) + const struct ldb_message *msg, + struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); void *data = ldb_module_get_private(module); @@ -731,7 +734,15 @@ int ltdb_modify_internal(struct ldb_module *module, case LDB_FLAG_MOD_REPLACE: if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { - if (el->num_values > 1) { + /* 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; @@ -852,7 +863,7 @@ static int ltdb_modify(struct ltdb_context *ctx) return LDB_ERR_OPERATIONS_ERROR; } - ret = ltdb_modify_internal(module, req->op.mod.message); + ret = ltdb_modify_internal(module, req->op.mod.message, req); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index bb4cb3f8b5..70b99c340c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -130,7 +130,7 @@ int ltdb_lock_read(struct ldb_module *module); int ltdb_unlock_read(struct ldb_module *module); struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn); int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); -int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); +int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg, struct ldb_request *req); int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn); int ltdb_err_map(enum TDB_ERROR tdb_code); -- cgit