diff options
author | Gary Lockyer <gary@catalyst.net.nz> | 2018-02-28 11:47:22 +1300 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2018-05-02 14:18:10 +0200 |
commit | b1ac0944146705ed13a89b0d0ac1b4656641c170 (patch) | |
tree | bcedc194b823f52a67d6d6f470e092a47d744ec3 | |
parent | f1bf8d74cc910c1a48c105b85c71dc84ffda8f10 (diff) | |
download | samba-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.c | 64 |
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) { |