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/>.
28 #include "ldb_includes.h"
31 #include "ldb_map_private.h"
35 * ================== */
37 /* Select attributes that stay in the local partition. */
38 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
40 const struct ldb_map_context *data = map_get_context(module);
48 result = talloc_array(mem_ctx, const char *, 1);
54 for (i = 0; attrs[i]; i++) {
55 /* Wildcards and ignored attributes are kept locally */
56 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
57 (!map_attr_check_remote(data, attrs[i]))) {
58 result = talloc_realloc(mem_ctx, result, const char *, last+2);
63 result[last] = talloc_strdup(result, attrs[i]);
64 result[last+1] = NULL;
77 /* Collect attributes that are mapped into the remote partition. */
78 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx,
79 const char * const *attrs)
81 const struct ldb_map_context *data = map_get_context(module);
83 const struct ldb_map_attribute *map;
84 const char *name=NULL;
89 result = talloc_array(mem_ctx, const char *, 1);
95 for (i = 0; attrs[i]; i++) {
96 /* Wildcards are kept remotely, too */
97 if (ldb_attr_cmp(attrs[i], "*") == 0) {
98 const char **new_attrs = NULL;
99 ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
100 if (ret != LDB_SUCCESS) {
103 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
104 if (ret != LDB_SUCCESS) {
113 for (i = 0; attrs[i]; i++) {
114 /* Wildcards are kept remotely, too */
115 if (ldb_attr_cmp(attrs[i], "*") == 0) {
116 /* Add all 'include in wildcard' attributes */
121 /* Add remote names of mapped attrs */
122 map = map_attr_find_local(data, attrs[i]);
137 name = map->u.rename.remote_name;
141 /* Add all remote names of "generate" attrs */
142 for (j = 0; map->u.generate.remote_names[j]; j++) {
143 result = talloc_realloc(mem_ctx, result, const char *, last+2);
144 if (result == NULL) {
148 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
149 result[last+1] = NULL;
155 named: /* We found a single remote name, add that */
156 result = talloc_realloc(mem_ctx, result, const char *, last+2);
157 if (result == NULL) {
161 result[last] = talloc_strdup(result, name);
162 result[last+1] = NULL;
174 /* Split attributes that stay in the local partition from those that
175 * are mapped into the remote partition. */
176 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
178 *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
179 *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
184 /* Mapping message elements
185 * ======================== */
187 /* Add an element to a message, overwriting any old identically named elements. */
188 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
190 struct ldb_message_element *old;
192 old = ldb_msg_find_element(msg, el->name);
194 /* no local result, add as new element */
196 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
199 talloc_free(discard_const_p(char, old->name));
202 /* copy new element */
205 /* and make sure we reference the contents */
206 if (!talloc_reference(msg->elements, el->name)) {
209 if (!talloc_reference(msg->elements, el->values)) {
216 /* Map a message element back into the local partition. */
217 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
219 const struct ldb_map_attribute *map,
220 const char *attr_name,
221 const struct ldb_message_element *old)
223 struct ldb_message_element *el;
226 el = talloc_zero(mem_ctx, struct ldb_message_element);
232 el->values = talloc_array(el, struct ldb_val, old->num_values);
233 if (el->values == NULL) {
239 el->name = talloc_strdup(el, attr_name);
240 if (el->name == NULL) {
246 for (i = 0; i < old->num_values; i++) {
247 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
248 /* Conversions might fail, in which case bail */
249 if (!el->values[i].data) {
259 /* Merge a remote message element into a local message. */
260 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
261 struct ldb_message *remote, const char *attr_name)
263 const struct ldb_map_context *data = map_get_context(module);
264 const struct ldb_map_attribute *map;
265 struct ldb_message_element *old, *el=NULL;
266 const char *remote_name = NULL;
268 /* We handle wildcards in ldb_msg_el_merge_wildcard */
269 if (ldb_attr_cmp(attr_name, "*") == 0) {
273 map = map_attr_find_local(data, attr_name);
275 /* Unknown attribute in remote message:
276 * skip, attribute was probably auto-generated */
285 remote_name = map->u.convert.remote_name;
288 remote_name = attr_name;
291 remote_name = map->u.rename.remote_name;
302 if (map->u.convert.convert_remote == NULL) {
303 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
304 "Skipping attribute '%s': "
305 "'convert_remote' not set\n",
312 old = ldb_msg_find_element(remote, remote_name);
314 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
316 return LDB_ERR_NO_SUCH_ATTRIBUTE;
321 if (map->u.generate.generate_local == NULL) {
322 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
323 "Skipping attribute '%s': "
324 "'generate_local' not set\n",
329 el = map->u.generate.generate_local(module, local, attr_name, remote);
331 /* Generation failure is probably due to lack of source attributes */
332 return LDB_ERR_NO_SUCH_ATTRIBUTE;
338 return LDB_ERR_NO_SUCH_ATTRIBUTE;
341 return ldb_msg_replace(local, el);
344 /* Handle wildcard parts of merging a remote message element into a local message. */
345 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
346 struct ldb_message *remote)
348 const struct ldb_map_context *data = map_get_context(module);
349 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
350 struct ldb_message_element *el=NULL;
353 /* Perhaps we have a mapping for "*" */
354 if (map && map->type == MAP_KEEP) {
355 /* We copy everything over, and hope that anything with a
356 more specific rule is overwritten */
357 for (i = 0; i < remote->num_elements; i++) {
358 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
359 &remote->elements[i]);
361 return LDB_ERR_OPERATIONS_ERROR;
364 ret = ldb_msg_replace(local, el);
371 /* Now walk the list of possible mappings, and apply each */
372 for (i = 0; data->attribute_maps[i].local_name; i++) {
373 ret = ldb_msg_el_merge(module, local, remote,
374 data->attribute_maps[i].local_name);
375 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
388 * ================ */
390 /* Merge two local messages into a single one. */
391 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
395 for (i = 0; i < msg2->num_elements; i++) {
396 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
405 /* Merge a local and a remote message into a single local one. */
406 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
407 struct ldb_message *remote)
410 const char * const *attrs = ac->all_attrs;
412 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
418 for (i = 0; attrs && attrs[i]; i++) {
419 if (ldb_attr_cmp(attrs[i], "*") == 0) {
420 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
428 /* Try to map each attribute back;
429 * Add to local message is possible,
430 * Overwrite old local attribute if necessary */
431 for (i = 0; attrs && attrs[i]; i++) {
432 ret = ldb_msg_el_merge(ac->module, local, remote,
434 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
443 /* Mapping search results
444 * ====================== */
446 /* Map a search result back into the local partition. */
447 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
449 struct ldb_message *msg;
453 /* There is no result message, skip */
454 if (ares->type != LDB_REPLY_ENTRY) {
458 /* Create a new result message */
459 msg = ldb_msg_new(ares);
465 /* Merge remote message into new message */
466 ret = ldb_msg_merge_remote(ac, msg, ares->message);
472 /* Create corresponding local DN */
473 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
480 /* Store new message with new DN as the result */
481 talloc_free(ares->message);
487 /* Mapping parse trees
488 * =================== */
490 /* Check whether a parse tree can safely be split in two. */
491 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
493 const struct ldb_parse_tree *subtree = tree;
497 switch (subtree->operation) {
500 subtree = subtree->u.isnot.child;
504 return !negate; /* if negate: False */
507 return negate; /* if negate: True */
510 return true; /* simple parse tree */
514 return true; /* no parse tree */
517 /* Collect a list of attributes required to match a given parse tree. */
518 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
520 const char **new_attrs;
527 switch (tree->operation) {
529 case LDB_OP_AND: /* attributes stored in list of subtrees */
530 for (i = 0; i < tree->u.list.num_elements; i++) {
531 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
532 attrs, tree->u.list.elements[i]);
539 case LDB_OP_NOT: /* attributes stored in single subtree */
540 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
542 default: /* single attribute in tree */
543 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
552 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
554 /* Select a negated subtree that queries attributes in the local partition */
555 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)
557 struct ldb_parse_tree *child;
560 /* Prepare new tree */
561 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
567 /* Generate new subtree */
568 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
574 /* Prune tree without subtree */
581 (*new)->u.isnot.child = child;
586 /* Select a list of subtrees that query attributes in the local partition */
587 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)
591 /* Prepare new tree */
592 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
598 /* Prepare list of subtrees */
599 (*new)->u.list.num_elements = 0;
600 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
601 if ((*new)->u.list.elements == NULL) {
607 /* Generate new list of subtrees */
609 for (i = 0; i < tree->u.list.num_elements; i++) {
610 struct ldb_parse_tree *child;
611 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
618 (*new)->u.list.elements[j] = child;
623 /* Prune tree without subtrees */
630 /* Fix subtree list size */
631 (*new)->u.list.num_elements = j;
632 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
637 /* Select a simple subtree that queries attributes in the local partition */
638 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)
640 /* Prepare new tree */
641 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
650 /* Select subtrees that query attributes in the local partition */
651 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
653 const struct ldb_map_context *data = map_get_context(module);
659 if (tree->operation == LDB_OP_NOT) {
660 return map_subtree_select_local_not(module, mem_ctx, new, tree);
663 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
664 return map_subtree_select_local_list(module, mem_ctx, new, tree);
667 if (map_attr_check_remote(data, tree->u.equality.attr)) {
672 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
675 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
677 /* Collect a negated subtree that queries attributes in the remote partition */
678 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)
680 struct ldb_parse_tree *child;
683 /* Prepare new tree */
684 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
690 /* Generate new subtree */
691 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
697 /* Prune tree without subtree */
704 (*new)->u.isnot.child = child;
709 /* Collect a list of subtrees that query attributes in the remote partition */
710 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)
714 /* Prepare new tree */
715 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
721 /* Prepare list of subtrees */
722 (*new)->u.list.num_elements = 0;
723 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
724 if ((*new)->u.list.elements == NULL) {
730 /* Generate new list of subtrees */
732 for (i = 0; i < tree->u.list.num_elements; i++) {
733 struct ldb_parse_tree *child;
734 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
741 (*new)->u.list.elements[j] = child;
746 /* Prune tree without subtrees */
753 /* Fix subtree list size */
754 (*new)->u.list.num_elements = j;
755 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
760 /* Collect a simple subtree that queries attributes in the remote partition */
761 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)
765 /* Prepare new tree */
766 *new = talloc(mem_ctx, struct ldb_parse_tree);
773 if (map->type == MAP_KEEP) {
774 /* Nothing to do here */
778 /* Store attribute and value in new tree */
779 switch (tree->operation) {
781 attr = map_attr_map_local(*new, map, tree->u.present.attr);
782 (*new)->u.present.attr = attr;
784 case LDB_OP_SUBSTRING:
786 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
787 (*new)->u.substring.attr = attr;
790 case LDB_OP_EQUALITY:
791 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
792 (*new)->u.equality.attr = attr;
797 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
798 (*new)->u.comparison.attr = attr;
800 case LDB_OP_EXTENDED:
801 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
802 (*new)->u.extended.attr = attr;
804 default: /* unknown kind of simple subtree */
815 if (map->type == MAP_RENAME) {
816 /* Nothing more to do here, the attribute has been renamed */
820 /* Store attribute and value in new tree */
821 switch (tree->operation) {
824 case LDB_OP_SUBSTRING:
828 (*new)->u.substring.chunks = NULL;
829 for (i=0; tree->u.substring.chunks[i]; i++) {
830 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
831 if (!(*new)->u.substring.chunks) {
836 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
837 if (!(*new)->u.substring.chunks[i]) {
842 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
843 (*new)->u.substring.chunks[i+1] = NULL;
847 case LDB_OP_EQUALITY:
848 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
853 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
855 case LDB_OP_EXTENDED:
856 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
857 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
859 default: /* unknown kind of simple subtree */
867 /* Collect subtrees that query attributes in the remote partition */
868 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
870 const struct ldb_map_context *data = map_get_context(module);
871 const struct ldb_map_attribute *map;
877 if (tree->operation == LDB_OP_NOT) {
878 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
881 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
882 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
885 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
890 map = map_attr_find_local(data, tree->u.equality.attr);
891 if (map->convert_operator) {
892 return map->convert_operator(module, mem_ctx, new, tree);
895 if (map->type == MAP_GENERATE) {
896 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
897 "Skipping attribute '%s': "
898 "'convert_operator' not set\n",
899 tree->u.equality.attr);
904 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
907 /* Split subtrees that query attributes in the local partition from
908 * those that query the remote partition. */
909 static int ldb_parse_tree_partition(struct ldb_module *module,
911 struct ldb_parse_tree **local_tree,
912 struct ldb_parse_tree **remote_tree,
913 const struct ldb_parse_tree *tree)
920 /* No original tree */
925 /* Generate local tree */
926 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
931 /* Generate remote tree */
932 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
934 talloc_free(*local_tree);
941 /* Collect a list of attributes required either explicitly from a
942 * given list or implicitly from a given parse tree; split the
943 * collected list into local and remote parts. */
944 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
945 const char * const *search_attrs,
946 const struct ldb_parse_tree *tree)
949 const char **tree_attrs;
950 const char **remote_attrs;
951 const char **local_attrs;
954 /* There is no tree, just partition the searched attributes */
956 ret = map_attrs_partition(module, ac,
957 &local_attrs, &remote_attrs, search_attrs);
959 ac->local_attrs = local_attrs;
960 ac->remote_attrs = remote_attrs;
961 ac->all_attrs = search_attrs;
966 /* Create context for temporary memory */
967 tmp_ctx = talloc_new(ac);
968 if (tmp_ctx == NULL) {
972 /* Prepare list of attributes from tree */
973 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
974 if (tree_attrs == NULL) {
975 talloc_free(tmp_ctx);
978 tree_attrs[0] = NULL;
980 /* Collect attributes from tree */
981 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
986 /* Merge attributes from search operation */
987 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
992 /* Split local from remote attributes */
993 ret = map_attrs_partition(module, ac, &local_attrs,
994 &remote_attrs, tree_attrs);
997 ac->local_attrs = local_attrs;
998 ac->remote_attrs = remote_attrs;
999 talloc_steal(ac, tree_attrs);
1000 ac->all_attrs = tree_attrs;
1003 /* Free temporary memory */
1004 talloc_free(tmp_ctx);
1013 /* Outbound requests: search
1014 * ========================= */
1016 static int map_remote_search_callback(struct ldb_request *req,
1017 struct ldb_reply *ares);
1018 static int map_local_merge_callback(struct ldb_request *req,
1019 struct ldb_reply *ares);
1020 static int map_search_local(struct map_context *ac);
1022 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1024 struct map_reply *mr;
1026 mr = talloc_zero(ac, struct map_reply);
1028 map_oom(ac->module);
1029 return LDB_ERR_OPERATIONS_ERROR;
1031 mr->remote = talloc_steal(mr, ares);
1032 if (ac->r_current) {
1033 ac->r_current->next = mr;
1043 /* Pass a merged search result up the callback chain. */
1044 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1046 struct ldb_message_element *el;
1047 const char * const *attrs;
1050 /* Merged result doesn't match original query, skip */
1051 if (!ldb_match_msg(ac->module->ldb, ares->message,
1052 ac->req->op.search.tree,
1053 ac->req->op.search.base,
1054 ac->req->op.search.scope)) {
1055 ldb_debug(ac->module->ldb, LDB_DEBUG_TRACE, "ldb_map: "
1056 "Skipping record '%s': "
1057 "doesn't match original search\n",
1058 ldb_dn_get_linearized(ares->message->dn));
1062 /* Limit result to requested attrs */
1063 if (ac->req->op.search.attrs &&
1064 (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1066 attrs = ac->req->op.search.attrs;
1069 while (i < ares->message->num_elements) {
1071 el = &ares->message->elements[i];
1072 if ( ! ldb_attr_in_list(attrs, el->name)) {
1073 ldb_msg_remove_element(ares->message, el);
1080 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1083 /* Search a record. */
1084 int map_search(struct ldb_module *module, struct ldb_request *req)
1086 struct ldb_parse_tree *remote_tree;
1087 struct ldb_parse_tree *local_tree;
1088 struct ldb_request *remote_req;
1089 struct map_context *ac;
1092 const char *wildcard[] = { "*", NULL };
1093 const char * const *attrs;
1095 if (!module->private_data) /* if we're not yet initialized, go to the next module */
1096 return ldb_next_request(module, req);
1098 /* Do not manipulate our control entries */
1099 if (ldb_dn_is_special(req->op.search.base)) {
1100 return ldb_next_request(module, req);
1103 /* No mapping requested, skip to next module */
1104 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1105 return ldb_next_request(module, req);
1108 /* TODO: How can we be sure about which partition we are
1109 * targetting when there is no search base? */
1111 /* Prepare context and handle */
1112 ac = map_init_context(module, req);
1114 return LDB_ERR_OPERATIONS_ERROR;
1117 /* It is easier to deal with the two different ways of
1118 * expressing the wildcard in the same codepath */
1119 attrs = req->op.search.attrs;
1120 if (attrs == NULL) {
1124 /* Split local from remote attrs */
1125 ret = map_attrs_collect_and_partition(module, ac,
1126 attrs, req->op.search.tree);
1128 return LDB_ERR_OPERATIONS_ERROR;
1131 /* Split local from remote tree */
1132 ret = ldb_parse_tree_partition(module, ac,
1133 &local_tree, &remote_tree,
1134 req->op.search.tree);
1136 return LDB_ERR_OPERATIONS_ERROR;
1139 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1140 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1141 /* The query can't safely be split, enumerate the remote partition */
1146 if (local_tree == NULL) {
1147 /* Construct default local parse tree */
1148 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1149 if (local_tree == NULL) {
1150 map_oom(ac->module);
1151 return LDB_ERR_OPERATIONS_ERROR;
1154 local_tree->operation = LDB_OP_PRESENT;
1155 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1157 if (remote_tree == NULL) {
1158 /* Construct default remote parse tree */
1159 remote_tree = ldb_parse_tree(ac, NULL);
1160 if (remote_tree == NULL) {
1161 return LDB_ERR_OPERATIONS_ERROR;
1165 ac->local_tree = local_tree;
1167 /* Prepare the remote operation */
1168 ret = ldb_build_search_req_ex(&remote_req, module->ldb, ac,
1169 req->op.search.base,
1170 req->op.search.scope,
1174 ac, map_remote_search_callback,
1176 if (ret != LDB_SUCCESS) {
1177 return LDB_ERR_OPERATIONS_ERROR;
1180 return ldb_next_remote_request(module, remote_req);
1183 /* Now, search the local part of a remote search result. */
1184 static int map_remote_search_callback(struct ldb_request *req,
1185 struct ldb_reply *ares)
1187 struct map_context *ac;
1190 ac = talloc_get_type(req->context, struct map_context);
1193 return ldb_module_done(ac->req, NULL, NULL,
1194 LDB_ERR_OPERATIONS_ERROR);
1196 if (ares->error != LDB_SUCCESS) {
1197 return ldb_module_done(ac->req, ares->controls,
1198 ares->response, ares->error);
1201 switch (ares->type) {
1202 case LDB_REPLY_REFERRAL:
1204 /* ignore referrals */
1208 case LDB_REPLY_ENTRY:
1210 /* Map result record into a local message */
1211 ret = map_reply_remote(ac, ares);
1214 return ldb_module_done(ac->req, NULL, NULL,
1215 LDB_ERR_OPERATIONS_ERROR);
1218 /* if we have no local db, then we can just return the reply to
1219 * the upper layer, otherwise we must save it and process it
1220 * when all replies ahve been gathered */
1221 if ( ! map_check_local_db(ac->module)) {
1222 ret = map_return_entry(ac, ares);
1224 ret = map_save_entry(ac,ares);
1227 if (ret != LDB_SUCCESS) {
1229 return ldb_module_done(ac->req, NULL, NULL,
1230 LDB_ERR_OPERATIONS_ERROR);
1234 case LDB_REPLY_DONE:
1236 if ( ! map_check_local_db(ac->module)) {
1237 return ldb_module_done(ac->req, ares->controls,
1238 ares->response, LDB_SUCCESS);
1243 /* reset the pointer to the start of the list */
1244 ac->r_current = ac->r_list;
1246 /* no entry just return */
1247 if (ac->r_current == NULL) {
1248 return ldb_module_done(ac->req, ares->controls,
1249 ares->response, LDB_SUCCESS);
1252 ret = map_search_local(ac);
1253 if (ret != LDB_SUCCESS) {
1254 return ldb_module_done(ac->req, NULL, NULL, ret);
1261 static int map_search_local(struct map_context *ac)
1263 struct ldb_request *search_req;
1265 if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1266 return LDB_ERR_OPERATIONS_ERROR;
1269 /* Prepare local search request */
1270 /* TODO: use GUIDs here instead? */
1271 search_req = map_search_base_req(ac,
1272 ac->r_current->remote->message->dn,
1274 ac, map_local_merge_callback);
1275 if (search_req == NULL) {
1276 return LDB_ERR_OPERATIONS_ERROR;
1279 return ldb_next_request(ac->module, search_req);
1282 /* Merge the remote and local parts of a search result. */
1283 int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares)
1285 struct map_context *ac;
1288 ac = talloc_get_type(req->context, struct map_context);
1291 return ldb_module_done(ac->req, NULL, NULL,
1292 LDB_ERR_OPERATIONS_ERROR);
1294 if (ares->error != LDB_SUCCESS) {
1295 return ldb_module_done(ac->req, ares->controls,
1296 ares->response, ares->error);
1299 switch (ares->type) {
1300 case LDB_REPLY_ENTRY:
1301 /* We have already found a local record */
1302 if (ac->r_current->local) {
1304 ldb_set_errstring(ac->module->ldb, "ldb_map: Too many results!");
1305 return ldb_module_done(ac->req, NULL, NULL,
1306 LDB_ERR_OPERATIONS_ERROR);
1309 /* Store local result */
1310 ac->r_current->local = talloc_steal(ac->r_current, ares);
1314 case LDB_REPLY_REFERRAL:
1315 /* ignore referrals */
1319 case LDB_REPLY_DONE:
1322 /* No local record found, map and send remote record */
1323 if (ac->r_current->local != NULL) {
1324 /* Merge remote into local message */
1325 ret = ldb_msg_merge_local(ac->module,
1326 ac->r_current->local->message,
1327 ac->r_current->remote->message);
1328 if (ret == LDB_SUCCESS) {
1329 ret = map_return_entry(ac, ac->r_current->local);
1331 if (ret != LDB_SUCCESS) {
1332 return ldb_module_done(ac->req, NULL, NULL,
1333 LDB_ERR_OPERATIONS_ERROR);
1336 ret = map_return_entry(ac, ac->r_current->remote);
1337 if (ret != LDB_SUCCESS) {
1338 return ldb_module_done(ac->req,
1343 if (ac->r_current->next != NULL) {
1344 ac->r_current = ac->r_current->next;
1345 if (ac->r_current->remote->type == LDB_REPLY_ENTRY) {
1346 ret = map_search_local(ac);
1347 if (ret != LDB_SUCCESS) {
1348 return ldb_module_done(ac->req,
1355 /* ok we are done with all search, finally it is time to
1356 * finish operations for this module */
1357 return ldb_module_done(ac->req,
1358 ac->r_current->remote->controls,
1359 ac->r_current->remote->response,
1360 ac->r_current->remote->error);