summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Lockyer <gary@catalyst.net.nz>2018-02-28 11:47:22 +1300
committerStefan Metzmacher <metze@samba.org>2018-05-02 14:18:10 +0200
commitb1ac0944146705ed13a89b0d0ac1b4656641c170 (patch)
treebcedc194b823f52a67d6d6f470e092a47d744ec3
parentf1bf8d74cc910c1a48c105b85c71dc84ffda8f10 (diff)
downloadsamba-b1ac0944146705ed13a89b0d0ac1b4656641c170.tar.gz
ldb_tdb: Do not fail in GUID index mode if there is a duplicate attribute
It is not the job of the index code to enforce this, but do give a a warning given it has been detected. However, now that we do allow it, we must never return the same object twice to the caller, so filter for it in ltdb_index_filter(). The GUID list is sorted, which makes this cheap to handle, thankfully. Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> BUG: https://bugzilla.samba.org/show_bug.cgi?id=13335 (cherry picked from commit 5c1504b94d1417894176811f18c5d450de22cfd2)
-rw-r--r--lib/ldb/ldb_tdb/ldb_index.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c
index 99fef23662f..ee2027319e3 100644
--- a/lib/ldb/ldb_tdb/ldb_index.c
+++ b/lib/ldb/ldb_tdb/ldb_index.c
@@ -1526,6 +1526,7 @@ static int ltdb_index_filter(struct ltdb_private *ltdb,
struct ldb_message *msg;
struct ldb_message *filtered_msg;
unsigned int i;
+ uint8_t previous_guid_key[LTDB_GUID_KEY_SIZE] = {};
ldb = ldb_module_get_ctx(ac->module);
@@ -1538,11 +1539,6 @@ static int ltdb_index_filter(struct ltdb_private *ltdb,
int ret;
bool matched;
- msg = ldb_msg_new(ac);
- if (!msg) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
ret = ltdb_idx_to_key(ac->module, ltdb,
ac, &dn_list->dn[i],
&tdb_key);
@@ -1550,6 +1546,33 @@ static int ltdb_index_filter(struct ltdb_private *ltdb,
return ret;
}
+ if (ltdb->cache->GUID_index_attribute != NULL) {
+ /*
+ * If we are in GUID index mode, then the dn_list is
+ * sorted. If we got a duplicate, forget about it, as
+ * otherwise we would send the same entry back more
+ * than once.
+ *
+ * This is needed in the truncated DN case, or if a
+ * duplicate was forced in via
+ * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK
+ */
+
+ if (memcmp(previous_guid_key, tdb_key.dptr,
+ sizeof(previous_guid_key)) == 0) {
+ continue;
+ }
+
+ memcpy(previous_guid_key, tdb_key.dptr,
+ sizeof(previous_guid_key));
+ }
+
+ msg = ldb_msg_new(ac);
+ if (!msg) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+
ret = ltdb_search_key(ac->module, ltdb,
tdb_key, msg,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
@@ -1923,9 +1946,36 @@ static int ltdb_index_add1(struct ldb_module *module,
BINARY_ARRAY_SEARCH_GTE(list->dn, list->count,
*key_val, ldb_val_equal_exact_ordered,
exact, next);
+
+ /*
+ * Give a warning rather than fail, this could be a
+ * duplicate value in the record allowed by a caller
+ * forcing in the value with
+ * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK
+ */
if (exact != NULL) {
- talloc_free(list);
- return LDB_ERR_OPERATIONS_ERROR;
+ /* This can't fail, gives a default at worst */
+ const struct ldb_schema_attribute *attr
+ = ldb_schema_attribute_by_name(
+ ldb,
+ ltdb->cache->GUID_index_attribute);
+ struct ldb_val v;
+ ret = attr->syntax->ldif_write_fn(ldb, list,
+ exact, &v);
+ if (ret == LDB_SUCCESS) {
+ ldb_debug(ldb, LDB_DEBUG_WARNING,
+ __location__
+ ": duplicate attribute value in %s "
+ "for index on %s, "
+ "duplicate of %s %*.*s in %s",
+ ldb_dn_get_linearized(msg->dn),
+ el->name,
+ ltdb->cache->GUID_index_attribute,
+ (int)v.length,
+ (int)v.length,
+ v.data,
+ ldb_dn_get_linearized(dn_key));
+ }
}
if (next == NULL) {