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_module.h"
29 #include "ldb_private.h"
32 #include "ldb_map_private.h"
36 * ================== */
38 /* Select attributes that stay in the local partition. */
39 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
41 const struct ldb_map_context *data = map_get_context(module);
49 result = talloc_array(mem_ctx, const char *, 1);
55 for (i = 0; attrs[i]; i++) {
56 /* Wildcards and ignored attributes are kept locally */
57 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
58 (!map_attr_check_remote(data, attrs[i]))) {
59 result = talloc_realloc(mem_ctx, result, const char *, last+2);
64 result[last] = talloc_strdup(result, attrs[i]);
65 result[last+1] = NULL;
78 /* Collect attributes that are mapped into the remote partition. */
79 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx,
80 const char * const *attrs)
82 const struct ldb_map_context *data = map_get_context(module);
84 const struct ldb_map_attribute *map;
85 const char *name=NULL;
90 result = talloc_array(mem_ctx, const char *, 1);
96 for (i = 0; attrs[i]; i++) {
97 /* Wildcards are kept remotely, too */
98 if (ldb_attr_cmp(attrs[i], "*") == 0) {
99 const char **new_attrs = NULL;
100 ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
101 if (ret != LDB_SUCCESS) {
104 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
105 if (ret != LDB_SUCCESS) {
114 for (i = 0; attrs[i]; i++) {
115 /* Wildcards are kept remotely, too */
116 if (ldb_attr_cmp(attrs[i], "*") == 0) {
117 /* Add all 'include in wildcard' attributes */
122 /* Add remote names of mapped attrs */
123 map = map_attr_find_local(data, attrs[i]);
138 name = map->u.rename.remote_name;
142 /* Add all remote names of "generate" attrs */
143 for (j = 0; map->u.generate.remote_names[j]; j++) {
144 result = talloc_realloc(mem_ctx, result, const char *, last+2);
145 if (result == NULL) {
149 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
150 result[last+1] = NULL;
156 named: /* We found a single remote name, add that */
157 result = talloc_realloc(mem_ctx, result, const char *, last+2);
158 if (result == NULL) {
162 result[last] = talloc_strdup(result, name);
163 result[last+1] = NULL;
175 /* Split attributes that stay in the local partition from those that
176 * are mapped into the remote partition. */
177 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
179 *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
180 *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
185 /* Mapping message elements
186 * ======================== */
188 /* Add an element to a message, overwriting any old identically named elements. */
189 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
191 struct ldb_message_element *old;
193 old = ldb_msg_find_element(msg, el->name);
195 /* no local result, add as new element */
197 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
200 talloc_free(discard_const_p(char, old->name));
203 /* copy new element */
206 /* and make sure we reference the contents */
207 if (!talloc_reference(msg->elements, el->name)) {
210 if (!talloc_reference(msg->elements, el->values)) {
217 /* Map a message element back into the local partition. */
218 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
220 const struct ldb_map_attribute *map,
221 const char *attr_name,
222 const struct ldb_message_element *old)
224 struct ldb_message_element *el;
227 el = talloc_zero(mem_ctx, struct ldb_message_element);
233 el->values = talloc_array(el, struct ldb_val, old->num_values);
234 if (el->values == NULL) {
240 el->name = talloc_strdup(el, attr_name);
241 if (el->name == NULL) {
247 for (i = 0; i < old->num_values; i++) {
248 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
249 /* Conversions might fail, in which case bail */
250 if (!el->values[i].data) {
260 /* Merge a remote message element into a local message. */
261 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
262 struct ldb_message *remote, const char *attr_name)
264 const struct ldb_map_context *data = map_get_context(module);
265 const struct ldb_map_attribute *map;
266 struct ldb_message_element *old, *el=NULL;
267 const char *remote_name = NULL;
268 struct ldb_context *ldb;
270 ldb = ldb_module_get_ctx(module);
272 /* We handle wildcards in ldb_msg_el_merge_wildcard */
273 if (ldb_attr_cmp(attr_name, "*") == 0) {
277 map = map_attr_find_local(data, attr_name);
279 /* Unknown attribute in remote message:
280 * skip, attribute was probably auto-generated */
289 remote_name = map->u.convert.remote_name;
292 remote_name = attr_name;
295 remote_name = map->u.rename.remote_name;
306 if (map->u.convert.convert_remote == NULL) {
307 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
308 "Skipping attribute '%s': "
309 "'convert_remote' not set\n",
316 old = ldb_msg_find_element(remote, remote_name);
318 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
320 return LDB_ERR_NO_SUCH_ATTRIBUTE;
325 if (map->u.generate.generate_local == NULL) {
326 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
327 "Skipping attribute '%s': "
328 "'generate_local' not set\n",
333 el = map->u.generate.generate_local(module, local, attr_name, remote);
335 /* Generation failure is probably due to lack of source attributes */
336 return LDB_ERR_NO_SUCH_ATTRIBUTE;
342 return LDB_ERR_NO_SUCH_ATTRIBUTE;
345 return ldb_msg_replace(local, el);
348 /* Handle wildcard parts of merging a remote message element into a local message. */
349 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
350 struct ldb_message *remote)
352 const struct ldb_map_context *data = map_get_context(module);
353 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
354 struct ldb_message_element *el=NULL;
357 /* Perhaps we have a mapping for "*" */
358 if (map && map->type == MAP_KEEP) {
359 /* We copy everything over, and hope that anything with a
360 more specific rule is overwritten */
361 for (i = 0; i < remote->num_elements; i++) {
362 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
363 &remote->elements[i]);
365 return LDB_ERR_OPERATIONS_ERROR;
368 ret = ldb_msg_replace(local, el);
375 /* Now walk the list of possible mappings, and apply each */
376 for (i = 0; data->attribute_maps[i].local_name; i++) {
377 ret = ldb_msg_el_merge(module, local, remote,
378 data->attribute_maps[i].local_name);
379 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
392 * ================ */
394 /* Merge two local messages into a single one. */
395 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
399 for (i = 0; i < msg2->num_elements; i++) {
400 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
409 /* Merge a local and a remote message into a single local one. */
410 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
411 struct ldb_message *remote)
414 const char * const *attrs = ac->all_attrs;
416 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
422 for (i = 0; attrs && attrs[i]; i++) {
423 if (ldb_attr_cmp(attrs[i], "*") == 0) {
424 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
432 /* Try to map each attribute back;
433 * Add to local message is possible,
434 * Overwrite old local attribute if necessary */
435 for (i = 0; attrs && attrs[i]; i++) {
436 ret = ldb_msg_el_merge(ac->module, local, remote,
438 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
447 /* Mapping search results
448 * ====================== */
450 /* Map a search result back into the local partition. */
451 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
453 struct ldb_message *msg;
457 /* There is no result message, skip */
458 if (ares->type != LDB_REPLY_ENTRY) {
462 /* Create a new result message */
463 msg = ldb_msg_new(ares);
469 /* Merge remote message into new message */
470 ret = ldb_msg_merge_remote(ac, msg, ares->message);
476 /* Create corresponding local DN */
477 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
484 /* Store new message with new DN as the result */
485 talloc_free(ares->message);
491 /* Mapping parse trees
492 * =================== */
494 /* Check whether a parse tree can safely be split in two. */
495 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
497 const struct ldb_parse_tree *subtree = tree;
501 switch (subtree->operation) {
504 subtree = subtree->u.isnot.child;
508 return !negate; /* if negate: False */
511 return negate; /* if negate: True */
514 return true; /* simple parse tree */
518 return true; /* no parse tree */
521 /* Collect a list of attributes required to match a given parse tree. */
522 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
524 const char **new_attrs;
531 switch (tree->operation) {
533 case LDB_OP_AND: /* attributes stored in list of subtrees */
534 for (i = 0; i < tree->u.list.num_elements; i++) {
535 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
536 attrs, tree->u.list.elements[i]);
543 case LDB_OP_NOT: /* attributes stored in single subtree */
544 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
546 default: /* single attribute in tree */
547 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
556 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
558 /* Select a negated subtree that queries attributes in the local partition */
559 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)
561 struct ldb_parse_tree *child;
564 /* Prepare new tree */
565 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
571 /* Generate new subtree */
572 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
578 /* Prune tree without subtree */
585 (*new)->u.isnot.child = child;
590 /* Select a list of subtrees that query attributes in the local partition */
591 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)
595 /* Prepare new tree */
596 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
602 /* Prepare list of subtrees */
603 (*new)->u.list.num_elements = 0;
604 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
605 if ((*new)->u.list.elements == NULL) {
611 /* Generate new list of subtrees */
613 for (i = 0; i < tree->u.list.num_elements; i++) {
614 struct ldb_parse_tree *child;
615 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
622 (*new)->u.list.elements[j] = child;
627 /* Prune tree without subtrees */
634 /* Fix subtree list size */
635 (*new)->u.list.num_elements = j;
636 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
641 /* Select a simple subtree that queries attributes in the local partition */
642 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)
644 /* Prepare new tree */
645 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
654 /* Select subtrees that query attributes in the local partition */
655 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
657 const struct ldb_map_context *data = map_get_context(module);
663 if (tree->operation == LDB_OP_NOT) {
664 return map_subtree_select_local_not(module, mem_ctx, new, tree);
667 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
668 return map_subtree_select_local_list(module, mem_ctx, new, tree);
671 if (map_attr_check_remote(data, tree->u.equality.attr)) {
676 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
679 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
681 /* Collect a negated subtree that queries attributes in the remote partition */
682 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)
684 struct ldb_parse_tree *child;
687 /* Prepare new tree */
688 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
694 /* Generate new subtree */
695 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
701 /* Prune tree without subtree */
708 (*new)->u.isnot.child = child;
713 /* Collect a list of subtrees that query attributes in the remote partition */
714 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)
718 /* Prepare new tree */
719 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
725 /* Prepare list of subtrees */
726 (*new)->u.list.num_elements = 0;
727 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
728 if ((*new)->u.list.elements == NULL) {
734 /* Generate new list of subtrees */
736 for (i = 0; i < tree->u.list.num_elements; i++) {
737 struct ldb_parse_tree *child;
738 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
745 (*new)->u.list.elements[j] = child;
750 /* Prune tree without subtrees */
757 /* Fix subtree list size */
758 (*new)->u.list.num_elements = j;
759 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
764 /* Collect a simple subtree that queries attributes in the remote partition */
765 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)
769 /* Prepare new tree */
770 *new = talloc(mem_ctx, struct ldb_parse_tree);
777 if (map->type == MAP_KEEP) {
778 /* Nothing to do here */
782 /* Store attribute and value in new tree */
783 switch (tree->operation) {
785 attr = map_attr_map_local(*new, map, tree->u.present.attr);
786 (*new)->u.present.attr = attr;
788 case LDB_OP_SUBSTRING:
790 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
791 (*new)->u.substring.attr = attr;
794 case LDB_OP_EQUALITY:
795 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
796 (*new)->u.equality.attr = attr;
801 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
802 (*new)->u.comparison.attr = attr;
804 case LDB_OP_EXTENDED:
805 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
806 (*new)->u.extended.attr = attr;
808 default: /* unknown kind of simple subtree */
819 if (map->type == MAP_RENAME) {
820 /* Nothing more to do here, the attribute has been renamed */
824 /* Store attribute and value in new tree */
825 switch (tree->operation) {
828 case LDB_OP_SUBSTRING:
832 (*new)->u.substring.chunks = NULL;
833 for (i=0; tree->u.substring.chunks[i]; i++) {
834 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
835 if (!(*new)->u.substring.chunks) {
840 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
841 if (!(*new)->u.substring.chunks[i]) {
846 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
847 (*new)->u.substring.chunks[i+1] = NULL;
851 case LDB_OP_EQUALITY:
852 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
857 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
859 case LDB_OP_EXTENDED:
860 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
861 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
863 default: /* unknown kind of simple subtree */
871 /* Collect subtrees that query attributes in the remote partition */
872 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
874 const struct ldb_map_context *data = map_get_context(module);
875 const struct ldb_map_attribute *map;
876 struct ldb_context *ldb;
878 ldb = ldb_module_get_ctx(module);
884 if (tree->operation == LDB_OP_NOT) {
885 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
888 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
889 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
892 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
897 map = map_attr_find_local(data, tree->u.equality.attr);
898 if (map->convert_operator) {
899 return map->convert_operator(module, mem_ctx, new, tree);
902 if (map->type == MAP_GENERATE) {
903 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
904 "Skipping attribute '%s': "
905 "'convert_operator' not set\n",
906 tree->u.equality.attr);
911 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
914 /* Split subtrees that query attributes in the local partition from
915 * those that query the remote partition. */
916 static int ldb_parse_tree_partition(struct ldb_module *module,
918 struct ldb_parse_tree **local_tree,
919 struct ldb_parse_tree **remote_tree,
920 const struct ldb_parse_tree *tree)
927 /* No original tree */
932 /* Generate local tree */
933 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
938 /* Generate remote tree */
939 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
941 talloc_free(*local_tree);
948 /* Collect a list of attributes required either explicitly from a
949 * given list or implicitly from a given parse tree; split the
950 * collected list into local and remote parts. */
951 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
952 const char * const *search_attrs,
953 const struct ldb_parse_tree *tree)
956 const char **tree_attrs;
957 const char **remote_attrs;
958 const char **local_attrs;
961 /* There is no tree, just partition the searched attributes */
963 ret = map_attrs_partition(module, ac,
964 &local_attrs, &remote_attrs, search_attrs);
966 ac->local_attrs = local_attrs;
967 ac->remote_attrs = remote_attrs;
968 ac->all_attrs = search_attrs;
973 /* Create context for temporary memory */
974 tmp_ctx = talloc_new(ac);
975 if (tmp_ctx == NULL) {
979 /* Prepare list of attributes from tree */
980 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
981 if (tree_attrs == NULL) {
982 talloc_free(tmp_ctx);
985 tree_attrs[0] = NULL;
987 /* Collect attributes from tree */
988 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
993 /* Merge attributes from search operation */
994 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
999 /* Split local from remote attributes */
1000 ret = map_attrs_partition(module, ac, &local_attrs,
1001 &remote_attrs, tree_attrs);
1004 ac->local_attrs = local_attrs;
1005 ac->remote_attrs = remote_attrs;
1006 talloc_steal(ac, tree_attrs);
1007 ac->all_attrs = tree_attrs;
1010 /* Free temporary memory */
1011 talloc_free(tmp_ctx);
1020 /* Outbound requests: search
1021 * ========================= */
1023 static int map_remote_search_callback(struct ldb_request *req,
1024 struct ldb_reply *ares);
1025 static int map_local_merge_callback(struct ldb_request *req,
1026 struct ldb_reply *ares);
1027 static int map_search_local(struct map_context *ac);
1029 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1031 struct map_reply *mr;
1033 mr = talloc_zero(ac, struct map_reply);
1035 map_oom(ac->module);
1036 return LDB_ERR_OPERATIONS_ERROR;
1038 mr->remote = talloc_steal(mr, ares);
1039 if (ac->r_current) {
1040 ac->r_current->next = mr;
1050 /* Pass a merged search result up the callback chain. */
1051 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1053 struct ldb_message_element *el;
1054 const char * const *attrs;
1055 struct ldb_context *ldb;
1058 ldb = ldb_module_get_ctx(ac->module);
1060 /* Merged result doesn't match original query, skip */
1061 if (!ldb_match_msg(ldb, ares->message,
1062 ac->req->op.search.tree,
1063 ac->req->op.search.base,
1064 ac->req->op.search.scope)) {
1065 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1066 "Skipping record '%s': "
1067 "doesn't match original search\n",
1068 ldb_dn_get_linearized(ares->message->dn));
1072 /* Limit result to requested attrs */
1073 if (ac->req->op.search.attrs &&
1074 (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1076 attrs = ac->req->op.search.attrs;
1079 while (i < ares->message->num_elements) {
1081 el = &ares->message->elements[i];
1082 if ( ! ldb_attr_in_list(attrs, el->name)) {
1083 ldb_msg_remove_element(ares->message, el);
1090 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1093 /* Search a record. */
1094 int map_search(struct ldb_module *module, struct ldb_request *req)
1096 struct ldb_parse_tree *remote_tree;
1097 struct ldb_parse_tree *local_tree;
1098 struct ldb_request *remote_req;
1099 struct ldb_context *ldb;
1100 struct map_context *ac;
1103 const char *wildcard[] = { "*", NULL };
1104 const char * const *attrs;
1106 ldb = ldb_module_get_ctx(module);
1108 /* if we're not yet initialized, go to the next module */
1109 if (!ldb_module_get_private(module))
1110 return ldb_next_request(module, req);
1112 /* Do not manipulate our control entries */
1113 if (ldb_dn_is_special(req->op.search.base)) {
1114 return ldb_next_request(module, req);
1117 /* No mapping requested, skip to next module */
1118 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1119 return ldb_next_request(module, req);
1122 /* TODO: How can we be sure about which partition we are
1123 * targetting when there is no search base? */
1125 /* Prepare context and handle */
1126 ac = map_init_context(module, req);
1128 return LDB_ERR_OPERATIONS_ERROR;
1131 /* It is easier to deal with the two different ways of
1132 * expressing the wildcard in the same codepath */
1133 attrs = req->op.search.attrs;
1134 if (attrs == NULL) {
1138 /* Split local from remote attrs */
1139 ret = map_attrs_collect_and_partition(module, ac,
1140 attrs, req->op.search.tree);
1142 return LDB_ERR_OPERATIONS_ERROR;
1145 /* Split local from remote tree */
1146 ret = ldb_parse_tree_partition(module, ac,
1147 &local_tree, &remote_tree,
1148 req->op.search.tree);
1150 return LDB_ERR_OPERATIONS_ERROR;
1153 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1154 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1155 /* The query can't safely be split, enumerate the remote partition */
1160 if (local_tree == NULL) {
1161 /* Construct default local parse tree */
1162 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1163 if (local_tree == NULL) {
1164 map_oom(ac->module);
1165 return LDB_ERR_OPERATIONS_ERROR;
1168 local_tree->operation = LDB_OP_PRESENT;
1169 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1171 if (remote_tree == NULL) {
1172 /* Construct default remote parse tree */
1173 remote_tree = ldb_parse_tree(ac, NULL);
1174 if (remote_tree == NULL) {
1175 return LDB_ERR_OPERATIONS_ERROR;
1179 ac->local_tree = local_tree;
1181 /* Prepare the remote operation */
1182 ret = ldb_build_search_req_ex(&remote_req, ldb, ac,
1183 req->op.search.base,
1184 req->op.search.scope,
1188 ac, map_remote_search_callback,
1190 if (ret != LDB_SUCCESS) {
1191 return LDB_ERR_OPERATIONS_ERROR;
1194 return ldb_next_remote_request(module, remote_req);
1197 /* Now, search the local part of a remote search result. */
1198 static int map_remote_search_callback(struct ldb_request *req,
1199 struct ldb_reply *ares)
1201 struct map_context *ac;
1204 ac = talloc_get_type(req->context, struct map_context);
1207 return ldb_module_done(ac->req, NULL, NULL,
1208 LDB_ERR_OPERATIONS_ERROR);
1210 if (ares->error != LDB_SUCCESS) {
1211 return ldb_module_done(ac->req, ares->controls,
1212 ares->response, ares->error);
1215 switch (ares->type) {
1216 case LDB_REPLY_REFERRAL:
1218 /* ignore referrals */
1222 case LDB_REPLY_ENTRY:
1224 /* Map result record into a local message */
1225 ret = map_reply_remote(ac, ares);
1228 return ldb_module_done(ac->req, NULL, NULL,
1229 LDB_ERR_OPERATIONS_ERROR);
1232 /* if we have no local db, then we can just return the reply to
1233 * the upper layer, otherwise we must save it and process it
1234 * when all replies ahve been gathered */
1235 if ( ! map_check_local_db(ac->module)) {
1236 ret = map_return_entry(ac, ares);
1238 ret = map_save_entry(ac,ares);
1241 if (ret != LDB_SUCCESS) {
1243 return ldb_module_done(ac->req, NULL, NULL,
1244 LDB_ERR_OPERATIONS_ERROR);
1248 case LDB_REPLY_DONE:
1250 if ( ! map_check_local_db(ac->module)) {
1251 return ldb_module_done(ac->req, ares->controls,
1252 ares->response, LDB_SUCCESS);
1257 /* reset the pointer to the start of the list */
1258 ac->r_current = ac->r_list;
1260 /* no entry just return */
1261 if (ac->r_current == NULL) {
1262 return ldb_module_done(ac->req, ares->controls,
1263 ares->response, LDB_SUCCESS);
1266 ret = map_search_local(ac);
1267 if (ret != LDB_SUCCESS) {
1268 return ldb_module_done(ac->req, NULL, NULL, ret);
1275 static int map_search_local(struct map_context *ac)
1277 struct ldb_request *search_req;
1279 if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1280 return LDB_ERR_OPERATIONS_ERROR;
1283 /* Prepare local search request */
1284 /* TODO: use GUIDs here instead? */
1285 search_req = map_search_base_req(ac,
1286 ac->r_current->remote->message->dn,
1288 ac, map_local_merge_callback);
1289 if (search_req == NULL) {
1290 return LDB_ERR_OPERATIONS_ERROR;
1293 return ldb_next_request(ac->module, search_req);
1296 /* Merge the remote and local parts of a search result. */
1297 int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares)
1299 struct ldb_context *ldb;
1300 struct map_context *ac;
1303 ac = talloc_get_type(req->context, struct map_context);
1304 ldb = ldb_module_get_ctx(ac->module);
1307 return ldb_module_done(ac->req, NULL, NULL,
1308 LDB_ERR_OPERATIONS_ERROR);
1310 if (ares->error != LDB_SUCCESS) {
1311 return ldb_module_done(ac->req, ares->controls,
1312 ares->response, ares->error);
1315 switch (ares->type) {
1316 case LDB_REPLY_ENTRY:
1317 /* We have already found a local record */
1318 if (ac->r_current->local) {
1320 ldb_set_errstring(ldb, "ldb_map: Too many results!");
1321 return ldb_module_done(ac->req, NULL, NULL,
1322 LDB_ERR_OPERATIONS_ERROR);
1325 /* Store local result */
1326 ac->r_current->local = talloc_steal(ac->r_current, ares);
1330 case LDB_REPLY_REFERRAL:
1331 /* ignore referrals */
1335 case LDB_REPLY_DONE:
1338 /* No local record found, map and send remote record */
1339 if (ac->r_current->local != NULL) {
1340 /* Merge remote into local message */
1341 ret = ldb_msg_merge_local(ac->module,
1342 ac->r_current->local->message,
1343 ac->r_current->remote->message);
1344 if (ret == LDB_SUCCESS) {
1345 ret = map_return_entry(ac, ac->r_current->local);
1347 if (ret != LDB_SUCCESS) {
1348 return ldb_module_done(ac->req, NULL, NULL,
1349 LDB_ERR_OPERATIONS_ERROR);
1352 ret = map_return_entry(ac, ac->r_current->remote);
1353 if (ret != LDB_SUCCESS) {
1354 return ldb_module_done(ac->req,
1359 if (ac->r_current->next != NULL) {
1360 ac->r_current = ac->r_current->next;
1361 if (ac->r_current->remote->type == LDB_REPLY_ENTRY) {
1362 ret = map_search_local(ac);
1363 if (ret != LDB_SUCCESS) {
1364 return ldb_module_done(ac->req,
1371 /* ok we are done with all search, finally it is time to
1372 * finish operations for this module */
1373 return ldb_module_done(ac->req,
1374 ac->r_current->remote->controls,
1375 ac->r_current->remote->response,
1376 ac->r_current->remote->error);