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
7 Copyright (C) Simo Sorce <idra@samba.org> 2008
9 ** NOTE! The following LGPL license applies to the ldb
10 ** library. This does NOT imply that all of Samba is released
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 3 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 #include "ldb_map_private.h"
33 * ================== */
35 /* Select attributes that stay in the local partition. */
36 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
38 const struct ldb_map_context *data = map_get_context(module);
46 result = talloc_array(mem_ctx, const char *, 1);
52 for (i = 0; attrs[i]; i++) {
53 /* Wildcards and ignored attributes are kept locally */
54 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
55 (!map_attr_check_remote(data, attrs[i]))) {
56 result = talloc_realloc(mem_ctx, result, const char *, last+2);
61 result[last] = talloc_strdup(result, attrs[i]);
62 result[last+1] = NULL;
75 /* Collect attributes that are mapped into the remote partition. */
76 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx,
77 const char * const *attrs)
79 const struct ldb_map_context *data = map_get_context(module);
81 const struct ldb_map_attribute *map;
82 const char *name=NULL;
87 result = talloc_array(mem_ctx, const char *, 1);
93 for (i = 0; attrs[i]; i++) {
94 /* Wildcards are kept remotely, too */
95 if (ldb_attr_cmp(attrs[i], "*") == 0) {
96 const char **new_attrs = NULL;
97 ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
98 if (ret != LDB_SUCCESS) {
101 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
102 if (ret != LDB_SUCCESS) {
111 for (i = 0; attrs[i]; i++) {
112 /* Wildcards are kept remotely, too */
113 if (ldb_attr_cmp(attrs[i], "*") == 0) {
114 /* Add all 'include in wildcard' attributes */
119 /* Add remote names of mapped attrs */
120 map = map_attr_find_local(data, attrs[i]);
135 name = map->u.rename.remote_name;
139 /* Add all remote names of "generate" attrs */
140 for (j = 0; map->u.generate.remote_names[j]; j++) {
141 result = talloc_realloc(mem_ctx, result, const char *, last+2);
142 if (result == NULL) {
146 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
147 result[last+1] = NULL;
153 named: /* We found a single remote name, add that */
154 result = talloc_realloc(mem_ctx, result, const char *, last+2);
155 if (result == NULL) {
159 result[last] = talloc_strdup(result, name);
160 result[last+1] = NULL;
172 /* Split attributes that stay in the local partition from those that
173 * are mapped into the remote partition. */
174 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
176 *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
177 *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
182 /* Mapping message elements
183 * ======================== */
185 /* Add an element to a message, overwriting any old identically named elements. */
186 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
188 struct ldb_message_element *old;
190 old = ldb_msg_find_element(msg, el->name);
192 /* no local result, add as new element */
194 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
197 talloc_free(discard_const_p(char, old->name));
200 /* copy new element */
203 /* and make sure we reference the contents */
204 if (!talloc_reference(msg->elements, el->name)) {
207 if (!talloc_reference(msg->elements, el->values)) {
214 /* Map a message element back into the local partition. */
215 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
217 const struct ldb_map_attribute *map,
218 const char *attr_name,
219 const struct ldb_message_element *old)
221 struct ldb_message_element *el;
224 el = talloc_zero(mem_ctx, struct ldb_message_element);
230 el->values = talloc_array(el, struct ldb_val, old->num_values);
231 if (el->values == NULL) {
237 el->name = talloc_strdup(el, attr_name);
238 if (el->name == NULL) {
244 for (i = 0; i < old->num_values; i++) {
245 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
246 /* Conversions might fail, in which case bail */
247 if (!el->values[i].data) {
257 /* Merge a remote message element into a local message. */
258 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
259 struct ldb_message *remote, const char *attr_name)
261 const struct ldb_map_context *data = map_get_context(module);
262 const struct ldb_map_attribute *map;
263 struct ldb_message_element *old, *el=NULL;
264 const char *remote_name = NULL;
265 struct ldb_context *ldb;
267 ldb = ldb_module_get_ctx(module);
269 /* We handle wildcards in ldb_msg_el_merge_wildcard */
270 if (ldb_attr_cmp(attr_name, "*") == 0) {
274 map = map_attr_find_local(data, attr_name);
276 /* Unknown attribute in remote message:
277 * skip, attribute was probably auto-generated */
286 remote_name = map->u.convert.remote_name;
289 remote_name = attr_name;
292 remote_name = map->u.rename.remote_name;
303 if (map->u.convert.convert_remote == NULL) {
304 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
305 "Skipping attribute '%s': "
306 "'convert_remote' not set\n",
313 old = ldb_msg_find_element(remote, remote_name);
315 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
317 return LDB_ERR_NO_SUCH_ATTRIBUTE;
322 if (map->u.generate.generate_local == NULL) {
323 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
324 "Skipping attribute '%s': "
325 "'generate_local' not set\n",
330 el = map->u.generate.generate_local(module, local, attr_name, remote);
332 /* Generation failure is probably due to lack of source attributes */
333 return LDB_ERR_NO_SUCH_ATTRIBUTE;
339 return LDB_ERR_NO_SUCH_ATTRIBUTE;
342 return ldb_msg_replace(local, el);
345 /* Handle wildcard parts of merging a remote message element into a local message. */
346 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
347 struct ldb_message *remote)
349 const struct ldb_map_context *data = map_get_context(module);
350 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
351 struct ldb_message_element *el=NULL;
354 /* Perhaps we have a mapping for "*" */
355 if (map && map->type == MAP_KEEP) {
356 /* We copy everything over, and hope that anything with a
357 more specific rule is overwritten */
358 for (i = 0; i < remote->num_elements; i++) {
359 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
360 &remote->elements[i]);
362 return LDB_ERR_OPERATIONS_ERROR;
365 ret = ldb_msg_replace(local, el);
372 /* Now walk the list of possible mappings, and apply each */
373 for (i = 0; data->attribute_maps[i].local_name; i++) {
374 ret = ldb_msg_el_merge(module, local, remote,
375 data->attribute_maps[i].local_name);
376 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
389 * ================ */
391 /* Merge two local messages into a single one. */
392 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
396 for (i = 0; i < msg2->num_elements; i++) {
397 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
406 /* Merge a local and a remote message into a single local one. */
407 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
408 struct ldb_message *remote)
411 const char * const *attrs = ac->all_attrs;
413 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
419 for (i = 0; attrs && attrs[i]; i++) {
420 if (ldb_attr_cmp(attrs[i], "*") == 0) {
421 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
429 /* Try to map each attribute back;
430 * Add to local message is possible,
431 * Overwrite old local attribute if necessary */
432 for (i = 0; attrs && attrs[i]; i++) {
433 ret = ldb_msg_el_merge(ac->module, local, remote,
435 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
444 /* Mapping search results
445 * ====================== */
447 /* Map a search result back into the local partition. */
448 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
450 struct ldb_message *msg;
454 /* There is no result message, skip */
455 if (ares->type != LDB_REPLY_ENTRY) {
459 /* Create a new result message */
460 msg = ldb_msg_new(ares);
466 /* Merge remote message into new message */
467 ret = ldb_msg_merge_remote(ac, msg, ares->message);
473 /* Create corresponding local DN */
474 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
481 /* Store new message with new DN as the result */
482 talloc_free(ares->message);
488 /* Mapping parse trees
489 * =================== */
491 /* Check whether a parse tree can safely be split in two. */
492 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
494 const struct ldb_parse_tree *subtree = tree;
498 switch (subtree->operation) {
501 subtree = subtree->u.isnot.child;
505 return !negate; /* if negate: False */
508 return negate; /* if negate: True */
511 return true; /* simple parse tree */
515 return true; /* no parse tree */
518 /* Collect a list of attributes required to match a given parse tree. */
519 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
521 const char **new_attrs;
528 switch (tree->operation) {
530 case LDB_OP_AND: /* attributes stored in list of subtrees */
531 for (i = 0; i < tree->u.list.num_elements; i++) {
532 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
533 attrs, tree->u.list.elements[i]);
540 case LDB_OP_NOT: /* attributes stored in single subtree */
541 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
543 default: /* single attribute in tree */
544 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
553 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
555 /* Select a negated subtree that queries attributes in the local partition */
556 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)
558 struct ldb_parse_tree *child;
561 /* Prepare new tree */
562 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
568 /* Generate new subtree */
569 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
575 /* Prune tree without subtree */
582 (*new)->u.isnot.child = child;
587 /* Select a list of subtrees that query attributes in the local partition */
588 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)
592 /* Prepare new tree */
593 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
599 /* Prepare list of subtrees */
600 (*new)->u.list.num_elements = 0;
601 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
602 if ((*new)->u.list.elements == NULL) {
608 /* Generate new list of subtrees */
610 for (i = 0; i < tree->u.list.num_elements; i++) {
611 struct ldb_parse_tree *child;
612 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
619 (*new)->u.list.elements[j] = child;
624 /* Prune tree without subtrees */
631 /* Fix subtree list size */
632 (*new)->u.list.num_elements = j;
633 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
638 /* Select a simple subtree that queries attributes in the local partition */
639 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)
641 /* Prepare new tree */
642 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
651 /* Select subtrees that query attributes in the local partition */
652 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
654 const struct ldb_map_context *data = map_get_context(module);
660 if (tree->operation == LDB_OP_NOT) {
661 return map_subtree_select_local_not(module, mem_ctx, new, tree);
664 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
665 return map_subtree_select_local_list(module, mem_ctx, new, tree);
668 if (map_attr_check_remote(data, tree->u.equality.attr)) {
673 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
676 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
678 /* Collect a negated subtree that queries attributes in the remote partition */
679 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)
681 struct ldb_parse_tree *child;
684 /* Prepare new tree */
685 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
691 /* Generate new subtree */
692 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
698 /* Prune tree without subtree */
705 (*new)->u.isnot.child = child;
710 /* Collect a list of subtrees that query attributes in the remote partition */
711 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)
715 /* Prepare new tree */
716 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
722 /* Prepare list of subtrees */
723 (*new)->u.list.num_elements = 0;
724 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
725 if ((*new)->u.list.elements == NULL) {
731 /* Generate new list of subtrees */
733 for (i = 0; i < tree->u.list.num_elements; i++) {
734 struct ldb_parse_tree *child;
735 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
742 (*new)->u.list.elements[j] = child;
747 /* Prune tree without subtrees */
754 /* Fix subtree list size */
755 (*new)->u.list.num_elements = j;
756 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
761 /* Collect a simple subtree that queries attributes in the remote partition */
762 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)
766 /* Prepare new tree */
767 *new = talloc(mem_ctx, struct ldb_parse_tree);
774 if (map->type == MAP_KEEP) {
775 /* Nothing to do here */
779 /* Store attribute and value in new tree */
780 switch (tree->operation) {
782 attr = map_attr_map_local(*new, map, tree->u.present.attr);
783 (*new)->u.present.attr = attr;
785 case LDB_OP_SUBSTRING:
787 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
788 (*new)->u.substring.attr = attr;
791 case LDB_OP_EQUALITY:
792 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
793 (*new)->u.equality.attr = attr;
798 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
799 (*new)->u.comparison.attr = attr;
801 case LDB_OP_EXTENDED:
802 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
803 (*new)->u.extended.attr = attr;
805 default: /* unknown kind of simple subtree */
816 if (map->type == MAP_RENAME) {
817 /* Nothing more to do here, the attribute has been renamed */
821 /* Store attribute and value in new tree */
822 switch (tree->operation) {
825 case LDB_OP_SUBSTRING:
829 (*new)->u.substring.chunks = NULL;
830 for (i=0; tree->u.substring.chunks[i]; i++) {
831 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
832 if (!(*new)->u.substring.chunks) {
837 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
838 if (!(*new)->u.substring.chunks[i]) {
843 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
844 (*new)->u.substring.chunks[i+1] = NULL;
848 case LDB_OP_EQUALITY:
849 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
854 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
856 case LDB_OP_EXTENDED:
857 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
858 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
860 default: /* unknown kind of simple subtree */
868 /* Collect subtrees that query attributes in the remote partition */
869 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
871 const struct ldb_map_context *data = map_get_context(module);
872 const struct ldb_map_attribute *map;
873 struct ldb_context *ldb;
875 ldb = ldb_module_get_ctx(module);
881 if (tree->operation == LDB_OP_NOT) {
882 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
885 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
886 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
889 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
894 map = map_attr_find_local(data, tree->u.equality.attr);
895 if (map->convert_operator) {
896 return map->convert_operator(module, mem_ctx, new, tree);
899 if (map->type == MAP_GENERATE) {
900 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
901 "Skipping attribute '%s': "
902 "'convert_operator' not set\n",
903 tree->u.equality.attr);
908 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
911 /* Split subtrees that query attributes in the local partition from
912 * those that query the remote partition. */
913 static int ldb_parse_tree_partition(struct ldb_module *module,
915 struct ldb_parse_tree **local_tree,
916 struct ldb_parse_tree **remote_tree,
917 const struct ldb_parse_tree *tree)
924 /* No original tree */
929 /* Generate local tree */
930 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
935 /* Generate remote tree */
936 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
938 talloc_free(*local_tree);
945 /* Collect a list of attributes required either explicitly from a
946 * given list or implicitly from a given parse tree; split the
947 * collected list into local and remote parts. */
948 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
949 const char * const *search_attrs,
950 const struct ldb_parse_tree *tree)
953 const char **tree_attrs;
954 const char **remote_attrs;
955 const char **local_attrs;
958 /* There is no tree, just partition the searched attributes */
960 ret = map_attrs_partition(module, ac,
961 &local_attrs, &remote_attrs, search_attrs);
963 ac->local_attrs = local_attrs;
964 ac->remote_attrs = remote_attrs;
965 ac->all_attrs = search_attrs;
970 /* Create context for temporary memory */
971 tmp_ctx = talloc_new(ac);
972 if (tmp_ctx == NULL) {
976 /* Prepare list of attributes from tree */
977 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
978 if (tree_attrs == NULL) {
979 talloc_free(tmp_ctx);
982 tree_attrs[0] = NULL;
984 /* Collect attributes from tree */
985 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
990 /* Merge attributes from search operation */
991 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
996 /* Split local from remote attributes */
997 ret = map_attrs_partition(module, ac, &local_attrs,
998 &remote_attrs, tree_attrs);
1001 ac->local_attrs = local_attrs;
1002 ac->remote_attrs = remote_attrs;
1003 talloc_steal(ac, tree_attrs);
1004 ac->all_attrs = tree_attrs;
1007 /* Free temporary memory */
1008 talloc_free(tmp_ctx);
1017 /* Outbound requests: search
1018 * ========================= */
1020 static int map_remote_search_callback(struct ldb_request *req,
1021 struct ldb_reply *ares);
1022 static int map_local_merge_callback(struct ldb_request *req,
1023 struct ldb_reply *ares);
1024 static int map_search_local(struct map_context *ac);
1026 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1028 struct map_reply *mr;
1030 mr = talloc_zero(ac, struct map_reply);
1032 map_oom(ac->module);
1033 return LDB_ERR_OPERATIONS_ERROR;
1035 mr->remote = talloc_steal(mr, ares);
1036 if (ac->r_current) {
1037 ac->r_current->next = mr;
1047 /* Pass a merged search result up the callback chain. */
1048 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1050 struct ldb_message_element *el;
1051 const char * const *attrs;
1052 struct ldb_context *ldb;
1055 ldb = ldb_module_get_ctx(ac->module);
1057 /* Merged result doesn't match original query, skip */
1058 if (!ldb_match_msg(ldb, ares->message,
1059 ac->req->op.search.tree,
1060 ac->req->op.search.base,
1061 ac->req->op.search.scope)) {
1062 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1063 "Skipping record '%s': "
1064 "doesn't match original search\n",
1065 ldb_dn_get_linearized(ares->message->dn));
1069 /* Limit result to requested attrs */
1070 if (ac->req->op.search.attrs &&
1071 (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1073 attrs = ac->req->op.search.attrs;
1076 while (i < ares->message->num_elements) {
1078 el = &ares->message->elements[i];
1079 if ( ! ldb_attr_in_list(attrs, el->name)) {
1080 ldb_msg_remove_element(ares->message, el);
1087 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1090 /* Search a record. */
1091 int map_search(struct ldb_module *module, struct ldb_request *req)
1093 struct ldb_parse_tree *remote_tree;
1094 struct ldb_parse_tree *local_tree;
1095 struct ldb_request *remote_req;
1096 struct ldb_context *ldb;
1097 struct map_context *ac;
1100 const char *wildcard[] = { "*", NULL };
1101 const char * const *attrs;
1103 ldb = ldb_module_get_ctx(module);
1105 /* if we're not yet initialized, go to the next module */
1106 if (!ldb_module_get_private(module))
1107 return ldb_next_request(module, req);
1109 /* Do not manipulate our control entries */
1110 if (ldb_dn_is_special(req->op.search.base)) {
1111 return ldb_next_request(module, req);
1114 /* No mapping requested, skip to next module */
1115 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1116 return ldb_next_request(module, req);
1119 /* TODO: How can we be sure about which partition we are
1120 * targetting when there is no search base? */
1122 /* Prepare context and handle */
1123 ac = map_init_context(module, req);
1125 return LDB_ERR_OPERATIONS_ERROR;
1128 /* It is easier to deal with the two different ways of
1129 * expressing the wildcard in the same codepath */
1130 attrs = req->op.search.attrs;
1131 if (attrs == NULL) {
1135 /* Split local from remote attrs */
1136 ret = map_attrs_collect_and_partition(module, ac,
1137 attrs, req->op.search.tree);
1139 return LDB_ERR_OPERATIONS_ERROR;
1142 /* Split local from remote tree */
1143 ret = ldb_parse_tree_partition(module, ac,
1144 &local_tree, &remote_tree,
1145 req->op.search.tree);
1147 return LDB_ERR_OPERATIONS_ERROR;
1150 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1151 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1152 /* The query can't safely be split, enumerate the remote partition */
1157 if (local_tree == NULL) {
1158 /* Construct default local parse tree */
1159 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1160 if (local_tree == NULL) {
1161 map_oom(ac->module);
1162 return LDB_ERR_OPERATIONS_ERROR;
1165 local_tree->operation = LDB_OP_PRESENT;
1166 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1168 if (remote_tree == NULL) {
1169 /* Construct default remote parse tree */
1170 remote_tree = ldb_parse_tree(ac, NULL);
1171 if (remote_tree == NULL) {
1172 return LDB_ERR_OPERATIONS_ERROR;
1176 ac->local_tree = local_tree;
1178 /* Prepare the remote operation */
1179 ret = ldb_build_search_req_ex(&remote_req, ldb, ac,
1180 req->op.search.base,
1181 req->op.search.scope,
1185 ac, map_remote_search_callback,
1187 if (ret != LDB_SUCCESS) {
1188 return LDB_ERR_OPERATIONS_ERROR;
1191 return ldb_next_remote_request(module, remote_req);
1194 /* Now, search the local part of a remote search result. */
1195 static int map_remote_search_callback(struct ldb_request *req,
1196 struct ldb_reply *ares)
1198 struct map_context *ac;
1201 ac = talloc_get_type(req->context, struct map_context);
1204 return ldb_module_done(ac->req, NULL, NULL,
1205 LDB_ERR_OPERATIONS_ERROR);
1207 if (ares->error != LDB_SUCCESS) {
1208 return ldb_module_done(ac->req, ares->controls,
1209 ares->response, ares->error);
1212 switch (ares->type) {
1213 case LDB_REPLY_REFERRAL:
1215 /* ignore referrals */
1219 case LDB_REPLY_ENTRY:
1221 /* Map result record into a local message */
1222 ret = map_reply_remote(ac, ares);
1225 return ldb_module_done(ac->req, NULL, NULL,
1226 LDB_ERR_OPERATIONS_ERROR);
1229 /* if we have no local db, then we can just return the reply to
1230 * the upper layer, otherwise we must save it and process it
1231 * when all replies ahve been gathered */
1232 if ( ! map_check_local_db(ac->module)) {
1233 ret = map_return_entry(ac, ares);
1235 ret = map_save_entry(ac,ares);
1238 if (ret != LDB_SUCCESS) {
1240 return ldb_module_done(ac->req, NULL, NULL,
1241 LDB_ERR_OPERATIONS_ERROR);
1245 case LDB_REPLY_DONE:
1247 if ( ! map_check_local_db(ac->module)) {
1248 return ldb_module_done(ac->req, ares->controls,
1249 ares->response, LDB_SUCCESS);
1254 /* reset the pointer to the start of the list */
1255 ac->r_current = ac->r_list;
1257 /* no entry just return */
1258 if (ac->r_current == NULL) {
1259 return ldb_module_done(ac->req, ares->controls,
1260 ares->response, LDB_SUCCESS);
1263 ret = map_search_local(ac);
1264 if (ret != LDB_SUCCESS) {
1265 return ldb_module_done(ac->req, NULL, NULL, ret);
1272 static int map_search_local(struct map_context *ac)
1274 struct ldb_request *search_req;
1276 if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1277 return LDB_ERR_OPERATIONS_ERROR;
1280 /* Prepare local search request */
1281 /* TODO: use GUIDs here instead? */
1282 search_req = map_search_base_req(ac,
1283 ac->r_current->remote->message->dn,
1285 ac, map_local_merge_callback);
1286 if (search_req == NULL) {
1287 return LDB_ERR_OPERATIONS_ERROR;
1290 return ldb_next_request(ac->module, search_req);
1293 /* Merge the remote and local parts of a search result. */
1294 int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares)
1296 struct ldb_context *ldb;
1297 struct map_context *ac;
1300 ac = talloc_get_type(req->context, struct map_context);
1301 ldb = ldb_module_get_ctx(ac->module);
1304 return ldb_module_done(ac->req, NULL, NULL,
1305 LDB_ERR_OPERATIONS_ERROR);
1307 if (ares->error != LDB_SUCCESS) {
1308 return ldb_module_done(ac->req, ares->controls,
1309 ares->response, ares->error);
1312 switch (ares->type) {
1313 case LDB_REPLY_ENTRY:
1314 /* We have already found a local record */
1315 if (ac->r_current->local) {
1317 ldb_set_errstring(ldb, "ldb_map: Too many results!");
1318 return ldb_module_done(ac->req, NULL, NULL,
1319 LDB_ERR_OPERATIONS_ERROR);
1322 /* Store local result */
1323 ac->r_current->local = talloc_steal(ac->r_current, ares);
1327 case LDB_REPLY_REFERRAL:
1328 /* ignore referrals */
1332 case LDB_REPLY_DONE:
1335 /* No local record found, map and send remote record */
1336 if (ac->r_current->local != NULL) {
1337 /* Merge remote into local message */
1338 ret = ldb_msg_merge_local(ac->module,
1339 ac->r_current->local->message,
1340 ac->r_current->remote->message);
1341 if (ret == LDB_SUCCESS) {
1342 ret = map_return_entry(ac, ac->r_current->local);
1344 if (ret != LDB_SUCCESS) {
1345 return ldb_module_done(ac->req, NULL, NULL,
1346 LDB_ERR_OPERATIONS_ERROR);
1349 ret = map_return_entry(ac, ac->r_current->remote);
1350 if (ret != LDB_SUCCESS) {
1351 return ldb_module_done(ac->req,
1356 if (ac->r_current->next != NULL) {
1357 ac->r_current = ac->r_current->next;
1358 if (ac->r_current->remote->type == LDB_REPLY_ENTRY) {
1359 ret = map_search_local(ac);
1360 if (ret != LDB_SUCCESS) {
1361 return ldb_module_done(ac->req,
1368 /* ok we are done with all search, finally it is time to
1369 * finish operations for this module */
1370 return ldb_module_done(ac->req,
1371 ac->r_current->remote->controls,
1372 ac->r_current->remote->response,
1373 ac->r_current->remote->error);