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"
30 #include "ldb_map_private.h"
34 * ================== */
36 /* Select attributes that stay in the local partition. */
37 static const char **map_attrs_select_local(struct ldb_module
*module
, void *mem_ctx
, const char * const *attrs
)
39 const struct ldb_map_context
*data
= map_get_context(module
);
47 result
= talloc_array(mem_ctx
, const char *, 1);
53 for (i
= 0; attrs
[i
]; i
++) {
54 /* Wildcards and ignored attributes are kept locally */
55 if ((ldb_attr_cmp(attrs
[i
], "*") == 0) ||
56 (!map_attr_check_remote(data
, attrs
[i
]))) {
57 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
62 result
[last
] = talloc_strdup(result
, attrs
[i
]);
63 result
[last
+1] = NULL
;
76 /* Collect attributes that are mapped into the remote partition. */
77 static const char **map_attrs_collect_remote(struct ldb_module
*module
, void *mem_ctx
,
78 const char * const *attrs
)
80 const struct ldb_map_context
*data
= map_get_context(module
);
82 const struct ldb_map_attribute
*map
;
83 const char *name
=NULL
;
84 unsigned int i
, j
, last
;
88 result
= talloc_array(mem_ctx
, const char *, 1);
94 for (i
= 0; attrs
[i
]; i
++) {
95 /* Wildcards are kept remotely, too */
96 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
97 const char **new_attrs
= NULL
;
98 ret
= map_attrs_merge(module
, mem_ctx
, &new_attrs
, attrs
);
99 if (ret
!= LDB_SUCCESS
) {
102 ret
= map_attrs_merge(module
, mem_ctx
, &new_attrs
, data
->wildcard_attributes
);
103 if (ret
!= LDB_SUCCESS
) {
112 for (i
= 0; attrs
[i
]; i
++) {
113 /* Wildcards are kept remotely, too */
114 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
115 /* Add all 'include in wildcard' attributes */
120 /* Add remote names of mapped attrs */
121 map
= map_attr_find_local(data
, attrs
[i
]);
135 case LDB_MAP_CONVERT
:
136 name
= map
->u
.rename
.remote_name
;
139 case LDB_MAP_GENERATE
:
140 /* Add all remote names of "generate" attrs */
141 for (j
= 0; map
->u
.generate
.remote_names
[j
]; j
++) {
142 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
143 if (result
== NULL
) {
147 result
[last
] = talloc_strdup(result
, map
->u
.generate
.remote_names
[j
]);
148 result
[last
+1] = NULL
;
154 named
: /* We found a single remote name, add that */
155 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
156 if (result
== NULL
) {
160 result
[last
] = talloc_strdup(result
, name
);
161 result
[last
+1] = NULL
;
173 /* Split attributes that stay in the local partition from those that
174 * are mapped into the remote partition. */
175 static int map_attrs_partition(struct ldb_module
*module
, void *mem_ctx
, const char ***local_attrs
, const char ***remote_attrs
, const char * const *attrs
)
177 *local_attrs
= map_attrs_select_local(module
, mem_ctx
, attrs
);
178 *remote_attrs
= map_attrs_collect_remote(module
, mem_ctx
, attrs
);
183 /* Mapping message elements
184 * ======================== */
186 /* Add an element to a message, overwriting any old identically named elements. */
187 static int ldb_msg_replace(struct ldb_message
*msg
, const struct ldb_message_element
*el
)
189 struct ldb_message_element
*old
;
191 old
= ldb_msg_find_element(msg
, el
->name
);
193 /* no local result, add as new element */
195 if (ldb_msg_add_empty(msg
, el
->name
, 0, &old
) != 0) {
198 talloc_free(discard_const_p(char, old
->name
));
201 /* copy new element */
204 /* and make sure we reference the contents */
205 if (!talloc_reference(msg
->elements
, el
->name
)) {
208 if (!talloc_reference(msg
->elements
, el
->values
)) {
215 /* Map a message element back into the local partition. */
216 static struct ldb_message_element
*ldb_msg_el_map_remote(struct ldb_module
*module
,
218 const struct ldb_map_attribute
*map
,
219 const char *attr_name
,
220 const struct ldb_message_element
*old
)
222 const struct ldb_map_context
*data
= map_get_context(module
);
223 const char *local_attr_name
= attr_name
;
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 for (i
= 0; data
->attribute_maps
[i
].local_name
; i
++) {
241 struct ldb_map_attribute
*am
= &data
->attribute_maps
[i
];
242 if ((am
->type
== LDB_MAP_RENAME
&&
243 !strcmp(am
->u
.rename
.remote_name
, attr_name
))
244 || (am
->type
== LDB_MAP_CONVERT
&&
245 !strcmp(am
->u
.convert
.remote_name
, attr_name
))) {
247 local_attr_name
= am
->local_name
;
252 el
->name
= talloc_strdup(el
, local_attr_name
);
253 if (el
->name
== NULL
) {
259 for (i
= 0; i
< old
->num_values
; i
++) {
260 el
->values
[i
] = ldb_val_map_remote(module
, el
->values
, map
, &old
->values
[i
]);
261 /* Conversions might fail, in which case bail */
262 if (!el
->values
[i
].data
) {
272 /* Merge a remote message element into a local message. */
273 static int ldb_msg_el_merge(struct ldb_module
*module
, struct ldb_message
*local
,
274 struct ldb_message
*remote
, const char *attr_name
)
276 const struct ldb_map_context
*data
= map_get_context(module
);
277 const struct ldb_map_attribute
*map
;
278 struct ldb_message_element
*old
, *el
=NULL
;
279 const char *remote_name
= NULL
;
280 struct ldb_context
*ldb
;
282 ldb
= ldb_module_get_ctx(module
);
284 /* We handle wildcards in ldb_msg_el_merge_wildcard */
285 if (ldb_attr_cmp(attr_name
, "*") == 0) {
289 map
= map_attr_find_local(data
, attr_name
);
291 /* Unknown attribute in remote message:
292 * skip, attribute was probably auto-generated */
300 case LDB_MAP_CONVERT
:
301 remote_name
= map
->u
.convert
.remote_name
;
304 remote_name
= attr_name
;
307 remote_name
= map
->u
.rename
.remote_name
;
309 case LDB_MAP_GENERATE
:
317 case LDB_MAP_CONVERT
:
318 if (map
->u
.convert
.convert_remote
== NULL
) {
319 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
320 "Skipping attribute '%s': "
321 "'convert_remote' not set",
328 old
= ldb_msg_find_element(remote
, remote_name
);
330 el
= ldb_msg_el_map_remote(module
, local
, map
, attr_name
, old
);
332 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
336 case LDB_MAP_GENERATE
:
337 if (map
->u
.generate
.generate_local
== NULL
) {
338 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
339 "Skipping attribute '%s': "
340 "'generate_local' not set",
345 el
= map
->u
.generate
.generate_local(module
, local
, attr_name
, remote
);
347 /* Generation failure is probably due to lack of source attributes */
348 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
354 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
357 return ldb_msg_replace(local
, el
);
360 /* Handle wildcard parts of merging a remote message element into a local message. */
361 static int ldb_msg_el_merge_wildcard(struct ldb_module
*module
, struct ldb_message
*local
,
362 struct ldb_message
*remote
)
364 const struct ldb_map_context
*data
= map_get_context(module
);
365 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, "*");
366 struct ldb_message_element
*el
=NULL
;
370 /* Perhaps we have a mapping for "*" */
371 if (map
&& map
->type
== LDB_MAP_KEEP
) {
372 /* We copy everything over, and hope that anything with a
373 more specific rule is overwritten */
374 for (i
= 0; i
< remote
->num_elements
; i
++) {
375 el
= ldb_msg_el_map_remote(module
, local
, map
, remote
->elements
[i
].name
,
376 &remote
->elements
[i
]);
378 return LDB_ERR_OPERATIONS_ERROR
;
381 ret
= ldb_msg_replace(local
, el
);
388 /* Now walk the list of possible mappings, and apply each */
389 for (i
= 0; data
->attribute_maps
[i
].local_name
; i
++) {
390 ret
= ldb_msg_el_merge(module
, local
, remote
,
391 data
->attribute_maps
[i
].local_name
);
392 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
405 * ================ */
407 /* Merge two local messages into a single one. */
408 static int ldb_msg_merge_local(struct ldb_module
*module
, struct ldb_message
*msg1
, struct ldb_message
*msg2
)
413 for (i
= 0; i
< msg2
->num_elements
; i
++) {
414 ret
= ldb_msg_replace(msg1
, &msg2
->elements
[i
]);
423 /* Merge a local and a remote message into a single local one. */
424 static int ldb_msg_merge_remote(struct map_context
*ac
, struct ldb_message
*local
,
425 struct ldb_message
*remote
)
429 const char * const *attrs
= ac
->all_attrs
;
431 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
437 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
438 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
439 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
447 /* Try to map each attribute back;
448 * Add to local message is possible,
449 * Overwrite old local attribute if necessary */
450 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
451 ret
= ldb_msg_el_merge(ac
->module
, local
, remote
,
453 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
462 /* Mapping search results
463 * ====================== */
465 /* Map a search result back into the local partition. */
466 static int map_reply_remote(struct map_context
*ac
, struct ldb_reply
*ares
)
468 struct ldb_message
*msg
;
472 /* There is no result message, skip */
473 if (ares
->type
!= LDB_REPLY_ENTRY
) {
477 /* Create a new result message */
478 msg
= ldb_msg_new(ares
);
484 /* Merge remote message into new message */
485 ret
= ldb_msg_merge_remote(ac
, msg
, ares
->message
);
491 /* Create corresponding local DN */
492 dn
= ldb_dn_map_rebase_remote(ac
->module
, msg
, ares
->message
->dn
);
499 /* Store new message with new DN as the result */
500 talloc_free(ares
->message
);
506 /* Mapping parse trees
507 * =================== */
509 /* Check whether a parse tree can safely be split in two. */
510 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree
*tree
)
512 const struct ldb_parse_tree
*subtree
= tree
;
516 switch (subtree
->operation
) {
519 subtree
= subtree
->u
.isnot
.child
;
523 return !negate
; /* if negate: False */
526 return negate
; /* if negate: True */
529 return true; /* simple parse tree */
533 return true; /* no parse tree */
536 /* Collect a list of attributes required to match a given parse tree. */
537 static int ldb_parse_tree_collect_attrs(struct ldb_module
*module
, void *mem_ctx
, const char ***attrs
, const struct ldb_parse_tree
*tree
)
539 const char **new_attrs
;
547 switch (tree
->operation
) {
549 case LDB_OP_AND
: /* attributes stored in list of subtrees */
550 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
551 ret
= ldb_parse_tree_collect_attrs(module
, mem_ctx
,
552 attrs
, tree
->u
.list
.elements
[i
]);
559 case LDB_OP_NOT
: /* attributes stored in single subtree */
560 return ldb_parse_tree_collect_attrs(module
, mem_ctx
, attrs
, tree
->u
.isnot
.child
);
562 default: /* single attribute in tree */
563 new_attrs
= ldb_attr_list_copy_add(mem_ctx
, *attrs
, tree
->u
.equality
.attr
);
570 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
572 /* Select a negated subtree that queries attributes in the local partition */
573 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
)
575 struct ldb_parse_tree
*child
;
578 /* Prepare new tree */
579 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
585 /* Generate new subtree */
586 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.isnot
.child
);
592 /* Prune tree without subtree */
599 (*new)->u
.isnot
.child
= child
;
604 /* Select a list of subtrees that query attributes in the local partition */
605 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
)
610 /* Prepare new tree */
611 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
617 /* Prepare list of subtrees */
618 (*new)->u
.list
.num_elements
= 0;
619 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
620 if ((*new)->u
.list
.elements
== NULL
) {
626 /* Generate new list of subtrees */
628 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
629 struct ldb_parse_tree
*child
;
630 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
637 (*new)->u
.list
.elements
[j
] = child
;
642 /* Prune tree without subtrees */
649 /* Fix subtree list size */
650 (*new)->u
.list
.num_elements
= j
;
651 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
656 /* Select a simple subtree that queries attributes in the local partition */
657 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
)
659 /* Prepare new tree */
660 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
669 /* Select subtrees that query attributes in the local partition */
670 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
672 const struct ldb_map_context
*data
= map_get_context(module
);
678 if (tree
->operation
== LDB_OP_NOT
) {
679 return map_subtree_select_local_not(module
, mem_ctx
, new, tree
);
682 if (tree
->operation
== LDB_OP_AND
|| tree
->operation
== LDB_OP_OR
) {
683 return map_subtree_select_local_list(module
, mem_ctx
, new, tree
);
686 if (map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
691 return map_subtree_select_local_simple(module
, mem_ctx
, new, tree
);
694 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
696 /* Collect a negated subtree that queries attributes in the remote partition */
697 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
)
699 struct ldb_parse_tree
*child
;
702 /* Prepare new tree */
703 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
709 /* Generate new subtree */
710 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.isnot
.child
);
716 /* Prune tree without subtree */
723 (*new)->u
.isnot
.child
= child
;
728 /* Collect a list of subtrees that query attributes in the remote partition */
729 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
)
734 /* Prepare new tree */
735 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
741 /* Prepare list of subtrees */
742 (*new)->u
.list
.num_elements
= 0;
743 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
744 if ((*new)->u
.list
.elements
== NULL
) {
750 /* Generate new list of subtrees */
752 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
753 struct ldb_parse_tree
*child
;
754 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
761 (*new)->u
.list
.elements
[j
] = child
;
766 /* Prune tree without subtrees */
773 /* Fix subtree list size */
774 (*new)->u
.list
.num_elements
= j
;
775 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
780 /* Collect a simple subtree that queries attributes in the remote partition */
781 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
)
785 /* Prepare new tree */
786 *new = talloc(mem_ctx
, struct ldb_parse_tree
);
793 if (map
->type
== LDB_MAP_KEEP
) {
794 /* Nothing to do here */
798 /* Store attribute and value in new tree */
799 switch (tree
->operation
) {
801 attr
= map_attr_map_local(*new, map
, tree
->u
.present
.attr
);
802 (*new)->u
.present
.attr
= attr
;
804 case LDB_OP_SUBSTRING
:
806 attr
= map_attr_map_local(*new, map
, tree
->u
.substring
.attr
);
807 (*new)->u
.substring
.attr
= attr
;
810 case LDB_OP_EQUALITY
:
811 attr
= map_attr_map_local(*new, map
, tree
->u
.equality
.attr
);
812 (*new)->u
.equality
.attr
= attr
;
817 attr
= map_attr_map_local(*new, map
, tree
->u
.comparison
.attr
);
818 (*new)->u
.comparison
.attr
= attr
;
820 case LDB_OP_EXTENDED
:
821 attr
= map_attr_map_local(*new, map
, tree
->u
.extended
.attr
);
822 (*new)->u
.extended
.attr
= attr
;
824 default: /* unknown kind of simple subtree */
835 if (map
->type
== LDB_MAP_RENAME
) {
836 /* Nothing more to do here, the attribute has been renamed */
840 /* Store attribute and value in new tree */
841 switch (tree
->operation
) {
844 case LDB_OP_SUBSTRING
:
848 (*new)->u
.substring
.chunks
= NULL
;
849 for (i
=0; tree
->u
.substring
.chunks
[i
]; i
++) {
850 (*new)->u
.substring
.chunks
= talloc_realloc(*new, (*new)->u
.substring
.chunks
, struct ldb_val
*, i
+2);
851 if (!(*new)->u
.substring
.chunks
) {
856 (*new)->u
.substring
.chunks
[i
] = talloc(*new, struct ldb_val
);
857 if (!(*new)->u
.substring
.chunks
[i
]) {
862 *(*new)->u
.substring
.chunks
[i
] = ldb_val_map_local(module
, *new, map
, tree
->u
.substring
.chunks
[i
]);
863 (*new)->u
.substring
.chunks
[i
+1] = NULL
;
867 case LDB_OP_EQUALITY
:
868 (*new)->u
.equality
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.equality
.value
);
873 (*new)->u
.comparison
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.comparison
.value
);
875 case LDB_OP_EXTENDED
:
876 (*new)->u
.extended
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.extended
.value
);
877 (*new)->u
.extended
.rule_id
= talloc_strdup(*new, tree
->u
.extended
.rule_id
);
879 default: /* unknown kind of simple subtree */
887 /* Collect subtrees that query attributes in the remote partition */
888 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
890 const struct ldb_map_context
*data
= map_get_context(module
);
891 const struct ldb_map_attribute
*map
;
892 struct ldb_context
*ldb
;
894 ldb
= ldb_module_get_ctx(module
);
900 if (tree
->operation
== LDB_OP_NOT
) {
901 return map_subtree_collect_remote_not(module
, mem_ctx
, new, tree
);
904 if ((tree
->operation
== LDB_OP_AND
) || (tree
->operation
== LDB_OP_OR
)) {
905 return map_subtree_collect_remote_list(module
, mem_ctx
, new, tree
);
908 if (!map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
913 map
= map_attr_find_local(data
, tree
->u
.equality
.attr
);
914 if (map
->convert_operator
) {
915 return map
->convert_operator(module
, mem_ctx
, new, tree
);
918 if (map
->type
== LDB_MAP_GENERATE
) {
919 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
920 "Skipping attribute '%s': "
921 "'convert_operator' not set",
922 tree
->u
.equality
.attr
);
927 return map_subtree_collect_remote_simple(module
, mem_ctx
, new, tree
, map
);
930 /* Split subtrees that query attributes in the local partition from
931 * those that query the remote partition. */
932 static int ldb_parse_tree_partition(struct ldb_module
*module
,
934 struct ldb_parse_tree
**local_tree
,
935 struct ldb_parse_tree
**remote_tree
,
936 const struct ldb_parse_tree
*tree
)
943 /* No original tree */
948 /* Generate local tree */
949 ret
= map_subtree_select_local(module
, mem_ctx
, local_tree
, tree
);
954 /* Generate remote tree */
955 ret
= map_subtree_collect_remote(module
, mem_ctx
, remote_tree
, tree
);
957 talloc_free(*local_tree
);
964 /* Collect a list of attributes required either explicitly from a
965 * given list or implicitly from a given parse tree; split the
966 * collected list into local and remote parts. */
967 static int map_attrs_collect_and_partition(struct ldb_module
*module
, struct map_context
*ac
,
968 const char * const *search_attrs
,
969 const struct ldb_parse_tree
*tree
)
972 const char **tree_attrs
;
973 const char **remote_attrs
;
974 const char **local_attrs
;
977 /* There is no tree, just partition the searched attributes */
979 ret
= map_attrs_partition(module
, ac
,
980 &local_attrs
, &remote_attrs
, search_attrs
);
982 ac
->local_attrs
= local_attrs
;
983 ac
->remote_attrs
= remote_attrs
;
984 ac
->all_attrs
= search_attrs
;
989 /* Create context for temporary memory */
990 tmp_ctx
= talloc_new(ac
);
991 if (tmp_ctx
== NULL
) {
995 /* Prepare list of attributes from tree */
996 tree_attrs
= talloc_array(tmp_ctx
, const char *, 1);
997 if (tree_attrs
== NULL
) {
998 talloc_free(tmp_ctx
);
1001 tree_attrs
[0] = NULL
;
1003 /* Collect attributes from tree */
1004 ret
= ldb_parse_tree_collect_attrs(module
, tmp_ctx
, &tree_attrs
, tree
);
1009 /* Merge attributes from search operation */
1010 ret
= map_attrs_merge(module
, tmp_ctx
, &tree_attrs
, search_attrs
);
1015 /* Split local from remote attributes */
1016 ret
= map_attrs_partition(module
, ac
, &local_attrs
,
1017 &remote_attrs
, tree_attrs
);
1020 ac
->local_attrs
= local_attrs
;
1021 ac
->remote_attrs
= remote_attrs
;
1022 talloc_steal(ac
, tree_attrs
);
1023 ac
->all_attrs
= tree_attrs
;
1026 /* Free temporary memory */
1027 talloc_free(tmp_ctx
);
1036 /* Outbound requests: search
1037 * ========================= */
1039 static int map_remote_search_callback(struct ldb_request
*req
,
1040 struct ldb_reply
*ares
);
1041 static int map_local_merge_callback(struct ldb_request
*req
,
1042 struct ldb_reply
*ares
);
1043 static int map_search_local(struct map_context
*ac
);
1045 static int map_save_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1047 struct map_reply
*mr
;
1049 mr
= talloc_zero(ac
, struct map_reply
);
1051 map_oom(ac
->module
);
1052 return LDB_ERR_OPERATIONS_ERROR
;
1054 mr
->remote
= talloc_steal(mr
, ares
);
1055 if (ac
->r_current
) {
1056 ac
->r_current
->next
= mr
;
1066 /* Pass a merged search result up the callback chain. */
1067 int map_return_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1069 struct ldb_message_element
*el
;
1070 const char * const *attrs
;
1071 struct ldb_context
*ldb
;
1074 ldb
= ldb_module_get_ctx(ac
->module
);
1076 /* Merged result doesn't match original query, skip */
1077 if (!ldb_match_msg(ldb
, ares
->message
,
1078 ac
->req
->op
.search
.tree
,
1079 ac
->req
->op
.search
.base
,
1080 ac
->req
->op
.search
.scope
)) {
1081 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "ldb_map: "
1082 "Skipping record '%s': "
1083 "doesn't match original search",
1084 ldb_dn_get_linearized(ares
->message
->dn
));
1088 /* Limit result to requested attrs */
1089 if (ac
->req
->op
.search
.attrs
&&
1090 (! ldb_attr_in_list(ac
->req
->op
.search
.attrs
, "*"))) {
1092 attrs
= ac
->req
->op
.search
.attrs
;
1095 while (i
< ares
->message
->num_elements
) {
1097 el
= &ares
->message
->elements
[i
];
1098 if ( ! ldb_attr_in_list(attrs
, el
->name
)) {
1099 ldb_msg_remove_element(ares
->message
, el
);
1106 return ldb_module_send_entry(ac
->req
, ares
->message
, ares
->controls
);
1109 /* Search a record. */
1110 int map_search(struct ldb_module
*module
, struct ldb_request
*req
)
1112 struct ldb_parse_tree
*remote_tree
;
1113 struct ldb_parse_tree
*local_tree
;
1114 struct ldb_request
*remote_req
;
1115 struct ldb_context
*ldb
;
1116 struct map_context
*ac
;
1119 const char *wildcard
[] = { "*", NULL
};
1120 const char * const *attrs
;
1122 ldb
= ldb_module_get_ctx(module
);
1124 /* if we're not yet initialized, go to the next module */
1125 if (!ldb_module_get_private(module
))
1126 return ldb_next_request(module
, req
);
1128 /* Do not manipulate our control entries */
1129 if (ldb_dn_is_special(req
->op
.search
.base
)) {
1130 return ldb_next_request(module
, req
);
1133 /* No mapping requested, skip to next module */
1134 if ((req
->op
.search
.base
) && (!ldb_dn_check_local(module
, req
->op
.search
.base
))) {
1135 return ldb_next_request(module
, req
);
1138 /* TODO: How can we be sure about which partition we are
1139 * targetting when there is no search base? */
1141 /* Prepare context and handle */
1142 ac
= map_init_context(module
, req
);
1144 return LDB_ERR_OPERATIONS_ERROR
;
1147 /* It is easier to deal with the two different ways of
1148 * expressing the wildcard in the same codepath */
1149 attrs
= req
->op
.search
.attrs
;
1150 if (attrs
== NULL
) {
1154 /* Split local from remote attrs */
1155 ret
= map_attrs_collect_and_partition(module
, ac
,
1156 attrs
, req
->op
.search
.tree
);
1158 return LDB_ERR_OPERATIONS_ERROR
;
1161 /* Split local from remote tree */
1162 ret
= ldb_parse_tree_partition(module
, ac
,
1163 &local_tree
, &remote_tree
,
1164 req
->op
.search
.tree
);
1166 return LDB_ERR_OPERATIONS_ERROR
;
1169 if (((local_tree
!= NULL
) && (remote_tree
!= NULL
)) &&
1170 (!ldb_parse_tree_check_splittable(req
->op
.search
.tree
))) {
1171 /* The query can't safely be split, enumerate the remote partition */
1176 if (local_tree
== NULL
) {
1177 /* Construct default local parse tree */
1178 local_tree
= talloc_zero(ac
, struct ldb_parse_tree
);
1179 if (local_tree
== NULL
) {
1180 map_oom(ac
->module
);
1181 return LDB_ERR_OPERATIONS_ERROR
;
1184 local_tree
->operation
= LDB_OP_PRESENT
;
1185 local_tree
->u
.present
.attr
= talloc_strdup(local_tree
, IS_MAPPED
);
1187 if (remote_tree
== NULL
) {
1188 /* Construct default remote parse tree */
1189 remote_tree
= ldb_parse_tree(ac
, NULL
);
1190 if (remote_tree
== NULL
) {
1191 return LDB_ERR_OPERATIONS_ERROR
;
1195 ac
->local_tree
= local_tree
;
1197 /* Prepare the remote operation */
1198 ret
= ldb_build_search_req_ex(&remote_req
, ldb
, ac
,
1199 req
->op
.search
.base
,
1200 req
->op
.search
.scope
,
1204 ac
, map_remote_search_callback
,
1206 if (ret
!= LDB_SUCCESS
) {
1207 return LDB_ERR_OPERATIONS_ERROR
;
1210 return ldb_next_remote_request(module
, remote_req
);
1213 /* Now, search the local part of a remote search result. */
1214 static int map_remote_search_callback(struct ldb_request
*req
,
1215 struct ldb_reply
*ares
)
1217 struct map_context
*ac
;
1220 ac
= talloc_get_type(req
->context
, struct map_context
);
1223 return ldb_module_done(ac
->req
, NULL
, NULL
,
1224 LDB_ERR_OPERATIONS_ERROR
);
1226 if (ares
->error
!= LDB_SUCCESS
) {
1227 return ldb_module_done(ac
->req
, ares
->controls
,
1228 ares
->response
, ares
->error
);
1231 switch (ares
->type
) {
1232 case LDB_REPLY_REFERRAL
:
1234 /* ignore referrals */
1238 case LDB_REPLY_ENTRY
:
1240 /* Map result record into a local message */
1241 ret
= map_reply_remote(ac
, ares
);
1244 return ldb_module_done(ac
->req
, NULL
, NULL
,
1245 LDB_ERR_OPERATIONS_ERROR
);
1248 /* if we have no local db, then we can just return the reply to
1249 * the upper layer, otherwise we must save it and process it
1250 * when all replies ahve been gathered */
1251 if ( ! map_check_local_db(ac
->module
)) {
1252 ret
= map_return_entry(ac
, ares
);
1254 ret
= map_save_entry(ac
,ares
);
1257 if (ret
!= LDB_SUCCESS
) {
1259 return ldb_module_done(ac
->req
, NULL
, NULL
,
1260 LDB_ERR_OPERATIONS_ERROR
);
1264 case LDB_REPLY_DONE
:
1266 if ( ! map_check_local_db(ac
->module
)) {
1267 return ldb_module_done(ac
->req
, ares
->controls
,
1268 ares
->response
, LDB_SUCCESS
);
1271 /* reset the pointer to the start of the list */
1272 ac
->r_current
= ac
->r_list
;
1274 /* no entry just return */
1275 if (ac
->r_current
== NULL
) {
1276 ret
= ldb_module_done(ac
->req
, ares
->controls
,
1277 ares
->response
, LDB_SUCCESS
);
1282 ac
->remote_done_ares
= talloc_steal(ac
, ares
);
1284 ret
= map_search_local(ac
);
1285 if (ret
!= LDB_SUCCESS
) {
1286 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
1293 static int map_search_local(struct map_context
*ac
)
1295 struct ldb_request
*search_req
;
1297 if (ac
->r_current
== NULL
|| ac
->r_current
->remote
== NULL
) {
1298 return LDB_ERR_OPERATIONS_ERROR
;
1301 /* Prepare local search request */
1302 /* TODO: use GUIDs here instead? */
1303 search_req
= map_search_base_req(ac
,
1304 ac
->r_current
->remote
->message
->dn
,
1306 ac
, map_local_merge_callback
);
1307 if (search_req
== NULL
) {
1308 return LDB_ERR_OPERATIONS_ERROR
;
1311 return ldb_next_request(ac
->module
, search_req
);
1314 /* Merge the remote and local parts of a search result. */
1315 int map_local_merge_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
1317 struct ldb_context
*ldb
;
1318 struct map_context
*ac
;
1321 ac
= talloc_get_type(req
->context
, struct map_context
);
1322 ldb
= ldb_module_get_ctx(ac
->module
);
1325 return ldb_module_done(ac
->req
, NULL
, NULL
,
1326 LDB_ERR_OPERATIONS_ERROR
);
1328 if (ares
->error
!= LDB_SUCCESS
) {
1329 return ldb_module_done(ac
->req
, ares
->controls
,
1330 ares
->response
, ares
->error
);
1333 switch (ares
->type
) {
1334 case LDB_REPLY_ENTRY
:
1335 /* We have already found a local record */
1336 if (ac
->r_current
->local
) {
1338 ldb_set_errstring(ldb
, "ldb_map: Too many results!");
1339 return ldb_module_done(ac
->req
, NULL
, NULL
,
1340 LDB_ERR_OPERATIONS_ERROR
);
1343 /* Store local result */
1344 ac
->r_current
->local
= talloc_steal(ac
->r_current
, ares
);
1348 case LDB_REPLY_REFERRAL
:
1349 /* ignore referrals */
1353 case LDB_REPLY_DONE
:
1354 /* We don't need the local 'ares', but we will use the remote one from below */
1357 /* No local record found, map and send remote record */
1358 if (ac
->r_current
->local
!= NULL
) {
1359 /* Merge remote into local message */
1360 ret
= ldb_msg_merge_local(ac
->module
,
1361 ac
->r_current
->local
->message
,
1362 ac
->r_current
->remote
->message
);
1363 if (ret
== LDB_SUCCESS
) {
1364 ret
= map_return_entry(ac
, ac
->r_current
->local
);
1366 if (ret
!= LDB_SUCCESS
) {
1367 return ldb_module_done(ac
->req
, NULL
, NULL
,
1368 LDB_ERR_OPERATIONS_ERROR
);
1371 ret
= map_return_entry(ac
, ac
->r_current
->remote
);
1372 if (ret
!= LDB_SUCCESS
) {
1373 return ldb_module_done(ac
->req
,
1378 if (ac
->r_current
->next
!= NULL
) {
1379 ac
->r_current
= ac
->r_current
->next
;
1380 if (ac
->r_current
->remote
->type
== LDB_REPLY_ENTRY
) {
1381 ret
= map_search_local(ac
);
1382 if (ret
!= LDB_SUCCESS
) {
1383 return ldb_module_done(ac
->req
,
1390 /* ok we are done with all search, finally it is time to
1391 * finish operations for this module */
1392 return ldb_module_done(ac
->req
,
1393 ac
->remote_done_ares
->controls
,
1394 ac
->remote_done_ares
->response
,
1395 ac
->remote_done_ares
->error
);