CVE-2019-3824 ldb: Add tests for ldb_wildcard_match
[Samba.git] / lib / ldb / ldb_tdb / ldb_index.c
blob56ecf935eb69fd50a3025bb065a76c9c5b92fbd8
1 /*
2 ldb database library
4 Copyright (C) Andrew Tridgell 2004-2009
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 * Name: ldb
27 * Component: ldb tdb backend - indexing
29 * Description: indexing routines for ldb tdb backend
31 * Author: Andrew Tridgell
34 #include "ldb_tdb.h"
35 #include "ldb_private.h"
37 struct dn_list {
38 unsigned int count;
39 struct ldb_val *dn;
42 struct ltdb_idxptr {
43 struct tdb_context *itdb;
44 int error;
47 /* we put a @IDXVERSION attribute on index entries. This
48 allows us to tell if it was written by an older version
50 #define LTDB_INDEXING_VERSION 2
52 /* enable the idxptr mode when transactions start */
53 int ltdb_index_transaction_start(struct ldb_module *module)
55 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
56 ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr);
57 if (ltdb->idxptr == NULL) {
58 return ldb_oom(ldb_module_get_ctx(module));
61 return LDB_SUCCESS;
64 /* compare two DN entries in a dn_list. Take account of possible
65 * differences in string termination */
66 static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
68 if (v1->length > v2->length && v1->data[v2->length] != 0) {
69 return -1;
71 if (v1->length < v2->length && v2->data[v1->length] != 0) {
72 return 1;
74 return strncmp((char *)v1->data, (char *)v2->data, v1->length);
79 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
80 comparison with the dn returns -1 if not found
82 static int ltdb_dn_list_find_val(struct ltdb_private *ltdb,
83 const struct dn_list *list,
84 const struct ldb_val *v)
86 unsigned int i;
87 for (i=0; i<list->count; i++) {
88 if (dn_list_cmp(&list->dn[i], v) == 0) {
89 return i;
92 return -1;
96 find a entry in a dn_list. Uses a case sensitive comparison with the dn
97 returns -1 if not found
99 static int ltdb_dn_list_find_str(struct ltdb_private *ltdb,
100 struct dn_list *list,
101 const char *dn)
103 struct ldb_val v;
104 v.data = discard_const_p(unsigned char, dn);
105 v.length = strlen(dn);
106 return ltdb_dn_list_find_val(ltdb, list, &v);
110 this is effectively a cast function, but with lots of paranoia
111 checks and also copes with CPUs that are fussy about pointer
112 alignment
114 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
116 struct dn_list *list;
117 if (rec.dsize != sizeof(void *)) {
118 ldb_asprintf_errstring(ldb_module_get_ctx(module),
119 "Bad data size for idxptr %u", (unsigned)rec.dsize);
120 return NULL;
122 /* note that we can't just use a cast here, as rec.dptr may
123 not be aligned sufficiently for a pointer. A cast would cause
124 platforms like some ARM CPUs to crash */
125 memcpy(&list, rec.dptr, sizeof(void *));
126 list = talloc_get_type(list, struct dn_list);
127 if (list == NULL) {
128 ldb_asprintf_errstring(ldb_module_get_ctx(module),
129 "Bad type '%s' for idxptr",
130 talloc_get_name(list));
131 return NULL;
133 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
134 ldb_asprintf_errstring(ldb_module_get_ctx(module),
135 "Bad parent '%s' for idxptr",
136 talloc_get_name(talloc_parent(list->dn)));
137 return NULL;
139 return list;
143 return the @IDX list in an index entry for a dn as a
144 struct dn_list
146 static int ltdb_dn_list_load(struct ldb_module *module,
147 struct ldb_dn *dn, struct dn_list *list)
149 struct ldb_message *msg;
150 int ret;
151 struct ldb_message_element *el;
152 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
153 TDB_DATA rec;
154 struct dn_list *list2;
155 TDB_DATA key;
157 list->dn = NULL;
158 list->count = 0;
160 /* see if we have any in-memory index entries */
161 if (ltdb->idxptr == NULL ||
162 ltdb->idxptr->itdb == NULL) {
163 goto normal_index;
166 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
167 key.dsize = strlen((char *)key.dptr);
169 rec = tdb_fetch(ltdb->idxptr->itdb, key);
170 if (rec.dptr == NULL) {
171 goto normal_index;
174 /* we've found an in-memory index entry */
175 list2 = ltdb_index_idxptr(module, rec, true);
176 if (list2 == NULL) {
177 free(rec.dptr);
178 return LDB_ERR_OPERATIONS_ERROR;
180 free(rec.dptr);
182 *list = *list2;
183 return LDB_SUCCESS;
185 normal_index:
186 msg = ldb_msg_new(list);
187 if (msg == NULL) {
188 return LDB_ERR_OPERATIONS_ERROR;
191 ret = ltdb_search_dn1(module, dn, msg,
192 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
193 |LDB_UNPACK_DATA_FLAG_NO_DN);
194 if (ret != LDB_SUCCESS) {
195 talloc_free(msg);
196 return ret;
199 /* TODO: check indexing version number */
201 el = ldb_msg_find_element(msg, LTDB_IDX);
202 if (!el) {
203 talloc_free(msg);
204 return LDB_SUCCESS;
208 * we avoid copying the strings by stealing the list. We have
209 * to steal msg onto el->values (which looks odd) because we
210 * asked for the memory to be allocated on msg, not on each
211 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
213 talloc_steal(el->values, msg);
214 list->dn = talloc_steal(list, el->values);
215 list->count = el->num_values;
217 /* We don't need msg->elements any more */
218 talloc_free(msg->elements);
219 return LDB_SUCCESS;
224 save a dn_list into a full @IDX style record
226 static int ltdb_dn_list_store_full(struct ldb_module *module,
227 struct ltdb_private *ltdb,
228 struct ldb_dn *dn,
229 struct dn_list *list)
231 struct ldb_message *msg;
232 int ret;
234 if (list->count == 0) {
235 ret = ltdb_delete_noindex(module, dn);
236 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
237 return LDB_SUCCESS;
239 return ret;
242 msg = ldb_msg_new(module);
243 if (!msg) {
244 return ldb_module_oom(module);
247 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
248 if (ret != LDB_SUCCESS) {
249 talloc_free(msg);
250 return ldb_module_oom(module);
253 msg->dn = dn;
254 if (list->count > 0) {
255 struct ldb_message_element *el;
257 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
258 if (ret != LDB_SUCCESS) {
259 talloc_free(msg);
260 return ldb_module_oom(module);
262 el->values = list->dn;
263 el->num_values = list->count;
266 ret = ltdb_store(module, msg, TDB_REPLACE);
267 talloc_free(msg);
268 return ret;
272 save a dn_list into the database, in either @IDX or internal format
274 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
275 struct dn_list *list)
277 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
278 TDB_DATA rec, key;
279 int ret;
280 struct dn_list *list2;
282 if (ltdb->idxptr == NULL) {
283 return ltdb_dn_list_store_full(module, ltdb,
284 dn, list);
287 if (ltdb->idxptr->itdb == NULL) {
288 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
289 if (ltdb->idxptr->itdb == NULL) {
290 return LDB_ERR_OPERATIONS_ERROR;
294 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
295 key.dsize = strlen((char *)key.dptr);
297 rec = tdb_fetch(ltdb->idxptr->itdb, key);
298 if (rec.dptr != NULL) {
299 list2 = ltdb_index_idxptr(module, rec, false);
300 if (list2 == NULL) {
301 free(rec.dptr);
302 return LDB_ERR_OPERATIONS_ERROR;
304 free(rec.dptr);
305 list2->dn = talloc_steal(list2, list->dn);
306 list2->count = list->count;
307 return LDB_SUCCESS;
310 list2 = talloc(ltdb->idxptr, struct dn_list);
311 if (list2 == NULL) {
312 return LDB_ERR_OPERATIONS_ERROR;
314 list2->dn = talloc_steal(list2, list->dn);
315 list2->count = list->count;
317 rec.dptr = (uint8_t *)&list2;
318 rec.dsize = sizeof(void *);
320 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
321 if (ret != 0) {
322 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
324 return LDB_SUCCESS;
328 traverse function for storing the in-memory index entries on disk
330 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
332 struct ldb_module *module = state;
333 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
334 struct ldb_dn *dn;
335 struct ldb_context *ldb = ldb_module_get_ctx(module);
336 struct ldb_val v;
337 struct dn_list *list;
339 list = ltdb_index_idxptr(module, data, true);
340 if (list == NULL) {
341 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
342 return -1;
345 v.data = key.dptr;
346 v.length = strnlen((char *)key.dptr, key.dsize);
348 dn = ldb_dn_from_ldb_val(module, ldb, &v);
349 if (dn == NULL) {
350 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
351 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
352 return -1;
355 ltdb->idxptr->error = ltdb_dn_list_store_full(module, ltdb,
356 dn, list);
357 talloc_free(dn);
358 if (ltdb->idxptr->error != 0) {
359 return -1;
361 return 0;
364 /* cleanup the idxptr mode when transaction commits */
365 int ltdb_index_transaction_commit(struct ldb_module *module)
367 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
368 int ret;
370 struct ldb_context *ldb = ldb_module_get_ctx(module);
372 ldb_reset_err_string(ldb);
374 if (ltdb->idxptr->itdb) {
375 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
376 tdb_close(ltdb->idxptr->itdb);
379 ret = ltdb->idxptr->error;
380 if (ret != LDB_SUCCESS) {
381 if (!ldb_errstring(ldb)) {
382 ldb_set_errstring(ldb, ldb_strerror(ret));
384 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
387 talloc_free(ltdb->idxptr);
388 ltdb->idxptr = NULL;
389 return ret;
392 /* cleanup the idxptr mode when transaction cancels */
393 int ltdb_index_transaction_cancel(struct ldb_module *module)
395 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
396 if (ltdb->idxptr && ltdb->idxptr->itdb) {
397 tdb_close(ltdb->idxptr->itdb);
399 talloc_free(ltdb->idxptr);
400 ltdb->idxptr = NULL;
401 return LDB_SUCCESS;
406 return the dn key to be used for an index
407 the caller is responsible for freeing
409 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
410 const char *attr, const struct ldb_val *value,
411 const struct ldb_schema_attribute **ap)
413 struct ldb_dn *ret;
414 struct ldb_val v;
415 const struct ldb_schema_attribute *a;
416 char *attr_folded;
417 int r;
419 attr_folded = ldb_attr_casefold(ldb, attr);
420 if (!attr_folded) {
421 return NULL;
424 a = ldb_schema_attribute_by_name(ldb, attr);
425 if (ap) {
426 *ap = a;
428 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
429 if (r != LDB_SUCCESS) {
430 const char *errstr = ldb_errstring(ldb);
431 /* canonicalisation can be refused. For example,
432 a attribute that takes wildcards will refuse to canonicalise
433 if the value contains a wildcard */
434 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
435 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
436 talloc_free(attr_folded);
437 return NULL;
439 if (ldb_should_b64_encode(ldb, &v)) {
440 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
441 if (!vstr) {
442 talloc_free(attr_folded);
443 return NULL;
445 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
446 talloc_free(vstr);
447 } else {
448 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
451 if (v.data != value->data) {
452 talloc_free(v.data);
454 talloc_free(attr_folded);
456 return ret;
460 see if a attribute value is in the list of indexed attributes
462 static bool ltdb_is_indexed(struct ldb_module *module,
463 struct ltdb_private *ltdb,
464 const char *attr)
466 struct ldb_context *ldb = ldb_module_get_ctx(module);
467 unsigned int i;
468 struct ldb_message_element *el;
470 if (ldb->schema.index_handler_override) {
471 const struct ldb_schema_attribute *a
472 = ldb_schema_attribute_by_name(ldb, attr);
474 if (a == NULL) {
475 return false;
478 if (a->flags & LDB_ATTR_FLAG_INDEXED) {
479 return true;
480 } else {
481 return false;
485 if (!ltdb->cache->attribute_indexes) {
486 return false;
489 el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
490 if (el == NULL) {
491 return false;
494 /* TODO: this is too expensive! At least use a binary search */
495 for (i=0; i<el->num_values; i++) {
496 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
497 return true;
500 return false;
504 in the following logic functions, the return value is treated as
505 follows:
507 LDB_SUCCESS: we found some matching index values
509 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
511 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
512 we'll need a full search
516 return a list of dn's that might match a simple indexed search (an
517 equality search only)
519 static int ltdb_index_dn_simple(struct ldb_module *module,
520 struct ltdb_private *ltdb,
521 const struct ldb_parse_tree *tree,
522 struct dn_list *list)
524 struct ldb_context *ldb;
525 struct ldb_dn *dn;
526 int ret;
528 ldb = ldb_module_get_ctx(module);
530 list->count = 0;
531 list->dn = NULL;
533 /* if the attribute isn't in the list of indexed attributes then
534 this node needs a full search */
535 if (!ltdb_is_indexed(module, ltdb, tree->u.equality.attr)) {
536 return LDB_ERR_OPERATIONS_ERROR;
539 /* the attribute is indexed. Pull the list of DNs that match the
540 search criterion */
541 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
542 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
544 ret = ltdb_dn_list_load(module, dn, list);
545 talloc_free(dn);
546 return ret;
550 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
553 return a list of dn's that might match a leaf indexed search
555 static int ltdb_index_dn_leaf(struct ldb_module *module,
556 struct ltdb_private *ltdb,
557 const struct ldb_parse_tree *tree,
558 struct dn_list *list)
560 if (ltdb->disallow_dn_filter &&
561 (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
562 /* in AD mode we do not support "(dn=...)" search filters */
563 list->dn = NULL;
564 list->count = 0;
565 return LDB_SUCCESS;
567 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
568 list->dn = talloc_array(list, struct ldb_val, 1);
569 if (list->dn == NULL) {
570 ldb_module_oom(module);
571 return LDB_ERR_OPERATIONS_ERROR;
573 list->dn[0] = tree->u.equality.value;
574 list->count = 1;
575 return LDB_SUCCESS;
577 return ltdb_index_dn_simple(module, ltdb, tree, list);
582 list intersection
583 list = list & list2
585 static bool list_intersect(struct ldb_context *ldb,
586 struct ltdb_private *ltdb,
587 struct dn_list *list, const struct dn_list *list2)
589 struct dn_list *list3;
590 unsigned int i;
592 if (list->count == 0) {
593 /* 0 & X == 0 */
594 return true;
596 if (list2->count == 0) {
597 /* X & 0 == 0 */
598 list->count = 0;
599 list->dn = NULL;
600 return true;
603 /* the indexing code is allowed to return a longer list than
604 what really matches, as all results are filtered by the
605 full expression at the end - this shortcut avoids a lot of
606 work in some cases */
607 if (list->count < 2 && list2->count > 10) {
608 return true;
610 if (list2->count < 2 && list->count > 10) {
611 list->count = list2->count;
612 list->dn = list2->dn;
613 /* note that list2 may not be the parent of list2->dn,
614 as list2->dn may be owned by ltdb->idxptr. In that
615 case we expect this reparent call to fail, which is
616 OK */
617 talloc_reparent(list2, list, list2->dn);
618 return true;
621 list3 = talloc_zero(list, struct dn_list);
622 if (list3 == NULL) {
623 return false;
626 list3->dn = talloc_array(list3, struct ldb_val, list->count);
627 if (!list3->dn) {
628 talloc_free(list3);
629 return false;
631 list3->count = 0;
633 for (i=0;i<list->count;i++) {
634 if (ltdb_dn_list_find_val(ltdb, list2,
635 &list->dn[i]) != -1) {
636 list3->dn[list3->count] = list->dn[i];
637 list3->count++;
641 list->dn = talloc_steal(list, list3->dn);
642 list->count = list3->count;
643 talloc_free(list3);
645 return true;
650 list union
651 list = list | list2
653 static bool list_union(struct ldb_context *ldb,
654 struct dn_list *list, const struct dn_list *list2)
656 struct ldb_val *dn3;
658 if (list2->count == 0) {
659 /* X | 0 == X */
660 return true;
663 if (list->count == 0) {
664 /* 0 | X == X */
665 list->count = list2->count;
666 list->dn = list2->dn;
667 /* note that list2 may not be the parent of list2->dn,
668 as list2->dn may be owned by ltdb->idxptr. In that
669 case we expect this reparent call to fail, which is
670 OK */
671 talloc_reparent(list2, list, list2->dn);
672 return true;
675 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
676 if (!dn3) {
677 ldb_oom(ldb);
678 return false;
681 /* we allow for duplicates here, and get rid of them later */
682 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
683 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
685 list->dn = dn3;
686 list->count += list2->count;
688 return true;
691 static int ltdb_index_dn(struct ldb_module *module,
692 struct ltdb_private *ltdb,
693 const struct ldb_parse_tree *tree,
694 struct dn_list *list);
698 process an OR list (a union)
700 static int ltdb_index_dn_or(struct ldb_module *module,
701 struct ltdb_private *ltdb,
702 const struct ldb_parse_tree *tree,
703 struct dn_list *list)
705 struct ldb_context *ldb;
706 unsigned int i;
708 ldb = ldb_module_get_ctx(module);
710 list->dn = NULL;
711 list->count = 0;
713 for (i=0; i<tree->u.list.num_elements; i++) {
714 struct dn_list *list2;
715 int ret;
717 list2 = talloc_zero(list, struct dn_list);
718 if (list2 == NULL) {
719 return LDB_ERR_OPERATIONS_ERROR;
722 ret = ltdb_index_dn(module, ltdb,
723 tree->u.list.elements[i], list2);
725 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
726 /* X || 0 == X */
727 talloc_free(list2);
728 continue;
731 if (ret != LDB_SUCCESS) {
732 /* X || * == * */
733 talloc_free(list2);
734 return ret;
737 if (!list_union(ldb, list, list2)) {
738 talloc_free(list2);
739 return LDB_ERR_OPERATIONS_ERROR;
743 if (list->count == 0) {
744 return LDB_ERR_NO_SUCH_OBJECT;
747 return LDB_SUCCESS;
752 NOT an index results
754 static int ltdb_index_dn_not(struct ldb_module *module,
755 struct ltdb_private *ltdb,
756 const struct ldb_parse_tree *tree,
757 struct dn_list *list)
759 /* the only way to do an indexed not would be if we could
760 negate the not via another not or if we knew the total
761 number of database elements so we could know that the
762 existing expression covered the whole database.
764 instead, we just give up, and rely on a full index scan
765 (unless an outer & manages to reduce the list)
767 return LDB_ERR_OPERATIONS_ERROR;
771 static bool ltdb_index_unique(struct ldb_context *ldb,
772 const char *attr)
774 const struct ldb_schema_attribute *a;
775 a = ldb_schema_attribute_by_name(ldb, attr);
776 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
777 return true;
779 return false;
783 process an AND expression (intersection)
785 static int ltdb_index_dn_and(struct ldb_module *module,
786 struct ltdb_private *ltdb,
787 const struct ldb_parse_tree *tree,
788 struct dn_list *list)
790 struct ldb_context *ldb;
791 unsigned int i;
792 bool found;
794 ldb = ldb_module_get_ctx(module);
796 list->dn = NULL;
797 list->count = 0;
799 /* in the first pass we only look for unique simple
800 equality tests, in the hope of avoiding having to look
801 at any others */
802 for (i=0; i<tree->u.list.num_elements; i++) {
803 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
804 int ret;
806 if (subtree->operation != LDB_OP_EQUALITY ||
807 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
808 continue;
811 ret = ltdb_index_dn(module, ltdb, subtree, list);
812 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
813 /* 0 && X == 0 */
814 return LDB_ERR_NO_SUCH_OBJECT;
816 if (ret == LDB_SUCCESS) {
817 /* a unique index match means we can
818 * stop. Note that we don't care if we return
819 * a few too many objects, due to later
820 * filtering */
821 return LDB_SUCCESS;
825 /* now do a full intersection */
826 found = false;
828 for (i=0; i<tree->u.list.num_elements; i++) {
829 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
830 struct dn_list *list2;
831 int ret;
833 list2 = talloc_zero(list, struct dn_list);
834 if (list2 == NULL) {
835 return ldb_module_oom(module);
838 ret = ltdb_index_dn(module, ltdb, subtree, list2);
840 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
841 /* X && 0 == 0 */
842 list->dn = NULL;
843 list->count = 0;
844 talloc_free(list2);
845 return LDB_ERR_NO_SUCH_OBJECT;
848 if (ret != LDB_SUCCESS) {
849 /* this didn't adding anything */
850 talloc_free(list2);
851 continue;
854 if (!found) {
855 talloc_reparent(list2, list, list->dn);
856 list->dn = list2->dn;
857 list->count = list2->count;
858 found = true;
859 } else if (!list_intersect(ldb, ltdb,
860 list, list2)) {
861 talloc_free(list2);
862 return LDB_ERR_OPERATIONS_ERROR;
865 if (list->count == 0) {
866 list->dn = NULL;
867 return LDB_ERR_NO_SUCH_OBJECT;
870 if (list->count < 2) {
871 /* it isn't worth loading the next part of the tree */
872 return LDB_SUCCESS;
876 if (!found) {
877 /* none of the attributes were indexed */
878 return LDB_ERR_OPERATIONS_ERROR;
881 return LDB_SUCCESS;
885 return a list of matching objects using a one-level index
887 static int ltdb_index_dn_one(struct ldb_module *module,
888 struct ldb_dn *parent_dn,
889 struct dn_list *list)
891 struct ldb_context *ldb;
892 struct ldb_dn *key;
893 struct ldb_val val;
894 int ret;
896 ldb = ldb_module_get_ctx(module);
898 /* work out the index key from the parent DN */
899 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
900 val.length = strlen((char *)val.data);
901 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
902 if (!key) {
903 ldb_oom(ldb);
904 return LDB_ERR_OPERATIONS_ERROR;
907 ret = ltdb_dn_list_load(module, key, list);
908 talloc_free(key);
909 if (ret != LDB_SUCCESS) {
910 return ret;
913 if (list->count == 0) {
914 return LDB_ERR_NO_SUCH_OBJECT;
917 return LDB_SUCCESS;
921 return a list of dn's that might match a indexed search or
922 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
924 static int ltdb_index_dn(struct ldb_module *module,
925 struct ltdb_private *ltdb,
926 const struct ldb_parse_tree *tree,
927 struct dn_list *list)
929 int ret = LDB_ERR_OPERATIONS_ERROR;
931 switch (tree->operation) {
932 case LDB_OP_AND:
933 ret = ltdb_index_dn_and(module, ltdb, tree, list);
934 break;
936 case LDB_OP_OR:
937 ret = ltdb_index_dn_or(module, ltdb, tree, list);
938 break;
940 case LDB_OP_NOT:
941 ret = ltdb_index_dn_not(module, ltdb, tree, list);
942 break;
944 case LDB_OP_EQUALITY:
945 ret = ltdb_index_dn_leaf(module, ltdb, tree, list);
946 break;
948 case LDB_OP_SUBSTRING:
949 case LDB_OP_GREATER:
950 case LDB_OP_LESS:
951 case LDB_OP_PRESENT:
952 case LDB_OP_APPROX:
953 case LDB_OP_EXTENDED:
954 /* we can't index with fancy bitops yet */
955 ret = LDB_ERR_OPERATIONS_ERROR;
956 break;
959 return ret;
963 filter a candidate dn_list from an indexed search into a set of results
964 extracting just the given attributes
966 static int ltdb_index_filter(struct ltdb_private *ltdb,
967 const struct dn_list *dn_list,
968 struct ltdb_context *ac,
969 uint32_t *match_count)
971 struct ldb_context *ldb;
972 struct ldb_message *msg;
973 struct ldb_message *filtered_msg;
974 unsigned int i;
976 ldb = ldb_module_get_ctx(ac->module);
978 for (i = 0; i < dn_list->count; i++) {
979 struct ldb_dn *dn;
980 int ret;
981 bool matched;
983 msg = ldb_msg_new(ac);
984 if (!msg) {
985 return LDB_ERR_OPERATIONS_ERROR;
988 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
989 if (dn == NULL) {
990 talloc_free(msg);
991 return LDB_ERR_OPERATIONS_ERROR;
994 ret = ltdb_search_dn1(ac->module, dn, msg,
995 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
996 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
997 talloc_free(dn);
998 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
999 /* the record has disappeared? yes, this can happen */
1000 talloc_free(msg);
1001 continue;
1004 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1005 /* an internal error */
1006 talloc_free(msg);
1007 return LDB_ERR_OPERATIONS_ERROR;
1010 ret = ldb_match_msg_error(ldb, msg,
1011 ac->tree, ac->base, ac->scope, &matched);
1012 if (ret != LDB_SUCCESS) {
1013 talloc_free(msg);
1014 return ret;
1016 if (!matched) {
1017 talloc_free(msg);
1018 continue;
1021 /* filter the attributes that the user wants */
1022 ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
1024 talloc_free(msg);
1026 if (ret == -1) {
1027 return LDB_ERR_OPERATIONS_ERROR;
1030 ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
1031 if (ret != LDB_SUCCESS) {
1032 /* Regardless of success or failure, the msg
1033 * is the callbacks responsiblity, and should
1034 * not be talloc_free()'ed */
1035 ac->request_terminated = true;
1036 return ret;
1039 (*match_count)++;
1042 return LDB_SUCCESS;
1046 remove any duplicated entries in a indexed result
1048 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
1050 unsigned int i, new_count;
1052 if (list->count < 2) {
1053 return;
1056 TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp);
1058 new_count = 1;
1059 for (i=1; i<list->count; i++) {
1060 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
1061 if (new_count != i) {
1062 list->dn[new_count] = list->dn[i];
1064 new_count++;
1068 list->count = new_count;
1072 search the database with a LDAP-like expression using indexes
1073 returns -1 if an indexed search is not possible, in which
1074 case the caller should call ltdb_search_full()
1076 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1078 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1079 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
1080 struct dn_list *dn_list;
1081 int ret;
1083 /* see if indexing is enabled */
1084 if (!ltdb->cache->attribute_indexes &&
1085 !ltdb->cache->one_level_indexes &&
1086 ac->scope != LDB_SCOPE_BASE) {
1087 /* fallback to a full search */
1088 return LDB_ERR_OPERATIONS_ERROR;
1091 dn_list = talloc_zero(ac, struct dn_list);
1092 if (dn_list == NULL) {
1093 return ldb_module_oom(ac->module);
1096 switch (ac->scope) {
1097 case LDB_SCOPE_BASE:
1098 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1099 if (dn_list->dn == NULL) {
1100 talloc_free(dn_list);
1101 return ldb_module_oom(ac->module);
1103 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1104 if (dn_list->dn[0].data == NULL) {
1105 talloc_free(dn_list);
1106 return ldb_module_oom(ac->module);
1108 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1109 dn_list->count = 1;
1110 break;
1112 case LDB_SCOPE_ONELEVEL:
1114 struct dn_list *idx_one_tree_list = NULL;
1115 if (!ltdb->cache->one_level_indexes) {
1116 talloc_free(dn_list);
1117 return LDB_ERR_OPERATIONS_ERROR;
1119 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1120 if (ret != LDB_SUCCESS) {
1121 talloc_free(dn_list);
1122 return ret;
1126 * If we have too many matches, also try the filter
1127 * tree and do index work there
1129 * We only do this in the GUID index mode, which is
1130 * O(n*log(m)) otherwise the intersection below will
1131 * be too costly at O(n*m).
1133 idx_one_tree_list
1134 = talloc_zero(ac, struct dn_list);
1135 if (idx_one_tree_list == NULL) {
1136 return ldb_module_oom(ac->module);
1139 if (!ltdb->cache->attribute_indexes) {
1140 talloc_free(idx_one_tree_list);
1141 talloc_free(dn_list);
1142 return LDB_ERR_OPERATIONS_ERROR;
1145 * Here we load the index for the tree.
1147 ret = ltdb_index_dn(ac->module, ltdb, ac->tree,
1148 idx_one_tree_list);
1149 if (ret != LDB_SUCCESS) {
1150 talloc_free(idx_one_tree_list);
1151 talloc_free(dn_list);
1152 return ret;
1156 * We have to avoid the O(n*m) behaviour here blowing
1157 * up, so we only intersect the lists if it will
1158 * really help
1160 if (idx_one_tree_list->count < 10) {
1161 if (!list_intersect(ldb, ltdb,
1162 dn_list, idx_one_tree_list)) {
1163 talloc_free(idx_one_tree_list);
1164 talloc_free(dn_list);
1165 return LDB_ERR_OPERATIONS_ERROR;
1167 } else {
1168 talloc_free(idx_one_tree_list);
1170 break;
1172 case LDB_SCOPE_SUBTREE:
1173 case LDB_SCOPE_DEFAULT:
1174 if (!ltdb->cache->attribute_indexes) {
1175 talloc_free(dn_list);
1176 return LDB_ERR_OPERATIONS_ERROR;
1178 ret = ltdb_index_dn(ac->module, ltdb, ac->tree, dn_list);
1179 if (ret != LDB_SUCCESS) {
1180 talloc_free(dn_list);
1181 return ret;
1183 ltdb_dn_list_remove_duplicates(dn_list);
1184 break;
1187 ret = ltdb_index_filter(ltdb, dn_list, ac, match_count);
1188 talloc_free(dn_list);
1189 return ret;
1193 * @brief Add a DN in the index list of a given attribute name/value pair
1195 * This function will add the DN in the index list for the index for
1196 * the given attribute name and value.
1198 * @param[in] module A ldb_module structure
1200 * @param[in] dn The string representation of the DN as it
1201 * will be stored in the index entry
1203 * @param[in] el A ldb_message_element array, one of the entry
1204 * referred by the v_idx is the attribute name and
1205 * value pair which will be used to construct the
1206 * index name
1208 * @param[in] v_idx The index of element in the el array to use
1210 * @return An ldb error code
1212 static int ltdb_index_add1(struct ldb_module *module,
1213 struct ltdb_private *ltdb,
1214 const char *dn,
1215 struct ldb_message_element *el, int v_idx)
1217 struct ldb_context *ldb;
1218 struct ldb_dn *dn_key;
1219 int ret;
1220 const struct ldb_schema_attribute *a;
1221 struct dn_list *list;
1222 unsigned alloc_len;
1224 ldb = ldb_module_get_ctx(module);
1226 list = talloc_zero(module, struct dn_list);
1227 if (list == NULL) {
1228 return LDB_ERR_OPERATIONS_ERROR;
1231 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1232 if (!dn_key) {
1233 talloc_free(list);
1234 return LDB_ERR_OPERATIONS_ERROR;
1236 talloc_steal(list, dn_key);
1238 ret = ltdb_dn_list_load(module, dn_key, list);
1239 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1240 talloc_free(list);
1241 return ret;
1244 if (list->count > 0 &&
1245 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1247 * We do not want to print info about a possibly
1248 * confidential DN that the conflict was with in the
1249 * user-visible error string
1251 ldb_debug(ldb, LDB_DEBUG_WARNING,
1252 __location__ ": unique index violation on %s in %s, "
1253 "conficts with %*.*s in %s",
1254 el->name, dn,
1255 (int)list->dn[0].length,
1256 (int)list->dn[0].length,
1257 list->dn[0].data,
1258 ldb_dn_get_linearized(dn_key));
1259 ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
1260 el->name, dn);
1261 talloc_free(list);
1262 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1265 /* overallocate the list a bit, to reduce the number of
1266 * realloc trigered copies */
1267 alloc_len = ((list->count+1)+7) & ~7;
1268 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
1269 if (list->dn == NULL) {
1270 talloc_free(list);
1271 return LDB_ERR_OPERATIONS_ERROR;
1274 list->dn[list->count].data
1275 = (uint8_t *)talloc_strdup(list->dn, dn);
1276 if (list->dn[list->count].data == NULL) {
1277 talloc_free(list);
1278 return LDB_ERR_OPERATIONS_ERROR;
1280 list->dn[list->count].length = strlen(dn);
1281 list->count++;
1283 ret = ltdb_dn_list_store(module, dn_key, list);
1285 talloc_free(list);
1287 return ret;
1291 add index entries for one elements in a message
1293 static int ltdb_index_add_el(struct ldb_module *module,
1294 struct ltdb_private *ltdb,
1295 const char *dn,
1296 struct ldb_message_element *el)
1298 unsigned int i;
1299 for (i = 0; i < el->num_values; i++) {
1300 int ret = ltdb_index_add1(module, ltdb,
1301 dn, el, i);
1302 if (ret != LDB_SUCCESS) {
1303 return ret;
1307 return LDB_SUCCESS;
1311 add index entries for all elements in a message
1313 static int ltdb_index_add_all(struct ldb_module *module,
1314 struct ltdb_private *ltdb,
1315 const char *dn,
1316 struct ldb_message_element *elements,
1317 unsigned int num_el)
1319 unsigned int i;
1321 if (dn[0] == '@') {
1322 return LDB_SUCCESS;
1325 if (!ltdb->cache->attribute_indexes) {
1326 /* no indexed fields */
1327 return LDB_SUCCESS;
1330 for (i = 0; i < num_el; i++) {
1331 int ret;
1332 if (!ltdb_is_indexed(module, ltdb, elements[i].name)) {
1333 continue;
1335 ret = ltdb_index_add_el(module, ltdb, dn, &elements[i]);
1336 if (ret != LDB_SUCCESS) {
1337 struct ldb_context *ldb = ldb_module_get_ctx(module);
1338 ldb_asprintf_errstring(ldb,
1339 __location__ ": Failed to re-index %s in %s - %s",
1340 elements[i].name, dn, ldb_errstring(ldb));
1341 return ret;
1345 return LDB_SUCCESS;
1350 insert a one level index for a message
1352 static int ltdb_index_onelevel(struct ldb_module *module,
1353 const struct ldb_message *msg, int add)
1355 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
1356 struct ltdb_private);
1357 struct ldb_message_element el;
1358 struct ldb_val val;
1359 struct ldb_dn *pdn;
1360 const char *dn;
1361 int ret;
1363 /* We index for ONE Level only if requested */
1364 if (!ltdb->cache->one_level_indexes) {
1365 return LDB_SUCCESS;
1368 pdn = ldb_dn_get_parent(module, msg->dn);
1369 if (pdn == NULL) {
1370 return LDB_ERR_OPERATIONS_ERROR;
1373 dn = ldb_dn_get_linearized(msg->dn);
1374 if (dn == NULL) {
1375 talloc_free(pdn);
1376 return LDB_ERR_OPERATIONS_ERROR;
1379 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1380 if (val.data == NULL) {
1381 talloc_free(pdn);
1382 return LDB_ERR_OPERATIONS_ERROR;
1385 val.length = strlen((char *)val.data);
1386 el.name = LTDB_IDXONE;
1387 el.values = &val;
1388 el.num_values = 1;
1390 if (add) {
1391 ret = ltdb_index_add1(module, ltdb, dn, &el, 0);
1392 } else { /* delete */
1393 ret = ltdb_index_del_value(module, ltdb, msg->dn, &el, 0);
1396 talloc_free(pdn);
1398 return ret;
1402 add the index entries for a new element in a record
1403 The caller guarantees that these element values are not yet indexed
1405 int ltdb_index_add_element(struct ldb_module *module,
1406 struct ltdb_private *ltdb,
1407 struct ldb_dn *dn,
1408 struct ldb_message_element *el)
1410 if (ldb_dn_is_special(dn)) {
1411 return LDB_SUCCESS;
1413 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1414 return LDB_SUCCESS;
1416 return ltdb_index_add_el(module, ltdb,
1417 ldb_dn_get_linearized(dn), el);
1421 add the index entries for a new record
1423 int ltdb_index_add_new(struct ldb_module *module,
1424 struct ltdb_private *ltdb,
1425 const struct ldb_message *msg)
1427 const char *dn;
1428 int ret;
1430 if (ldb_dn_is_special(msg->dn)) {
1431 return LDB_SUCCESS;
1434 dn = ldb_dn_get_linearized(msg->dn);
1435 if (dn == NULL) {
1436 return LDB_ERR_OPERATIONS_ERROR;
1439 ret = ltdb_index_add_all(module, ltdb, dn, msg->elements,
1440 msg->num_elements);
1441 if (ret != LDB_SUCCESS) {
1442 return ret;
1445 return ltdb_index_onelevel(module, msg, 1);
1450 delete an index entry for one message element
1452 int ltdb_index_del_value(struct ldb_module *module,
1453 struct ltdb_private *ltdb,
1454 struct ldb_dn *dn,
1455 struct ldb_message_element *el, unsigned int v_idx)
1457 struct ldb_context *ldb;
1458 struct ldb_dn *dn_key;
1459 const char *dn_str;
1460 int ret, i;
1461 unsigned int j;
1462 struct dn_list *list;
1464 ldb = ldb_module_get_ctx(module);
1466 dn_str = ldb_dn_get_linearized(dn);
1467 if (dn_str == NULL) {
1468 return LDB_ERR_OPERATIONS_ERROR;
1471 if (dn_str[0] == '@') {
1472 return LDB_SUCCESS;
1475 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1476 if (!dn_key) {
1477 return LDB_ERR_OPERATIONS_ERROR;
1480 list = talloc_zero(dn_key, struct dn_list);
1481 if (list == NULL) {
1482 talloc_free(dn_key);
1483 return LDB_ERR_OPERATIONS_ERROR;
1486 ret = ltdb_dn_list_load(module, dn_key, list);
1487 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1488 /* it wasn't indexed. Did we have an earlier error? If we did then
1489 its gone now */
1490 talloc_free(dn_key);
1491 return LDB_SUCCESS;
1494 if (ret != LDB_SUCCESS) {
1495 talloc_free(dn_key);
1496 return ret;
1499 i = ltdb_dn_list_find_str(ltdb, list, dn_str);
1500 if (i == -1) {
1501 /* nothing to delete */
1502 talloc_free(dn_key);
1503 return LDB_SUCCESS;
1506 j = (unsigned int) i;
1507 if (j != list->count - 1) {
1508 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
1510 list->count--;
1511 if (list->count == 0) {
1512 talloc_free(list->dn);
1513 list->dn = NULL;
1514 } else {
1515 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1518 ret = ltdb_dn_list_store(module, dn_key, list);
1520 talloc_free(dn_key);
1522 return ret;
1526 delete the index entries for a element
1527 return -1 on failure
1529 int ltdb_index_del_element(struct ldb_module *module,
1530 struct ltdb_private *ltdb,
1531 struct ldb_dn *dn,
1532 struct ldb_message_element *el)
1534 const char *dn_str;
1535 int ret;
1536 unsigned int i;
1538 if (!ltdb->cache->attribute_indexes) {
1539 /* no indexed fields */
1540 return LDB_SUCCESS;
1543 dn_str = ldb_dn_get_linearized(dn);
1544 if (dn_str == NULL) {
1545 return LDB_ERR_OPERATIONS_ERROR;
1548 if (dn_str[0] == '@') {
1549 return LDB_SUCCESS;
1552 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1553 return LDB_SUCCESS;
1555 for (i = 0; i < el->num_values; i++) {
1556 ret = ltdb_index_del_value(module, ltdb, dn, el, i);
1557 if (ret != LDB_SUCCESS) {
1558 return ret;
1562 return LDB_SUCCESS;
1566 delete the index entries for a record
1567 return -1 on failure
1569 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1571 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1572 int ret;
1573 unsigned int i;
1575 if (ldb_dn_is_special(msg->dn)) {
1576 return LDB_SUCCESS;
1579 ret = ltdb_index_onelevel(module, msg, 0);
1580 if (ret != LDB_SUCCESS) {
1581 return ret;
1584 if (!ltdb->cache->attribute_indexes) {
1585 /* no indexed fields */
1586 return LDB_SUCCESS;
1589 for (i = 0; i < msg->num_elements; i++) {
1590 ret = ltdb_index_del_element(module, ltdb,
1591 msg->dn, &msg->elements[i]);
1592 if (ret != LDB_SUCCESS) {
1593 return ret;
1597 return LDB_SUCCESS;
1602 traversal function that deletes all @INDEX records
1604 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1606 struct ldb_module *module = state;
1607 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1608 const char *dnstr = "DN=" LTDB_INDEX ":";
1609 struct dn_list list;
1610 struct ldb_dn *dn;
1611 struct ldb_val v;
1612 int ret;
1614 if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
1615 return 0;
1617 /* we need to put a empty list in the internal tdb for this
1618 * index entry */
1619 list.dn = NULL;
1620 list.count = 0;
1622 /* the offset of 3 is to remove the DN= prefix. */
1623 v.data = key.dptr + 3;
1624 v.length = strnlen((char *)key.dptr, key.dsize) - 3;
1626 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
1627 ret = ltdb_dn_list_store(module, dn, &list);
1628 if (ret != LDB_SUCCESS) {
1629 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1630 "Unable to store null index for %s\n",
1631 ldb_dn_get_linearized(dn));
1632 talloc_free(dn);
1633 return -1;
1635 talloc_free(dn);
1636 return 0;
1639 struct ltdb_reindex_context {
1640 struct ldb_module *module;
1641 int error;
1645 traversal function that adds @INDEX records during a re index
1647 static int re_key(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1649 struct ldb_context *ldb;
1650 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1651 struct ldb_module *module = ctx->module;
1652 struct ldb_message *msg;
1653 unsigned int nb_elements_in_db;
1654 const struct ldb_val val = {
1655 .data = data.dptr,
1656 .length = data.dsize,
1658 int ret;
1659 TDB_DATA key2;
1660 bool is_record;
1662 ldb = ldb_module_get_ctx(module);
1664 if (key.dsize > 4 &&
1665 memcmp(key.dptr, "DN=@", 4) == 0) {
1666 return 0;
1669 is_record = ltdb_key_is_record(key);
1670 if (is_record == false) {
1671 return 0;
1674 msg = ldb_msg_new(module);
1675 if (msg == NULL) {
1676 return -1;
1679 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
1680 msg,
1681 NULL, 0,
1682 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
1683 &nb_elements_in_db);
1684 if (ret != 0) {
1685 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1686 ldb_dn_get_linearized(msg->dn));
1687 ctx->error = ret;
1688 talloc_free(msg);
1689 return -1;
1692 if (msg->dn == NULL) {
1693 ldb_debug(ldb, LDB_DEBUG_ERROR,
1694 "Refusing to re-index as GUID "
1695 "key %*.*s with no DN\n",
1696 (int)key.dsize, (int)key.dsize,
1697 (char *)key.dptr);
1698 talloc_free(msg);
1699 return -1;
1702 /* check if the DN key has changed, perhaps due to the
1703 case insensitivity of an element changing */
1704 key2 = ltdb_key(module, msg->dn);
1705 if (key2.dptr == NULL) {
1706 /* probably a corrupt record ... darn */
1707 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1708 ldb_dn_get_linearized(msg->dn));
1709 talloc_free(msg);
1710 return 0;
1712 if (key.dsize != key2.dsize ||
1713 (memcmp(key.dptr, key2.dptr, key.dsize) != 0)) {
1714 int tdb_ret;
1715 tdb_ret = tdb_delete(tdb, key);
1716 if (tdb_ret != 0) {
1717 ldb_debug(ldb, LDB_DEBUG_ERROR,
1718 "Failed to delete %*.*s "
1719 "for rekey as %*.*s: %s",
1720 (int)key.dsize, (int)key.dsize,
1721 (const char *)key.dptr,
1722 (int)key2.dsize, (int)key2.dsize,
1723 (const char *)key.dptr,
1724 tdb_errorstr(tdb));
1725 ctx->error = ltdb_err_map(tdb_error(tdb));
1726 return -1;
1728 tdb_ret = tdb_store(tdb, key2, data, 0);
1729 if (tdb_ret != 0) {
1730 ldb_debug(ldb, LDB_DEBUG_ERROR,
1731 "Failed to rekey %*.*s as %*.*s: %s",
1732 (int)key.dsize, (int)key.dsize,
1733 (const char *)key.dptr,
1734 (int)key2.dsize, (int)key2.dsize,
1735 (const char *)key.dptr,
1736 tdb_errorstr(tdb));
1737 ctx->error = ltdb_err_map(tdb_error(tdb));
1738 return -1;
1741 talloc_free(key2.dptr);
1743 talloc_free(msg);
1745 return 0;
1749 traversal function that adds @INDEX records during a re index
1751 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1753 struct ldb_context *ldb;
1754 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1755 struct ldb_module *module = ctx->module;
1756 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
1757 struct ltdb_private);
1758 struct ldb_message *msg;
1759 const char *dn = NULL;
1760 unsigned int nb_elements_in_db;
1761 const struct ldb_val val = {
1762 .data = data.dptr,
1763 .length = data.dsize,
1765 int ret;
1766 bool is_record;
1768 ldb = ldb_module_get_ctx(module);
1770 if (key.dsize > 4 &&
1771 memcmp(key.dptr, "DN=@", 4) == 0) {
1772 return 0;
1775 is_record = ltdb_key_is_record(key);
1776 if (is_record == false) {
1777 return 0;
1780 msg = ldb_msg_new(module);
1781 if (msg == NULL) {
1782 return -1;
1785 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
1786 msg,
1787 NULL, 0,
1788 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
1789 &nb_elements_in_db);
1790 if (ret != 0) {
1791 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1792 ldb_dn_get_linearized(msg->dn));
1793 ctx->error = ret;
1794 talloc_free(msg);
1795 return -1;
1798 if (msg->dn == NULL) {
1799 ldb_debug(ldb, LDB_DEBUG_ERROR,
1800 "Refusing to re-index as GUID "
1801 "key %*.*s with no DN\n",
1802 (int)key.dsize, (int)key.dsize,
1803 (char *)key.dptr);
1804 talloc_free(msg);
1805 return -1;
1806 } else {
1807 dn = ldb_dn_get_linearized(msg->dn);
1810 ret = ltdb_index_onelevel(module, msg, 1);
1811 if (ret != LDB_SUCCESS) {
1812 ldb_debug(ldb, LDB_DEBUG_ERROR,
1813 "Adding special ONE LEVEL index failed (%s)!",
1814 ldb_dn_get_linearized(msg->dn));
1815 talloc_free(msg);
1816 return -1;
1819 ret = ltdb_index_add_all(module, ltdb, dn,
1820 msg->elements, msg->num_elements);
1822 if (ret != LDB_SUCCESS) {
1823 ctx->error = ret;
1824 talloc_free(msg);
1825 return -1;
1828 talloc_free(msg);
1830 return 0;
1834 force a complete reindex of the database
1836 int ltdb_reindex(struct ldb_module *module)
1838 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1839 int ret;
1840 struct ltdb_reindex_context ctx;
1842 if (ltdb_cache_reload(module) != 0) {
1843 return LDB_ERR_OPERATIONS_ERROR;
1847 * Ensure we read (and so remove) the entries from the real
1848 * DB, no values stored so far are any use as we want to do a
1849 * re-index
1851 ltdb_index_transaction_cancel(module);
1853 ret = ltdb_index_transaction_start(module);
1854 if (ret != LDB_SUCCESS) {
1855 return ret;
1858 /* first traverse the database deleting any @INDEX records by
1859 * putting NULL entries in the in-memory tdb
1861 ret = tdb_traverse(ltdb->tdb, delete_index, module);
1862 if (ret < 0) {
1863 struct ldb_context *ldb = ldb_module_get_ctx(module);
1864 ldb_asprintf_errstring(ldb, "index deletion traverse failed: %s",
1865 ldb_errstring(ldb));
1866 return LDB_ERR_OPERATIONS_ERROR;
1869 /* if we don't have indexes we have nothing todo */
1870 if (!ltdb->cache->attribute_indexes) {
1871 return LDB_SUCCESS;
1874 ctx.module = module;
1875 ctx.error = 0;
1877 /* now traverse adding any indexes for normal LDB records */
1878 ret = tdb_traverse(ltdb->tdb, re_key, &ctx);
1879 if (ret < 0) {
1880 struct ldb_context *ldb = ldb_module_get_ctx(module);
1881 ldb_asprintf_errstring(ldb, "key correction traverse failed: %s",
1882 ldb_errstring(ldb));
1883 return LDB_ERR_OPERATIONS_ERROR;
1886 if (ctx.error != LDB_SUCCESS) {
1887 struct ldb_context *ldb = ldb_module_get_ctx(module);
1888 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
1889 return ctx.error;
1892 ctx.error = 0;
1894 /* now traverse adding any indexes for normal LDB records */
1895 ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
1896 if (ret < 0) {
1897 struct ldb_context *ldb = ldb_module_get_ctx(module);
1898 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s",
1899 ldb_errstring(ldb));
1900 return LDB_ERR_OPERATIONS_ERROR;
1903 if (ctx.error != LDB_SUCCESS) {
1904 struct ldb_context *ldb = ldb_module_get_ctx(module);
1905 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
1906 return ctx.error;
1909 return LDB_SUCCESS;