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"
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
;
267 struct ldb_context
*ldb
;
269 ldb
= ldb_module_get_ctx(module
);
271 /* We handle wildcards in ldb_msg_el_merge_wildcard */
272 if (ldb_attr_cmp(attr_name
, "*") == 0) {
276 map
= map_attr_find_local(data
, attr_name
);
278 /* Unknown attribute in remote message:
279 * skip, attribute was probably auto-generated */
288 remote_name
= map
->u
.convert
.remote_name
;
291 remote_name
= attr_name
;
294 remote_name
= map
->u
.rename
.remote_name
;
305 if (map
->u
.convert
.convert_remote
== NULL
) {
306 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
307 "Skipping attribute '%s': "
308 "'convert_remote' not set\n",
315 old
= ldb_msg_find_element(remote
, remote_name
);
317 el
= ldb_msg_el_map_remote(module
, local
, map
, attr_name
, old
);
319 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
324 if (map
->u
.generate
.generate_local
== NULL
) {
325 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
326 "Skipping attribute '%s': "
327 "'generate_local' not set\n",
332 el
= map
->u
.generate
.generate_local(module
, local
, attr_name
, remote
);
334 /* Generation failure is probably due to lack of source attributes */
335 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
341 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
344 return ldb_msg_replace(local
, el
);
347 /* Handle wildcard parts of merging a remote message element into a local message. */
348 static int ldb_msg_el_merge_wildcard(struct ldb_module
*module
, struct ldb_message
*local
,
349 struct ldb_message
*remote
)
351 const struct ldb_map_context
*data
= map_get_context(module
);
352 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, "*");
353 struct ldb_message_element
*el
=NULL
;
356 /* Perhaps we have a mapping for "*" */
357 if (map
&& map
->type
== MAP_KEEP
) {
358 /* We copy everything over, and hope that anything with a
359 more specific rule is overwritten */
360 for (i
= 0; i
< remote
->num_elements
; i
++) {
361 el
= ldb_msg_el_map_remote(module
, local
, map
, remote
->elements
[i
].name
,
362 &remote
->elements
[i
]);
364 return LDB_ERR_OPERATIONS_ERROR
;
367 ret
= ldb_msg_replace(local
, el
);
374 /* Now walk the list of possible mappings, and apply each */
375 for (i
= 0; data
->attribute_maps
[i
].local_name
; i
++) {
376 ret
= ldb_msg_el_merge(module
, local
, remote
,
377 data
->attribute_maps
[i
].local_name
);
378 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
391 * ================ */
393 /* Merge two local messages into a single one. */
394 static int ldb_msg_merge_local(struct ldb_module
*module
, struct ldb_message
*msg1
, struct ldb_message
*msg2
)
398 for (i
= 0; i
< msg2
->num_elements
; i
++) {
399 ret
= ldb_msg_replace(msg1
, &msg2
->elements
[i
]);
408 /* Merge a local and a remote message into a single local one. */
409 static int ldb_msg_merge_remote(struct map_context
*ac
, struct ldb_message
*local
,
410 struct ldb_message
*remote
)
413 const char * const *attrs
= ac
->all_attrs
;
415 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
421 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
422 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
423 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
431 /* Try to map each attribute back;
432 * Add to local message is possible,
433 * Overwrite old local attribute if necessary */
434 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
435 ret
= ldb_msg_el_merge(ac
->module
, local
, remote
,
437 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
446 /* Mapping search results
447 * ====================== */
449 /* Map a search result back into the local partition. */
450 static int map_reply_remote(struct map_context
*ac
, struct ldb_reply
*ares
)
452 struct ldb_message
*msg
;
456 /* There is no result message, skip */
457 if (ares
->type
!= LDB_REPLY_ENTRY
) {
461 /* Create a new result message */
462 msg
= ldb_msg_new(ares
);
468 /* Merge remote message into new message */
469 ret
= ldb_msg_merge_remote(ac
, msg
, ares
->message
);
475 /* Create corresponding local DN */
476 dn
= ldb_dn_map_rebase_remote(ac
->module
, msg
, ares
->message
->dn
);
483 /* Store new message with new DN as the result */
484 talloc_free(ares
->message
);
490 /* Mapping parse trees
491 * =================== */
493 /* Check whether a parse tree can safely be split in two. */
494 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree
*tree
)
496 const struct ldb_parse_tree
*subtree
= tree
;
500 switch (subtree
->operation
) {
503 subtree
= subtree
->u
.isnot
.child
;
507 return !negate
; /* if negate: False */
510 return negate
; /* if negate: True */
513 return true; /* simple parse tree */
517 return true; /* no parse tree */
520 /* Collect a list of attributes required to match a given parse tree. */
521 static int ldb_parse_tree_collect_attrs(struct ldb_module
*module
, void *mem_ctx
, const char ***attrs
, const struct ldb_parse_tree
*tree
)
523 const char **new_attrs
;
530 switch (tree
->operation
) {
532 case LDB_OP_AND
: /* attributes stored in list of subtrees */
533 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
534 ret
= ldb_parse_tree_collect_attrs(module
, mem_ctx
,
535 attrs
, tree
->u
.list
.elements
[i
]);
542 case LDB_OP_NOT
: /* attributes stored in single subtree */
543 return ldb_parse_tree_collect_attrs(module
, mem_ctx
, attrs
, tree
->u
.isnot
.child
);
545 default: /* single attribute in tree */
546 new_attrs
= ldb_attr_list_copy_add(mem_ctx
, *attrs
, tree
->u
.equality
.attr
);
555 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
557 /* Select a negated subtree that queries attributes in the local partition */
558 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
)
560 struct ldb_parse_tree
*child
;
563 /* Prepare new tree */
564 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
570 /* Generate new subtree */
571 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.isnot
.child
);
577 /* Prune tree without subtree */
584 (*new)->u
.isnot
.child
= child
;
589 /* Select a list of subtrees that query attributes in the local partition */
590 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
)
594 /* Prepare new tree */
595 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
601 /* Prepare list of subtrees */
602 (*new)->u
.list
.num_elements
= 0;
603 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
604 if ((*new)->u
.list
.elements
== NULL
) {
610 /* Generate new list of subtrees */
612 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
613 struct ldb_parse_tree
*child
;
614 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
621 (*new)->u
.list
.elements
[j
] = child
;
626 /* Prune tree without subtrees */
633 /* Fix subtree list size */
634 (*new)->u
.list
.num_elements
= j
;
635 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
640 /* Select a simple subtree that queries attributes in the local partition */
641 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
)
643 /* Prepare new tree */
644 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
653 /* Select subtrees that query attributes in the local partition */
654 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
656 const struct ldb_map_context
*data
= map_get_context(module
);
662 if (tree
->operation
== LDB_OP_NOT
) {
663 return map_subtree_select_local_not(module
, mem_ctx
, new, tree
);
666 if (tree
->operation
== LDB_OP_AND
|| tree
->operation
== LDB_OP_OR
) {
667 return map_subtree_select_local_list(module
, mem_ctx
, new, tree
);
670 if (map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
675 return map_subtree_select_local_simple(module
, mem_ctx
, new, tree
);
678 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
680 /* Collect a negated subtree that queries attributes in the remote partition */
681 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
)
683 struct ldb_parse_tree
*child
;
686 /* Prepare new tree */
687 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
693 /* Generate new subtree */
694 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.isnot
.child
);
700 /* Prune tree without subtree */
707 (*new)->u
.isnot
.child
= child
;
712 /* Collect a list of subtrees that query attributes in the remote partition */
713 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
)
717 /* Prepare new tree */
718 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
724 /* Prepare list of subtrees */
725 (*new)->u
.list
.num_elements
= 0;
726 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
727 if ((*new)->u
.list
.elements
== NULL
) {
733 /* Generate new list of subtrees */
735 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
736 struct ldb_parse_tree
*child
;
737 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
744 (*new)->u
.list
.elements
[j
] = child
;
749 /* Prune tree without subtrees */
756 /* Fix subtree list size */
757 (*new)->u
.list
.num_elements
= j
;
758 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
763 /* Collect a simple subtree that queries attributes in the remote partition */
764 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
)
768 /* Prepare new tree */
769 *new = talloc(mem_ctx
, struct ldb_parse_tree
);
776 if (map
->type
== MAP_KEEP
) {
777 /* Nothing to do here */
781 /* Store attribute and value in new tree */
782 switch (tree
->operation
) {
784 attr
= map_attr_map_local(*new, map
, tree
->u
.present
.attr
);
785 (*new)->u
.present
.attr
= attr
;
787 case LDB_OP_SUBSTRING
:
789 attr
= map_attr_map_local(*new, map
, tree
->u
.substring
.attr
);
790 (*new)->u
.substring
.attr
= attr
;
793 case LDB_OP_EQUALITY
:
794 attr
= map_attr_map_local(*new, map
, tree
->u
.equality
.attr
);
795 (*new)->u
.equality
.attr
= attr
;
800 attr
= map_attr_map_local(*new, map
, tree
->u
.comparison
.attr
);
801 (*new)->u
.comparison
.attr
= attr
;
803 case LDB_OP_EXTENDED
:
804 attr
= map_attr_map_local(*new, map
, tree
->u
.extended
.attr
);
805 (*new)->u
.extended
.attr
= attr
;
807 default: /* unknown kind of simple subtree */
818 if (map
->type
== MAP_RENAME
) {
819 /* Nothing more to do here, the attribute has been renamed */
823 /* Store attribute and value in new tree */
824 switch (tree
->operation
) {
827 case LDB_OP_SUBSTRING
:
831 (*new)->u
.substring
.chunks
= NULL
;
832 for (i
=0; tree
->u
.substring
.chunks
[i
]; i
++) {
833 (*new)->u
.substring
.chunks
= talloc_realloc(*new, (*new)->u
.substring
.chunks
, struct ldb_val
*, i
+2);
834 if (!(*new)->u
.substring
.chunks
) {
839 (*new)->u
.substring
.chunks
[i
] = talloc(*new, struct ldb_val
);
840 if (!(*new)->u
.substring
.chunks
[i
]) {
845 *(*new)->u
.substring
.chunks
[i
] = ldb_val_map_local(module
, *new, map
, tree
->u
.substring
.chunks
[i
]);
846 (*new)->u
.substring
.chunks
[i
+1] = NULL
;
850 case LDB_OP_EQUALITY
:
851 (*new)->u
.equality
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.equality
.value
);
856 (*new)->u
.comparison
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.comparison
.value
);
858 case LDB_OP_EXTENDED
:
859 (*new)->u
.extended
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.extended
.value
);
860 (*new)->u
.extended
.rule_id
= talloc_strdup(*new, tree
->u
.extended
.rule_id
);
862 default: /* unknown kind of simple subtree */
870 /* Collect subtrees that query attributes in the remote partition */
871 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
873 const struct ldb_map_context
*data
= map_get_context(module
);
874 const struct ldb_map_attribute
*map
;
875 struct ldb_context
*ldb
;
877 ldb
= ldb_module_get_ctx(module
);
883 if (tree
->operation
== LDB_OP_NOT
) {
884 return map_subtree_collect_remote_not(module
, mem_ctx
, new, tree
);
887 if ((tree
->operation
== LDB_OP_AND
) || (tree
->operation
== LDB_OP_OR
)) {
888 return map_subtree_collect_remote_list(module
, mem_ctx
, new, tree
);
891 if (!map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
896 map
= map_attr_find_local(data
, tree
->u
.equality
.attr
);
897 if (map
->convert_operator
) {
898 return map
->convert_operator(module
, mem_ctx
, new, tree
);
901 if (map
->type
== MAP_GENERATE
) {
902 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
903 "Skipping attribute '%s': "
904 "'convert_operator' not set\n",
905 tree
->u
.equality
.attr
);
910 return map_subtree_collect_remote_simple(module
, mem_ctx
, new, tree
, map
);
913 /* Split subtrees that query attributes in the local partition from
914 * those that query the remote partition. */
915 static int ldb_parse_tree_partition(struct ldb_module
*module
,
917 struct ldb_parse_tree
**local_tree
,
918 struct ldb_parse_tree
**remote_tree
,
919 const struct ldb_parse_tree
*tree
)
926 /* No original tree */
931 /* Generate local tree */
932 ret
= map_subtree_select_local(module
, mem_ctx
, local_tree
, tree
);
937 /* Generate remote tree */
938 ret
= map_subtree_collect_remote(module
, mem_ctx
, remote_tree
, tree
);
940 talloc_free(*local_tree
);
947 /* Collect a list of attributes required either explicitly from a
948 * given list or implicitly from a given parse tree; split the
949 * collected list into local and remote parts. */
950 static int map_attrs_collect_and_partition(struct ldb_module
*module
, struct map_context
*ac
,
951 const char * const *search_attrs
,
952 const struct ldb_parse_tree
*tree
)
955 const char **tree_attrs
;
956 const char **remote_attrs
;
957 const char **local_attrs
;
960 /* There is no tree, just partition the searched attributes */
962 ret
= map_attrs_partition(module
, ac
,
963 &local_attrs
, &remote_attrs
, search_attrs
);
965 ac
->local_attrs
= local_attrs
;
966 ac
->remote_attrs
= remote_attrs
;
967 ac
->all_attrs
= search_attrs
;
972 /* Create context for temporary memory */
973 tmp_ctx
= talloc_new(ac
);
974 if (tmp_ctx
== NULL
) {
978 /* Prepare list of attributes from tree */
979 tree_attrs
= talloc_array(tmp_ctx
, const char *, 1);
980 if (tree_attrs
== NULL
) {
981 talloc_free(tmp_ctx
);
984 tree_attrs
[0] = NULL
;
986 /* Collect attributes from tree */
987 ret
= ldb_parse_tree_collect_attrs(module
, tmp_ctx
, &tree_attrs
, tree
);
992 /* Merge attributes from search operation */
993 ret
= map_attrs_merge(module
, tmp_ctx
, &tree_attrs
, search_attrs
);
998 /* Split local from remote attributes */
999 ret
= map_attrs_partition(module
, ac
, &local_attrs
,
1000 &remote_attrs
, tree_attrs
);
1003 ac
->local_attrs
= local_attrs
;
1004 ac
->remote_attrs
= remote_attrs
;
1005 talloc_steal(ac
, tree_attrs
);
1006 ac
->all_attrs
= tree_attrs
;
1009 /* Free temporary memory */
1010 talloc_free(tmp_ctx
);
1019 /* Outbound requests: search
1020 * ========================= */
1022 static int map_remote_search_callback(struct ldb_request
*req
,
1023 struct ldb_reply
*ares
);
1024 static int map_local_merge_callback(struct ldb_request
*req
,
1025 struct ldb_reply
*ares
);
1026 static int map_search_local(struct map_context
*ac
);
1028 static int map_save_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1030 struct map_reply
*mr
;
1032 mr
= talloc_zero(ac
, struct map_reply
);
1034 map_oom(ac
->module
);
1035 return LDB_ERR_OPERATIONS_ERROR
;
1037 mr
->remote
= talloc_steal(mr
, ares
);
1038 if (ac
->r_current
) {
1039 ac
->r_current
->next
= mr
;
1049 /* Pass a merged search result up the callback chain. */
1050 int map_return_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1052 struct ldb_message_element
*el
;
1053 const char * const *attrs
;
1054 struct ldb_context
*ldb
;
1057 ldb
= ldb_module_get_ctx(ac
->module
);
1059 /* Merged result doesn't match original query, skip */
1060 if (!ldb_match_msg(ldb
, ares
->message
,
1061 ac
->req
->op
.search
.tree
,
1062 ac
->req
->op
.search
.base
,
1063 ac
->req
->op
.search
.scope
)) {
1064 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "ldb_map: "
1065 "Skipping record '%s': "
1066 "doesn't match original search\n",
1067 ldb_dn_get_linearized(ares
->message
->dn
));
1071 /* Limit result to requested attrs */
1072 if (ac
->req
->op
.search
.attrs
&&
1073 (! ldb_attr_in_list(ac
->req
->op
.search
.attrs
, "*"))) {
1075 attrs
= ac
->req
->op
.search
.attrs
;
1078 while (i
< ares
->message
->num_elements
) {
1080 el
= &ares
->message
->elements
[i
];
1081 if ( ! ldb_attr_in_list(attrs
, el
->name
)) {
1082 ldb_msg_remove_element(ares
->message
, el
);
1089 return ldb_module_send_entry(ac
->req
, ares
->message
, ares
->controls
);
1092 /* Search a record. */
1093 int map_search(struct ldb_module
*module
, struct ldb_request
*req
)
1095 struct ldb_parse_tree
*remote_tree
;
1096 struct ldb_parse_tree
*local_tree
;
1097 struct ldb_request
*remote_req
;
1098 struct ldb_context
*ldb
;
1099 struct map_context
*ac
;
1102 const char *wildcard
[] = { "*", NULL
};
1103 const char * const *attrs
;
1105 ldb
= ldb_module_get_ctx(module
);
1107 /* if we're not yet initialized, go to the next module */
1108 if (!ldb_module_get_private(module
))
1109 return ldb_next_request(module
, req
);
1111 /* Do not manipulate our control entries */
1112 if (ldb_dn_is_special(req
->op
.search
.base
)) {
1113 return ldb_next_request(module
, req
);
1116 /* No mapping requested, skip to next module */
1117 if ((req
->op
.search
.base
) && (!ldb_dn_check_local(module
, req
->op
.search
.base
))) {
1118 return ldb_next_request(module
, req
);
1121 /* TODO: How can we be sure about which partition we are
1122 * targetting when there is no search base? */
1124 /* Prepare context and handle */
1125 ac
= map_init_context(module
, req
);
1127 return LDB_ERR_OPERATIONS_ERROR
;
1130 /* It is easier to deal with the two different ways of
1131 * expressing the wildcard in the same codepath */
1132 attrs
= req
->op
.search
.attrs
;
1133 if (attrs
== NULL
) {
1137 /* Split local from remote attrs */
1138 ret
= map_attrs_collect_and_partition(module
, ac
,
1139 attrs
, req
->op
.search
.tree
);
1141 return LDB_ERR_OPERATIONS_ERROR
;
1144 /* Split local from remote tree */
1145 ret
= ldb_parse_tree_partition(module
, ac
,
1146 &local_tree
, &remote_tree
,
1147 req
->op
.search
.tree
);
1149 return LDB_ERR_OPERATIONS_ERROR
;
1152 if (((local_tree
!= NULL
) && (remote_tree
!= NULL
)) &&
1153 (!ldb_parse_tree_check_splittable(req
->op
.search
.tree
))) {
1154 /* The query can't safely be split, enumerate the remote partition */
1159 if (local_tree
== NULL
) {
1160 /* Construct default local parse tree */
1161 local_tree
= talloc_zero(ac
, struct ldb_parse_tree
);
1162 if (local_tree
== NULL
) {
1163 map_oom(ac
->module
);
1164 return LDB_ERR_OPERATIONS_ERROR
;
1167 local_tree
->operation
= LDB_OP_PRESENT
;
1168 local_tree
->u
.present
.attr
= talloc_strdup(local_tree
, IS_MAPPED
);
1170 if (remote_tree
== NULL
) {
1171 /* Construct default remote parse tree */
1172 remote_tree
= ldb_parse_tree(ac
, NULL
);
1173 if (remote_tree
== NULL
) {
1174 return LDB_ERR_OPERATIONS_ERROR
;
1178 ac
->local_tree
= local_tree
;
1180 /* Prepare the remote operation */
1181 ret
= ldb_build_search_req_ex(&remote_req
, ldb
, ac
,
1182 req
->op
.search
.base
,
1183 req
->op
.search
.scope
,
1187 ac
, map_remote_search_callback
,
1189 if (ret
!= LDB_SUCCESS
) {
1190 return LDB_ERR_OPERATIONS_ERROR
;
1193 return ldb_next_remote_request(module
, remote_req
);
1196 /* Now, search the local part of a remote search result. */
1197 static int map_remote_search_callback(struct ldb_request
*req
,
1198 struct ldb_reply
*ares
)
1200 struct map_context
*ac
;
1203 ac
= talloc_get_type(req
->context
, struct map_context
);
1206 return ldb_module_done(ac
->req
, NULL
, NULL
,
1207 LDB_ERR_OPERATIONS_ERROR
);
1209 if (ares
->error
!= LDB_SUCCESS
) {
1210 return ldb_module_done(ac
->req
, ares
->controls
,
1211 ares
->response
, ares
->error
);
1214 switch (ares
->type
) {
1215 case LDB_REPLY_REFERRAL
:
1217 /* ignore referrals */
1221 case LDB_REPLY_ENTRY
:
1223 /* Map result record into a local message */
1224 ret
= map_reply_remote(ac
, ares
);
1227 return ldb_module_done(ac
->req
, NULL
, NULL
,
1228 LDB_ERR_OPERATIONS_ERROR
);
1231 /* if we have no local db, then we can just return the reply to
1232 * the upper layer, otherwise we must save it and process it
1233 * when all replies ahve been gathered */
1234 if ( ! map_check_local_db(ac
->module
)) {
1235 ret
= map_return_entry(ac
, ares
);
1237 ret
= map_save_entry(ac
,ares
);
1240 if (ret
!= LDB_SUCCESS
) {
1242 return ldb_module_done(ac
->req
, NULL
, NULL
,
1243 LDB_ERR_OPERATIONS_ERROR
);
1247 case LDB_REPLY_DONE
:
1249 if ( ! map_check_local_db(ac
->module
)) {
1250 return ldb_module_done(ac
->req
, ares
->controls
,
1251 ares
->response
, LDB_SUCCESS
);
1256 /* reset the pointer to the start of the list */
1257 ac
->r_current
= ac
->r_list
;
1259 /* no entry just return */
1260 if (ac
->r_current
== NULL
) {
1261 return ldb_module_done(ac
->req
, ares
->controls
,
1262 ares
->response
, LDB_SUCCESS
);
1265 ret
= map_search_local(ac
);
1266 if (ret
!= LDB_SUCCESS
) {
1267 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
1274 static int map_search_local(struct map_context
*ac
)
1276 struct ldb_request
*search_req
;
1278 if (ac
->r_current
== NULL
|| ac
->r_current
->remote
== NULL
) {
1279 return LDB_ERR_OPERATIONS_ERROR
;
1282 /* Prepare local search request */
1283 /* TODO: use GUIDs here instead? */
1284 search_req
= map_search_base_req(ac
,
1285 ac
->r_current
->remote
->message
->dn
,
1287 ac
, map_local_merge_callback
);
1288 if (search_req
== NULL
) {
1289 return LDB_ERR_OPERATIONS_ERROR
;
1292 return ldb_next_request(ac
->module
, search_req
);
1295 /* Merge the remote and local parts of a search result. */
1296 int map_local_merge_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
1298 struct ldb_context
*ldb
;
1299 struct map_context
*ac
;
1302 ac
= talloc_get_type(req
->context
, struct map_context
);
1303 ldb
= ldb_module_get_ctx(ac
->module
);
1306 return ldb_module_done(ac
->req
, NULL
, NULL
,
1307 LDB_ERR_OPERATIONS_ERROR
);
1309 if (ares
->error
!= LDB_SUCCESS
) {
1310 return ldb_module_done(ac
->req
, ares
->controls
,
1311 ares
->response
, ares
->error
);
1314 switch (ares
->type
) {
1315 case LDB_REPLY_ENTRY
:
1316 /* We have already found a local record */
1317 if (ac
->r_current
->local
) {
1319 ldb_set_errstring(ldb
, "ldb_map: Too many results!");
1320 return ldb_module_done(ac
->req
, NULL
, NULL
,
1321 LDB_ERR_OPERATIONS_ERROR
);
1324 /* Store local result */
1325 ac
->r_current
->local
= talloc_steal(ac
->r_current
, ares
);
1329 case LDB_REPLY_REFERRAL
:
1330 /* ignore referrals */
1334 case LDB_REPLY_DONE
:
1337 /* No local record found, map and send remote record */
1338 if (ac
->r_current
->local
!= NULL
) {
1339 /* Merge remote into local message */
1340 ret
= ldb_msg_merge_local(ac
->module
,
1341 ac
->r_current
->local
->message
,
1342 ac
->r_current
->remote
->message
);
1343 if (ret
== LDB_SUCCESS
) {
1344 ret
= map_return_entry(ac
, ac
->r_current
->local
);
1346 if (ret
!= LDB_SUCCESS
) {
1347 return ldb_module_done(ac
->req
, NULL
, NULL
,
1348 LDB_ERR_OPERATIONS_ERROR
);
1351 ret
= map_return_entry(ac
, ac
->r_current
->remote
);
1352 if (ret
!= LDB_SUCCESS
) {
1353 return ldb_module_done(ac
->req
,
1358 if (ac
->r_current
->next
!= NULL
) {
1359 ac
->r_current
= ac
->r_current
->next
;
1360 if (ac
->r_current
->remote
->type
== LDB_REPLY_ENTRY
) {
1361 ret
= map_search_local(ac
);
1362 if (ret
!= LDB_SUCCESS
) {
1363 return ldb_module_done(ac
->req
,
1370 /* ok we are done with all search, finally it is time to
1371 * finish operations for this module */
1372 return ldb_module_done(ac
->req
,
1373 ac
->r_current
->remote
->controls
,
1374 ac
->r_current
->remote
->response
,
1375 ac
->r_current
->remote
->error
);