2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8 ** NOTE! The following LGPL license applies to the ldb
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "ldb_includes.h"
30 #include "ldb_map_private.h"
34 * ================== */
36 /* Select attributes that stay in the local partition. */
37 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
39 const struct ldb_map_context *data = map_get_context(module);
47 result = talloc_array(mem_ctx, const char *, 1);
53 for (i = 0; attrs[i]; i++) {
54 /* Wildcards and ignored attributes are kept locally */
55 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
56 (!map_attr_check_remote(data, attrs[i]))) {
57 result = talloc_realloc(mem_ctx, result, const char *, last+2);
62 result[last] = talloc_strdup(result, attrs[i]);
63 result[last+1] = NULL;
76 /* Collect attributes that are mapped into the remote partition. */
77 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx,
78 const char * const *attrs)
80 const struct ldb_map_context *data = map_get_context(module);
82 const struct ldb_map_attribute *map;
83 const char *name=NULL;
88 result = talloc_array(mem_ctx, const char *, 1);
94 for (i = 0; attrs[i]; i++) {
95 /* Wildcards are kept remotely, too */
96 if (ldb_attr_cmp(attrs[i], "*") == 0) {
97 const char **new_attrs = NULL;
98 ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
99 if (ret != LDB_SUCCESS) {
102 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
103 if (ret != LDB_SUCCESS) {
112 for (i = 0; attrs[i]; i++) {
113 /* Wildcards are kept remotely, too */
114 if (ldb_attr_cmp(attrs[i], "*") == 0) {
115 /* Add all 'include in wildcard' attributes */
120 /* Add remote names of mapped attrs */
121 map = map_attr_find_local(data, attrs[i]);
136 name = map->u.rename.remote_name;
140 /* Add all remote names of "generate" attrs */
141 for (j = 0; map->u.generate.remote_names[j]; j++) {
142 result = talloc_realloc(mem_ctx, result, const char *, last+2);
143 if (result == NULL) {
147 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
148 result[last+1] = NULL;
154 named: /* We found a single remote name, add that */
155 result = talloc_realloc(mem_ctx, result, const char *, last+2);
156 if (result == NULL) {
160 result[last] = talloc_strdup(result, name);
161 result[last+1] = NULL;
173 /* Split attributes that stay in the local partition from those that
174 * are mapped into the remote partition. */
175 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
177 *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
178 *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
183 /* Mapping message elements
184 * ======================== */
186 /* Add an element to a message, overwriting any old identically named elements. */
187 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
189 struct ldb_message_element *old;
191 old = ldb_msg_find_element(msg, el->name);
193 /* no local result, add as new element */
195 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
198 talloc_free(discard_const_p(char, old->name));
201 /* copy new element */
204 /* and make sure we reference the contents */
205 if (!talloc_reference(msg->elements, el->name)) {
208 if (!talloc_reference(msg->elements, el->values)) {
215 /* Map a message element back into the local partition. */
216 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
218 const struct ldb_map_attribute *map,
219 const char *attr_name,
220 const struct ldb_message_element *old)
222 struct ldb_message_element *el;
225 el = talloc_zero(mem_ctx, struct ldb_message_element);
231 el->values = talloc_array(el, struct ldb_val, old->num_values);
232 if (el->values == NULL) {
238 el->name = talloc_strdup(el, attr_name);
239 if (el->name == NULL) {
245 for (i = 0; i < old->num_values; i++) {
246 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
247 /* Conversions might fail, in which case bail */
248 if (!el->values[i].data) {
258 /* Merge a remote message element into a local message. */
259 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
260 struct ldb_message *remote, const char *attr_name)
262 const struct ldb_map_context *data = map_get_context(module);
263 const struct ldb_map_attribute *map;
264 struct ldb_message_element *old, *el=NULL;
265 const char *remote_name = NULL;
267 /* We handle wildcards in ldb_msg_el_merge_wildcard */
268 if (ldb_attr_cmp(attr_name, "*") == 0) {
272 map = map_attr_find_local(data, attr_name);
274 /* Unknown attribute in remote message:
275 * skip, attribute was probably auto-generated */
284 remote_name = map->u.convert.remote_name;
287 remote_name = attr_name;
290 remote_name = map->u.rename.remote_name;
301 if (map->u.convert.convert_remote == NULL) {
302 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
303 "Skipping attribute '%s': "
304 "'convert_remote' not set\n",
311 old = ldb_msg_find_element(remote, remote_name);
313 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
315 return LDB_ERR_NO_SUCH_ATTRIBUTE;
320 if (map->u.generate.generate_local == NULL) {
321 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
322 "Skipping attribute '%s': "
323 "'generate_local' not set\n",
328 el = map->u.generate.generate_local(module, local, attr_name, remote);
330 /* Generation failure is probably due to lack of source attributes */
331 return LDB_ERR_NO_SUCH_ATTRIBUTE;
337 return LDB_ERR_NO_SUCH_ATTRIBUTE;
340 return ldb_msg_replace(local, el);
343 /* Handle wildcard parts of merging a remote message element into a local message. */
344 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
345 struct ldb_message *remote)
347 const struct ldb_map_context *data = map_get_context(module);
348 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
349 struct ldb_message_element *el=NULL;
352 /* Perhaps we have a mapping for "*" */
353 if (map && map->type == MAP_KEEP) {
354 /* We copy everything over, and hope that anything with a
355 more specific rule is overwritten */
356 for (i = 0; i < remote->num_elements; i++) {
357 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
358 &remote->elements[i]);
360 return LDB_ERR_OPERATIONS_ERROR;
363 ret = ldb_msg_replace(local, el);
370 /* Now walk the list of possible mappings, and apply each */
371 for (i = 0; data->attribute_maps[i].local_name; i++) {
372 ret = ldb_msg_el_merge(module, local, remote,
373 data->attribute_maps[i].local_name);
374 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
387 * ================ */
389 /* Merge two local messages into a single one. */
390 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
394 for (i = 0; i < msg2->num_elements; i++) {
395 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
404 /* Merge a local and a remote message into a single local one. */
405 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
406 struct ldb_message *remote)
409 const char * const *attrs = ac->all_attrs;
411 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
417 for (i = 0; attrs && attrs[i]; i++) {
418 if (ldb_attr_cmp(attrs[i], "*") == 0) {
419 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
427 /* Try to map each attribute back;
428 * Add to local message is possible,
429 * Overwrite old local attribute if necessary */
430 for (i = 0; attrs && attrs[i]; i++) {
431 ret = ldb_msg_el_merge(ac->module, local, remote,
433 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
442 /* Mapping search results
443 * ====================== */
445 /* Map a search result back into the local partition. */
446 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
448 struct ldb_message *msg;
452 /* There is no result message, skip */
453 if (ares->type != LDB_REPLY_ENTRY) {
457 /* Create a new result message */
458 msg = ldb_msg_new(ares);
464 /* Merge remote message into new message */
465 ret = ldb_msg_merge_remote(ac, msg, ares->message);
471 /* Create corresponding local DN */
472 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
479 /* Store new message with new DN as the result */
480 talloc_free(ares->message);
486 /* Mapping parse trees
487 * =================== */
489 /* Check whether a parse tree can safely be split in two. */
490 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
492 const struct ldb_parse_tree *subtree = tree;
496 switch (subtree->operation) {
499 subtree = subtree->u.isnot.child;
503 return !negate; /* if negate: False */
506 return negate; /* if negate: True */
509 return true; /* simple parse tree */
513 return true; /* no parse tree */
516 /* Collect a list of attributes required to match a given parse tree. */
517 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
519 const char **new_attrs;
526 switch (tree->operation) {
528 case LDB_OP_AND: /* attributes stored in list of subtrees */
529 for (i = 0; i < tree->u.list.num_elements; i++) {
530 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
531 attrs, tree->u.list.elements[i]);
538 case LDB_OP_NOT: /* attributes stored in single subtree */
539 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
541 default: /* single attribute in tree */
542 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
551 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
553 /* Select a negated subtree that queries attributes in the local partition */
554 static int map_subtree_select_local_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
556 struct ldb_parse_tree *child;
559 /* Prepare new tree */
560 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
566 /* Generate new subtree */
567 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
573 /* Prune tree without subtree */
580 (*new)->u.isnot.child = child;
585 /* Select a list of subtrees that query attributes in the local partition */
586 static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
590 /* Prepare new tree */
591 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
597 /* Prepare list of subtrees */
598 (*new)->u.list.num_elements = 0;
599 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
600 if ((*new)->u.list.elements == NULL) {
606 /* Generate new list of subtrees */
608 for (i = 0; i < tree->u.list.num_elements; i++) {
609 struct ldb_parse_tree *child;
610 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
617 (*new)->u.list.elements[j] = child;
622 /* Prune tree without subtrees */
629 /* Fix subtree list size */
630 (*new)->u.list.num_elements = j;
631 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
636 /* Select a simple subtree that queries attributes in the local partition */
637 static int map_subtree_select_local_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
639 /* Prepare new tree */
640 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
649 /* Select subtrees that query attributes in the local partition */
650 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
652 const struct ldb_map_context *data = map_get_context(module);
658 if (tree->operation == LDB_OP_NOT) {
659 return map_subtree_select_local_not(module, mem_ctx, new, tree);
662 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
663 return map_subtree_select_local_list(module, mem_ctx, new, tree);
666 if (map_attr_check_remote(data, tree->u.equality.attr)) {
671 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
674 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
676 /* Collect a negated subtree that queries attributes in the remote partition */
677 static int map_subtree_collect_remote_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
679 struct ldb_parse_tree *child;
682 /* Prepare new tree */
683 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
689 /* Generate new subtree */
690 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
696 /* Prune tree without subtree */
703 (*new)->u.isnot.child = child;
708 /* Collect a list of subtrees that query attributes in the remote partition */
709 static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
713 /* Prepare new tree */
714 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
720 /* Prepare list of subtrees */
721 (*new)->u.list.num_elements = 0;
722 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
723 if ((*new)->u.list.elements == NULL) {
729 /* Generate new list of subtrees */
731 for (i = 0; i < tree->u.list.num_elements; i++) {
732 struct ldb_parse_tree *child;
733 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
740 (*new)->u.list.elements[j] = child;
745 /* Prune tree without subtrees */
752 /* Fix subtree list size */
753 (*new)->u.list.num_elements = j;
754 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
759 /* Collect a simple subtree that queries attributes in the remote partition */
760 int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree, const struct ldb_map_attribute *map)
764 /* Prepare new tree */
765 *new = talloc(mem_ctx, struct ldb_parse_tree);
772 if (map->type == MAP_KEEP) {
773 /* Nothing to do here */
777 /* Store attribute and value in new tree */
778 switch (tree->operation) {
780 attr = map_attr_map_local(*new, map, tree->u.present.attr);
781 (*new)->u.present.attr = attr;
783 case LDB_OP_SUBSTRING:
785 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
786 (*new)->u.substring.attr = attr;
789 case LDB_OP_EQUALITY:
790 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
791 (*new)->u.equality.attr = attr;
796 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
797 (*new)->u.comparison.attr = attr;
799 case LDB_OP_EXTENDED:
800 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
801 (*new)->u.extended.attr = attr;
803 default: /* unknown kind of simple subtree */
814 if (map->type == MAP_RENAME) {
815 /* Nothing more to do here, the attribute has been renamed */
819 /* Store attribute and value in new tree */
820 switch (tree->operation) {
823 case LDB_OP_SUBSTRING:
827 (*new)->u.substring.chunks = NULL;
828 for (i=0; tree->u.substring.chunks[i]; i++) {
829 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
830 if (!(*new)->u.substring.chunks) {
835 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
836 if (!(*new)->u.substring.chunks[i]) {
841 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
842 (*new)->u.substring.chunks[i+1] = NULL;
846 case LDB_OP_EQUALITY:
847 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
852 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
854 case LDB_OP_EXTENDED:
855 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
856 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
858 default: /* unknown kind of simple subtree */
866 /* Collect subtrees that query attributes in the remote partition */
867 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
869 const struct ldb_map_context *data = map_get_context(module);
870 const struct ldb_map_attribute *map;
876 if (tree->operation == LDB_OP_NOT) {
877 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
880 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
881 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
884 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
889 map = map_attr_find_local(data, tree->u.equality.attr);
890 if (map->convert_operator) {
891 return map->convert_operator(module, mem_ctx, new, tree);
894 if (map->type == MAP_GENERATE) {
895 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
896 "Skipping attribute '%s': "
897 "'convert_operator' not set\n",
898 tree->u.equality.attr);
903 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
906 /* Split subtrees that query attributes in the local partition from
907 * those that query the remote partition. */
908 static int ldb_parse_tree_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, struct ldb_parse_tree **local_tree, struct ldb_parse_tree **remote_tree, const struct ldb_parse_tree *tree)
915 /* No original tree */
920 /* Generate local tree */
921 ret = map_subtree_select_local(module, local_ctx, local_tree, tree);
926 /* Generate remote tree */
927 ret = map_subtree_collect_remote(module, remote_ctx, remote_tree, tree);
929 talloc_free(*local_tree);
936 /* Collect a list of attributes required either explicitly from a
937 * given list or implicitly from a given parse tree; split the
938 * collected list into local and remote parts. */
939 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
940 const char * const *search_attrs,
941 const struct ldb_parse_tree *tree)
944 const char **tree_attrs;
945 const char **remote_attrs;
946 const char **local_attrs;
949 /* There is no tree, just partition the searched attributes */
951 ret = map_attrs_partition(module, ac,
952 &local_attrs, &remote_attrs, search_attrs);
954 ac->local_attrs = local_attrs;
955 ac->remote_attrs = remote_attrs;
956 ac->all_attrs = search_attrs;
961 /* Create context for temporary memory */
962 tmp_ctx = talloc_new(ac);
963 if (tmp_ctx == NULL) {
967 /* Prepare list of attributes from tree */
968 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
969 if (tree_attrs == NULL) {
970 talloc_free(tmp_ctx);
973 tree_attrs[0] = NULL;
975 /* Collect attributes from tree */
976 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
981 /* Merge attributes from search operation */
982 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
987 /* Split local from remote attributes */
988 ret = map_attrs_partition(module, ac, &local_attrs,
989 &remote_attrs, tree_attrs);
992 ac->local_attrs = local_attrs;
993 ac->remote_attrs = remote_attrs;
994 talloc_steal(ac, tree_attrs);
995 ac->all_attrs = tree_attrs;
998 /* Free temporary memory */
999 talloc_free(tmp_ctx);
1008 /* Outbound requests: search
1009 * ========================= */
1011 /* Pass a merged search result up the callback chain. */
1012 int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, struct ldb_reply *ares)
1016 /* No callback registered, stop */
1017 if (req->callback == NULL) {
1021 /* Only records need special treatment */
1022 if (ares->type != LDB_REPLY_ENTRY) {
1023 return req->callback(ldb, req->context, ares);
1026 /* Merged result doesn't match original query, skip */
1027 if (!ldb_match_msg(ldb, ares->message, req->op.search.tree, req->op.search.base, req->op.search.scope)) {
1028 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1029 "Skipping record '%s': "
1030 "doesn't match original search\n",
1031 ldb_dn_get_linearized(ares->message->dn));
1035 /* Limit result to requested attrs */
1036 if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) {
1037 for (i = 0; i < ares->message->num_elements; ) {
1038 struct ldb_message_element *el = &ares->message->elements[i];
1039 if (!ldb_attr_in_list(req->op.search.attrs, el->name)) {
1040 ldb_msg_remove_element(ares->message, el);
1047 return req->callback(ldb, req->context, ares);
1050 /* Merge the remote and local parts of a search result. */
1051 int map_local_merge_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
1053 struct map_search_context *sc;
1056 if (context == NULL || ares == NULL) {
1057 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1058 "NULL Context or Result in `map_local_merge_callback`"));
1059 return LDB_ERR_OPERATIONS_ERROR;
1062 sc = talloc_get_type(context, struct map_search_context);
1064 switch (ares->type) {
1065 case LDB_REPLY_ENTRY:
1066 /* We have already found a local record */
1067 if (sc->local_res) {
1068 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1069 "Too many results to base search for local entry"));
1071 return LDB_ERR_OPERATIONS_ERROR;
1074 /* Store local result */
1075 sc->local_res = ares;
1077 /* Merge remote into local message */
1078 ret = ldb_msg_merge_local(sc->ac->module, ares->message, sc->remote_res->message);
1081 return LDB_ERR_OPERATIONS_ERROR;
1084 return map_up_callback(ldb, sc->ac->orig_req, ares);
1086 case LDB_REPLY_DONE:
1087 /* No local record found, continue with remote record */
1088 if (sc->local_res == NULL) {
1089 return map_up_callback(ldb, sc->ac->orig_req, sc->remote_res);
1094 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1095 "Unexpected result type in base search for local entry"));
1097 return LDB_ERR_OPERATIONS_ERROR;
1101 /* Search the local part of a remote search result. */
1102 int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
1104 struct map_context *ac;
1105 struct map_search_context *sc;
1106 struct ldb_request *req;
1109 if (context == NULL || ares == NULL) {
1110 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1111 "NULL Context or Result in `map_remote_search_callback`"));
1112 return LDB_ERR_OPERATIONS_ERROR;
1115 ac = talloc_get_type(context, struct map_context);
1117 /* It's not a record, stop searching */
1118 if (ares->type != LDB_REPLY_ENTRY) {
1119 return map_up_callback(ldb, ac->orig_req, ares);
1122 /* Map result record into a local message */
1123 ret = map_reply_remote(ac, ares);
1126 return LDB_ERR_OPERATIONS_ERROR;
1129 /* There is no local db, stop searching */
1130 if (!map_check_local_db(ac->module)) {
1131 return map_up_callback(ldb, ac->orig_req, ares);
1134 /* Prepare local search context */
1135 sc = map_init_search_context(ac, ares);
1138 return LDB_ERR_OPERATIONS_ERROR;
1141 /* Prepare local search request */
1142 /* TODO: use GUIDs here instead? */
1144 ac->search_reqs = talloc_realloc(ac, ac->search_reqs, struct ldb_request *, ac->num_searches + 2);
1145 if (ac->search_reqs == NULL) {
1147 return LDB_ERR_OPERATIONS_ERROR;
1150 ac->search_reqs[ac->num_searches]
1151 = req = map_search_base_req(ac, ares->message->dn,
1152 NULL, NULL, sc, map_local_merge_callback);
1156 return LDB_ERR_OPERATIONS_ERROR;
1159 ac->search_reqs[ac->num_searches] = NULL;
1161 return ldb_next_request(ac->module, req);
1164 /* Search a record. */
1165 int map_search(struct ldb_module *module, struct ldb_request *req)
1167 struct ldb_handle *h;
1168 struct map_context *ac;
1169 struct ldb_parse_tree *local_tree, *remote_tree;
1172 const char *wildcard[] = { "*", NULL };
1173 const char * const *attrs;
1175 if (!module->private_data) /* if we're not yet initialized, go to the next module */
1176 return ldb_next_request(module, req);
1178 /* Do not manipulate our control entries */
1179 if (ldb_dn_is_special(req->op.search.base))
1180 return ldb_next_request(module, req);
1182 /* No mapping requested, skip to next module */
1183 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1184 return ldb_next_request(module, req);
1187 /* TODO: How can we be sure about which partition we are
1188 * targetting when there is no search base? */
1190 /* Prepare context and handle */
1191 h = map_init_handle(req, module);
1193 return LDB_ERR_OPERATIONS_ERROR;
1195 ac = talloc_get_type(h->private_data, struct map_context);
1197 ac->search_reqs = talloc_array(ac, struct ldb_request *, 2);
1198 if (ac->search_reqs == NULL) {
1200 return LDB_ERR_OPERATIONS_ERROR;
1202 ac->num_searches = 1;
1203 ac->search_reqs[1] = NULL;
1205 /* Prepare the remote operation */
1206 ac->search_reqs[0] = talloc(ac, struct ldb_request);
1207 if (ac->search_reqs[0] == NULL) {
1211 *(ac->search_reqs[0]) = *req; /* copy the request */
1213 ac->search_reqs[0]->handle = h; /* return our own handle to deal with this call */
1215 ac->search_reqs[0]->context = ac;
1216 ac->search_reqs[0]->callback = map_remote_search_callback;
1218 /* It is easier to deal with the two different ways of
1219 * expressing the wildcard in the same codepath */
1220 attrs = req->op.search.attrs;
1221 if (attrs == NULL) {
1225 /* Split local from remote attrs */
1226 ret = map_attrs_collect_and_partition(module, ac,
1227 attrs, req->op.search.tree);
1232 ac->search_reqs[0]->op.search.attrs = ac->remote_attrs;
1234 /* Split local from remote tree */
1235 ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0],
1236 &local_tree, &remote_tree,
1237 req->op.search.tree);
1242 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1243 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1244 /* The query can't safely be split, enumerate the remote partition */
1249 if (local_tree == NULL) {
1250 /* Construct default local parse tree */
1251 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1252 if (local_tree == NULL) {
1253 map_oom(ac->module);
1257 local_tree->operation = LDB_OP_PRESENT;
1258 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1260 if (remote_tree == NULL) {
1261 /* Construct default remote parse tree */
1262 remote_tree = ldb_parse_tree(ac->search_reqs[0], NULL);
1263 if (remote_tree == NULL) {
1268 ac->local_tree = local_tree;
1269 ac->search_reqs[0]->op.search.tree = remote_tree;
1271 ldb_set_timeout_from_prev_req(module->ldb, req, ac->search_reqs[0]);
1273 h->state = LDB_ASYNC_INIT;
1274 h->status = LDB_SUCCESS;
1276 ac->step = MAP_SEARCH_REMOTE;
1278 ret = ldb_next_remote_request(module, ac->search_reqs[0]);
1279 if (ret == LDB_SUCCESS) {
1288 return LDB_ERR_OPERATIONS_ERROR;