2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
7 Copyright (C) Simo Sorce <idra@samba.org> 2008
9 ** NOTE! The following LGPL license applies to the ldb
10 ** library. This does NOT imply that all of Samba is released
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 3 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 #include "system/filesys.h"
30 #include "system/time.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
;
86 unsigned int i
, j
, last
;
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
]);
137 case LDB_MAP_RENDROP
:
138 case LDB_MAP_CONVERT
:
139 name
= map
->u
.rename
.remote_name
;
142 case LDB_MAP_GENERATE
:
143 /* Add all remote names of "generate" attrs */
144 for (j
= 0; map
->u
.generate
.remote_names
[j
]; j
++) {
145 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
146 if (result
== NULL
) {
150 result
[last
] = talloc_strdup(result
, map
->u
.generate
.remote_names
[j
]);
151 result
[last
+1] = NULL
;
157 named
: /* We found a single remote name, add that */
158 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
159 if (result
== NULL
) {
163 result
[last
] = talloc_strdup(result
, name
);
164 result
[last
+1] = NULL
;
176 /* Split attributes that stay in the local partition from those that
177 * are mapped into the remote partition. */
178 static int map_attrs_partition(struct ldb_module
*module
, void *mem_ctx
, const char ***local_attrs
, const char ***remote_attrs
, const char * const *attrs
)
180 *local_attrs
= map_attrs_select_local(module
, mem_ctx
, attrs
);
181 *remote_attrs
= map_attrs_collect_remote(module
, mem_ctx
, attrs
);
186 /* Mapping message elements
187 * ======================== */
189 /* Add an element to a message, overwriting any old identically named elements. */
190 static int ldb_msg_replace(struct ldb_message
*msg
, const struct ldb_message_element
*el
)
192 struct ldb_message_element
*old
;
194 old
= ldb_msg_find_element(msg
, el
->name
);
196 /* no local result, add as new element */
198 if (ldb_msg_add_empty(msg
, el
->name
, 0, &old
) != 0) {
199 return LDB_ERR_OPERATIONS_ERROR
;
203 talloc_free(old
->values
);
206 old
->values
= talloc_array(msg
->elements
, struct ldb_val
, el
->num_values
);
207 old
->num_values
= el
->num_values
;
208 if (old
->values
== NULL
) {
209 return LDB_ERR_OPERATIONS_ERROR
;
211 /* copy the values into the element */
212 for (j
=0;j
<el
->num_values
;j
++) {
213 old
->values
[j
] = ldb_val_dup(old
->values
, &el
->values
[j
]);
214 if (old
->values
[j
].data
== NULL
&& el
->values
[j
].length
!= 0) {
215 return LDB_ERR_OPERATIONS_ERROR
;
222 /* Map a message element back into the local partition. */
223 static struct ldb_message_element
*ldb_msg_el_map_remote(struct ldb_module
*module
,
225 const struct ldb_map_attribute
*map
,
226 const char *attr_name
,
227 const struct ldb_message_element
*old
)
229 const struct ldb_map_context
*data
= map_get_context(module
);
230 const char *local_attr_name
= attr_name
;
231 struct ldb_message_element
*el
;
234 el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
240 el
->values
= talloc_array(el
, struct ldb_val
, old
->num_values
);
241 if (el
->values
== NULL
) {
247 for (i
= 0; data
->attribute_maps
[i
].local_name
; i
++) {
248 struct ldb_map_attribute
*am
= &data
->attribute_maps
[i
];
249 if (((am
->type
== LDB_MAP_RENAME
|| am
->type
== LDB_MAP_RENDROP
) &&
250 !strcmp(am
->u
.rename
.remote_name
, attr_name
))
251 || (am
->type
== LDB_MAP_CONVERT
&&
252 !strcmp(am
->u
.convert
.remote_name
, attr_name
))) {
254 local_attr_name
= am
->local_name
;
259 el
->name
= talloc_strdup(el
, local_attr_name
);
260 if (el
->name
== NULL
) {
266 for (i
= 0; i
< old
->num_values
; i
++) {
267 el
->values
[i
] = ldb_val_map_remote(module
, el
->values
, map
, &old
->values
[i
]);
268 /* Conversions might fail, in which case bail */
269 if (!el
->values
[i
].data
) {
279 /* Merge a remote message element into a local message. */
280 static int ldb_msg_el_merge(struct ldb_module
*module
, struct ldb_message
*local
,
281 struct ldb_message
*remote
, const char *attr_name
)
283 const struct ldb_map_context
*data
= map_get_context(module
);
284 const struct ldb_map_attribute
*map
;
285 struct ldb_message_element
*old
, *el
=NULL
;
286 const char *remote_name
= NULL
;
287 struct ldb_context
*ldb
;
289 ldb
= ldb_module_get_ctx(module
);
291 /* We handle wildcards in ldb_msg_el_merge_wildcard */
292 if (ldb_attr_cmp(attr_name
, "*") == 0) {
296 map
= map_attr_find_local(data
, attr_name
);
298 /* Unknown attribute in remote message:
299 * skip, attribute was probably auto-generated */
307 case LDB_MAP_CONVERT
:
308 remote_name
= map
->u
.convert
.remote_name
;
311 remote_name
= attr_name
;
314 case LDB_MAP_RENDROP
:
315 remote_name
= map
->u
.rename
.remote_name
;
317 case LDB_MAP_GENERATE
:
325 case LDB_MAP_CONVERT
:
326 if (map
->u
.convert
.convert_remote
== NULL
) {
327 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
328 "Skipping attribute '%s': "
329 "'convert_remote' not set",
337 case LDB_MAP_RENDROP
:
338 old
= ldb_msg_find_element(remote
, remote_name
);
340 el
= ldb_msg_el_map_remote(module
, local
, map
, attr_name
, old
);
342 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
346 case LDB_MAP_GENERATE
:
347 if (map
->u
.generate
.generate_local
== NULL
) {
348 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
349 "Skipping attribute '%s': "
350 "'generate_local' not set",
355 el
= map
->u
.generate
.generate_local(module
, local
, attr_name
, remote
);
357 /* Generation failure is probably due to lack of source attributes */
358 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
364 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
367 return ldb_msg_replace(local
, el
);
370 /* Handle wildcard parts of merging a remote message element into a local message. */
371 static int ldb_msg_el_merge_wildcard(struct ldb_module
*module
, struct ldb_message
*local
,
372 struct ldb_message
*remote
)
374 const struct ldb_map_context
*data
= map_get_context(module
);
375 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, "*");
376 struct ldb_message_element
*el
=NULL
;
380 /* Perhaps we have a mapping for "*" */
381 if (map
&& map
->type
== LDB_MAP_KEEP
) {
382 /* We copy everything over, and hope that anything with a
383 more specific rule is overwritten */
384 for (i
= 0; i
< remote
->num_elements
; i
++) {
385 el
= ldb_msg_el_map_remote(module
, local
, map
, remote
->elements
[i
].name
,
386 &remote
->elements
[i
]);
388 return LDB_ERR_OPERATIONS_ERROR
;
391 ret
= ldb_msg_replace(local
, el
);
398 /* Now walk the list of possible mappings, and apply each */
399 for (i
= 0; data
->attribute_maps
[i
].local_name
; i
++) {
400 ret
= ldb_msg_el_merge(module
, local
, remote
,
401 data
->attribute_maps
[i
].local_name
);
402 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
415 * ================ */
417 /* Merge two local messages into a single one. */
418 static int ldb_msg_merge_local(struct ldb_module
*module
, struct ldb_message
*msg1
, struct ldb_message
*msg2
)
423 for (i
= 0; i
< msg2
->num_elements
; i
++) {
424 ret
= ldb_msg_replace(msg1
, &msg2
->elements
[i
]);
433 /* Merge a local and a remote message into a single local one. */
434 static int ldb_msg_merge_remote(struct map_context
*ac
, struct ldb_message
*local
,
435 struct ldb_message
*remote
)
439 const char * const *attrs
= ac
->all_attrs
;
441 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
447 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
448 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
449 ret
= ldb_msg_el_merge_wildcard(ac
->module
, local
, remote
);
457 /* Try to map each attribute back;
458 * Add to local message is possible,
459 * Overwrite old local attribute if necessary */
460 for (i
= 0; attrs
&& attrs
[i
]; i
++) {
461 ret
= ldb_msg_el_merge(ac
->module
, local
, remote
,
463 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
472 /* Mapping search results
473 * ====================== */
475 /* Map a search result back into the local partition. */
476 static int map_reply_remote(struct map_context
*ac
, struct ldb_reply
*ares
)
478 struct ldb_message
*msg
;
482 /* There is no result message, skip */
483 if (ares
->type
!= LDB_REPLY_ENTRY
) {
487 /* Create a new result message */
488 msg
= ldb_msg_new(ares
);
491 return LDB_ERR_OPERATIONS_ERROR
;
494 /* Merge remote message into new message */
495 ret
= ldb_msg_merge_remote(ac
, msg
, ares
->message
);
501 /* Create corresponding local DN */
502 dn
= ldb_dn_map_rebase_remote(ac
->module
, msg
, ares
->message
->dn
);
505 return LDB_ERR_OPERATIONS_ERROR
;
509 /* Store new message with new DN as the result */
510 talloc_free(ares
->message
);
516 /* Mapping parse trees
517 * =================== */
519 /* Check whether a parse tree can safely be split in two. */
520 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree
*tree
)
522 const struct ldb_parse_tree
*subtree
= tree
;
526 switch (subtree
->operation
) {
529 subtree
= subtree
->u
.isnot
.child
;
533 return !negate
; /* if negate: False */
536 return negate
; /* if negate: True */
539 return true; /* simple parse tree */
543 return true; /* no parse tree */
546 /* Collect a list of attributes required to match a given parse tree. */
547 static int ldb_parse_tree_collect_attrs(struct ldb_module
*module
, void *mem_ctx
, const char ***attrs
, const struct ldb_parse_tree
*tree
)
549 const char *attr
= NULL
;
550 const char **new_attrs
;
558 switch (tree
->operation
) {
560 case LDB_OP_AND
: /* attributes stored in list of subtrees */
561 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
562 ret
= ldb_parse_tree_collect_attrs(module
, mem_ctx
,
563 attrs
, tree
->u
.list
.elements
[i
]);
570 case LDB_OP_NOT
: /* attributes stored in single subtree */
571 return ldb_parse_tree_collect_attrs(module
, mem_ctx
, attrs
, tree
->u
.isnot
.child
);
573 default: /* single attribute in tree */
574 attr
= ldb_parse_tree_get_attr(tree
);
575 new_attrs
= ldb_attr_list_copy_add(mem_ctx
, *attrs
, attr
);
576 if (new_attrs
== NULL
) {
577 return ldb_module_oom(module
);
585 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
587 /* Select a negated subtree that queries attributes in the local partition */
588 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
)
590 struct ldb_parse_tree
*child
;
593 /* Prepare new tree */
594 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
597 return LDB_ERR_OPERATIONS_ERROR
;
600 /* Generate new subtree */
601 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.isnot
.child
);
607 /* Prune tree without subtree */
614 (*new)->u
.isnot
.child
= child
;
619 /* Select a list of subtrees that query attributes in the local partition */
620 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
)
625 /* Prepare new tree */
626 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
629 return LDB_ERR_OPERATIONS_ERROR
;
632 /* Prepare list of subtrees */
633 (*new)->u
.list
.num_elements
= 0;
634 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
635 if ((*new)->u
.list
.elements
== NULL
) {
638 return LDB_ERR_OPERATIONS_ERROR
;
641 /* Generate new list of subtrees */
643 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
644 struct ldb_parse_tree
*child
= NULL
;
645 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
652 (*new)->u
.list
.elements
[j
] = child
;
657 /* Prune tree without subtrees */
664 /* Fix subtree list size */
665 (*new)->u
.list
.num_elements
= j
;
666 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
671 /* Select a simple subtree that queries attributes in the local partition */
672 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
)
674 /* Prepare new tree */
675 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
678 return LDB_ERR_OPERATIONS_ERROR
;
684 /* Select subtrees that query attributes in the local partition */
685 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
687 const struct ldb_map_context
*data
= map_get_context(module
);
693 if (tree
->operation
== LDB_OP_NOT
) {
694 return map_subtree_select_local_not(module
, mem_ctx
, new, tree
);
697 if (tree
->operation
== LDB_OP_AND
|| tree
->operation
== LDB_OP_OR
) {
698 return map_subtree_select_local_list(module
, mem_ctx
, new, tree
);
701 if (map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
706 return map_subtree_select_local_simple(module
, mem_ctx
, new, tree
);
709 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
711 /* Collect a negated subtree that queries attributes in the remote partition */
712 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
)
714 struct ldb_parse_tree
*child
;
717 /* Prepare new tree */
718 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
721 return LDB_ERR_OPERATIONS_ERROR
;
724 /* Generate new subtree */
725 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.isnot
.child
);
731 /* Prune tree without subtree */
738 (*new)->u
.isnot
.child
= child
;
743 /* Collect a list of subtrees that query attributes in the remote partition */
744 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
)
749 /* Prepare new tree */
750 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
753 return LDB_ERR_OPERATIONS_ERROR
;
756 /* Prepare list of subtrees */
757 (*new)->u
.list
.num_elements
= 0;
758 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
759 if ((*new)->u
.list
.elements
== NULL
) {
762 return LDB_ERR_OPERATIONS_ERROR
;
765 /* Generate new list of subtrees */
767 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
768 struct ldb_parse_tree
*child
;
769 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
776 (*new)->u
.list
.elements
[j
] = child
;
781 /* Prune tree without subtrees */
788 /* Fix subtree list size */
789 (*new)->u
.list
.num_elements
= j
;
790 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
795 /* Collect a simple subtree that queries attributes in the remote partition */
796 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
)
800 /* Prepare new tree */
801 *new = talloc(mem_ctx
, struct ldb_parse_tree
);
804 return LDB_ERR_OPERATIONS_ERROR
;
808 if (map
->type
== LDB_MAP_KEEP
) {
809 /* Nothing to do here */
813 /* Store attribute and value in new tree */
814 switch (tree
->operation
) {
816 attr
= map_attr_map_local(*new, map
, tree
->u
.present
.attr
);
817 (*new)->u
.present
.attr
= attr
;
819 case LDB_OP_SUBSTRING
:
821 attr
= map_attr_map_local(*new, map
, tree
->u
.substring
.attr
);
822 (*new)->u
.substring
.attr
= attr
;
825 case LDB_OP_EQUALITY
:
826 attr
= map_attr_map_local(*new, map
, tree
->u
.equality
.attr
);
827 (*new)->u
.equality
.attr
= attr
;
832 attr
= map_attr_map_local(*new, map
, tree
->u
.comparison
.attr
);
833 (*new)->u
.comparison
.attr
= attr
;
835 case LDB_OP_EXTENDED
:
836 attr
= map_attr_map_local(*new, map
, tree
->u
.extended
.attr
);
837 (*new)->u
.extended
.attr
= attr
;
839 default: /* unknown kind of simple subtree */
841 return LDB_ERR_OPERATIONS_ERROR
;
850 if (map
->type
== LDB_MAP_RENAME
|| map
->type
== LDB_MAP_RENDROP
) {
851 /* Nothing more to do here, the attribute has been renamed */
855 /* Store attribute and value in new tree */
856 switch (tree
->operation
) {
859 case LDB_OP_SUBSTRING
:
863 (*new)->u
.substring
.chunks
= NULL
;
864 for (i
=0; tree
->u
.substring
.chunks
&& tree
->u
.substring
.chunks
[i
]; i
++) {
865 (*new)->u
.substring
.chunks
= talloc_realloc(*new, (*new)->u
.substring
.chunks
, struct ldb_val
*, i
+2);
866 if (!(*new)->u
.substring
.chunks
) {
871 (*new)->u
.substring
.chunks
[i
] = talloc(*new, struct ldb_val
);
872 if (!(*new)->u
.substring
.chunks
[i
]) {
877 *(*new)->u
.substring
.chunks
[i
] = ldb_val_map_local(module
, *new, map
, tree
->u
.substring
.chunks
[i
]);
878 (*new)->u
.substring
.chunks
[i
+1] = NULL
;
882 case LDB_OP_EQUALITY
:
883 (*new)->u
.equality
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.equality
.value
);
888 (*new)->u
.comparison
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.comparison
.value
);
890 case LDB_OP_EXTENDED
:
891 (*new)->u
.extended
.value
= ldb_val_map_local(module
, *new, map
, &tree
->u
.extended
.value
);
892 (*new)->u
.extended
.rule_id
= talloc_strdup(*new, tree
->u
.extended
.rule_id
);
894 default: /* unknown kind of simple subtree */
896 return LDB_ERR_OPERATIONS_ERROR
;
902 /* Collect subtrees that query attributes in the remote partition */
903 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
905 const struct ldb_map_context
*data
= map_get_context(module
);
906 const struct ldb_map_attribute
*map
;
907 struct ldb_context
*ldb
;
909 ldb
= ldb_module_get_ctx(module
);
915 if (tree
->operation
== LDB_OP_NOT
) {
916 return map_subtree_collect_remote_not(module
, mem_ctx
, new, tree
);
919 if ((tree
->operation
== LDB_OP_AND
) || (tree
->operation
== LDB_OP_OR
)) {
920 return map_subtree_collect_remote_list(module
, mem_ctx
, new, tree
);
923 if (!map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
928 map
= map_attr_find_local(data
, tree
->u
.equality
.attr
);
930 return LDB_ERR_OPERATIONS_ERROR
;
932 if (map
->convert_operator
) {
933 return map
->convert_operator(module
, mem_ctx
, new, tree
);
936 if (map
->type
== LDB_MAP_GENERATE
) {
937 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
938 "Skipping attribute '%s': "
939 "'convert_operator' not set",
940 tree
->u
.equality
.attr
);
945 return map_subtree_collect_remote_simple(module
, mem_ctx
, new, tree
, map
);
948 /* Split subtrees that query attributes in the local partition from
949 * those that query the remote partition. */
950 static int ldb_parse_tree_partition(struct ldb_module
*module
,
952 struct ldb_parse_tree
**local_tree
,
953 struct ldb_parse_tree
**remote_tree
,
954 const struct ldb_parse_tree
*tree
)
961 /* No original tree */
966 /* Generate local tree */
967 ret
= map_subtree_select_local(module
, mem_ctx
, local_tree
, tree
);
972 /* Generate remote tree */
973 ret
= map_subtree_collect_remote(module
, mem_ctx
, remote_tree
, tree
);
975 talloc_free(*local_tree
);
982 /* Collect a list of attributes required either explicitly from a
983 * given list or implicitly from a given parse tree; split the
984 * collected list into local and remote parts. */
985 static int map_attrs_collect_and_partition(struct ldb_module
*module
, struct map_context
*ac
,
986 const char * const *search_attrs
,
987 const struct ldb_parse_tree
*tree
)
990 const char **tree_attrs
;
991 const char **remote_attrs
;
992 const char **local_attrs
;
995 /* There is no tree, just partition the searched attributes */
997 ret
= map_attrs_partition(module
, ac
,
998 &local_attrs
, &remote_attrs
, search_attrs
);
1000 ac
->local_attrs
= local_attrs
;
1001 ac
->remote_attrs
= remote_attrs
;
1002 ac
->all_attrs
= search_attrs
;
1007 /* Create context for temporary memory */
1008 tmp_ctx
= talloc_new(ac
);
1009 if (tmp_ctx
== NULL
) {
1013 /* Prepare list of attributes from tree */
1014 tree_attrs
= talloc_array(tmp_ctx
, const char *, 1);
1015 if (tree_attrs
== NULL
) {
1016 talloc_free(tmp_ctx
);
1019 tree_attrs
[0] = NULL
;
1021 /* Collect attributes from tree */
1022 ret
= ldb_parse_tree_collect_attrs(module
, tmp_ctx
, &tree_attrs
, tree
);
1027 /* Merge attributes from search operation */
1028 ret
= map_attrs_merge(module
, tmp_ctx
, &tree_attrs
, search_attrs
);
1033 /* Split local from remote attributes */
1034 ret
= map_attrs_partition(module
, ac
, &local_attrs
,
1035 &remote_attrs
, tree_attrs
);
1038 ac
->local_attrs
= local_attrs
;
1039 ac
->remote_attrs
= remote_attrs
;
1040 talloc_steal(ac
, tree_attrs
);
1041 ac
->all_attrs
= tree_attrs
;
1044 /* Free temporary memory */
1045 talloc_free(tmp_ctx
);
1050 return LDB_ERR_OPERATIONS_ERROR
;
1054 /* Outbound requests: search
1055 * ========================= */
1057 static int map_remote_search_callback(struct ldb_request
*req
,
1058 struct ldb_reply
*ares
);
1059 static int map_local_merge_callback(struct ldb_request
*req
,
1060 struct ldb_reply
*ares
);
1061 static int map_search_local(struct map_context
*ac
);
1063 static int map_save_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1065 struct map_reply
*mr
;
1067 mr
= talloc_zero(ac
, struct map_reply
);
1069 map_oom(ac
->module
);
1070 return LDB_ERR_OPERATIONS_ERROR
;
1072 mr
->remote
= talloc_steal(mr
, ares
);
1073 if (ac
->r_current
) {
1074 ac
->r_current
->next
= mr
;
1084 /* Pass a merged search result up the callback chain. */
1085 int map_return_entry(struct map_context
*ac
, struct ldb_reply
*ares
)
1087 struct ldb_message_element
*el
;
1088 const char * const *attrs
;
1089 struct ldb_context
*ldb
;
1094 ldb
= ldb_module_get_ctx(ac
->module
);
1096 /* Merged result doesn't match original query, skip */
1097 ret
= ldb_match_msg_error(ldb
, ares
->message
,
1098 ac
->req
->op
.search
.tree
,
1099 ac
->req
->op
.search
.base
,
1100 ac
->req
->op
.search
.scope
,
1102 if (ret
!= LDB_SUCCESS
) return ret
;
1104 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "ldb_map: "
1105 "Skipping record '%s': "
1106 "doesn't match original search",
1107 ldb_dn_get_linearized(ares
->message
->dn
));
1111 /* Limit result to requested attrs */
1112 if (ac
->req
->op
.search
.attrs
&&
1113 (! ldb_attr_in_list(ac
->req
->op
.search
.attrs
, "*"))) {
1115 attrs
= ac
->req
->op
.search
.attrs
;
1118 while (i
< ares
->message
->num_elements
) {
1120 el
= &ares
->message
->elements
[i
];
1121 if ( ! ldb_attr_in_list(attrs
, el
->name
)) {
1122 ldb_msg_remove_element(ares
->message
, el
);
1129 return ldb_module_send_entry(ac
->req
, ares
->message
, ares
->controls
);
1132 /* Search a record. */
1133 int ldb_map_search(struct ldb_module
*module
, struct ldb_request
*req
)
1135 struct ldb_parse_tree
*remote_tree
;
1136 struct ldb_parse_tree
*local_tree
;
1137 struct ldb_request
*remote_req
;
1138 struct ldb_context
*ldb
;
1139 struct map_context
*ac
;
1142 const char *wildcard
[] = { "*", NULL
};
1143 const char * const *attrs
;
1145 ldb
= ldb_module_get_ctx(module
);
1147 /* if we're not yet initialized, go to the next module */
1148 if (!ldb_module_get_private(module
))
1149 return ldb_next_request(module
, req
);
1151 /* Do not manipulate our control entries */
1152 if (ldb_dn_is_special(req
->op
.search
.base
)) {
1153 return ldb_next_request(module
, req
);
1156 /* No mapping requested, skip to next module */
1157 if ((req
->op
.search
.base
) && (!ldb_dn_check_local(module
, req
->op
.search
.base
))) {
1158 return ldb_next_request(module
, req
);
1161 /* TODO: How can we be sure about which partition we are
1162 * targeting when there is no search base? */
1164 /* Prepare context and handle */
1165 ac
= map_init_context(module
, req
);
1167 return LDB_ERR_OPERATIONS_ERROR
;
1170 /* It is easier to deal with the two different ways of
1171 * expressing the wildcard in the same codepath */
1172 attrs
= req
->op
.search
.attrs
;
1173 if (attrs
== NULL
) {
1177 /* Split local from remote attrs */
1178 ret
= map_attrs_collect_and_partition(module
, ac
,
1179 attrs
, req
->op
.search
.tree
);
1181 return LDB_ERR_OPERATIONS_ERROR
;
1184 /* Split local from remote tree */
1185 ret
= ldb_parse_tree_partition(module
, ac
,
1186 &local_tree
, &remote_tree
,
1187 req
->op
.search
.tree
);
1189 return LDB_ERR_OPERATIONS_ERROR
;
1192 if (((local_tree
!= NULL
) && (remote_tree
!= NULL
)) &&
1193 (!ldb_parse_tree_check_splittable(req
->op
.search
.tree
))) {
1194 /* The query can't safely be split, enumerate the remote partition */
1199 if (local_tree
== NULL
) {
1200 /* Construct default local parse tree */
1201 local_tree
= talloc_zero(ac
, struct ldb_parse_tree
);
1202 if (local_tree
== NULL
) {
1203 map_oom(ac
->module
);
1204 return LDB_ERR_OPERATIONS_ERROR
;
1207 local_tree
->operation
= LDB_OP_PRESENT
;
1208 local_tree
->u
.present
.attr
= talloc_strdup(local_tree
, IS_MAPPED
);
1210 if (remote_tree
== NULL
) {
1211 /* Construct default remote parse tree */
1212 remote_tree
= ldb_parse_tree(ac
, NULL
);
1213 if (remote_tree
== NULL
) {
1214 return LDB_ERR_OPERATIONS_ERROR
;
1218 ac
->local_tree
= local_tree
;
1220 /* Prepare the remote operation */
1221 ret
= ldb_build_search_req_ex(&remote_req
, ldb
, ac
,
1222 req
->op
.search
.base
,
1223 req
->op
.search
.scope
,
1227 ac
, map_remote_search_callback
,
1229 LDB_REQ_SET_LOCATION(remote_req
);
1230 if (ret
!= LDB_SUCCESS
) {
1231 return LDB_ERR_OPERATIONS_ERROR
;
1234 return ldb_next_remote_request(module
, remote_req
);
1237 /* Now, search the local part of a remote search result. */
1238 static int map_remote_search_callback(struct ldb_request
*req
,
1239 struct ldb_reply
*ares
)
1241 struct map_context
*ac
;
1244 ac
= talloc_get_type(req
->context
, struct map_context
);
1247 return ldb_module_done(ac
->req
, NULL
, NULL
,
1248 LDB_ERR_OPERATIONS_ERROR
);
1250 if (ares
->error
!= LDB_SUCCESS
) {
1251 return ldb_module_done(ac
->req
, ares
->controls
,
1252 ares
->response
, ares
->error
);
1255 switch (ares
->type
) {
1256 case LDB_REPLY_REFERRAL
:
1258 /* ignore referrals */
1262 case LDB_REPLY_ENTRY
:
1264 /* Map result record into a local message */
1265 ret
= map_reply_remote(ac
, ares
);
1268 return ldb_module_done(ac
->req
, NULL
, NULL
,
1269 LDB_ERR_OPERATIONS_ERROR
);
1272 /* if we have no local db, then we can just return the reply to
1273 * the upper layer, otherwise we must save it and process it
1274 * when all replies have been gathered */
1275 if ( ! map_check_local_db(ac
->module
)) {
1276 ret
= map_return_entry(ac
, ares
);
1278 ret
= map_save_entry(ac
,ares
);
1281 if (ret
!= LDB_SUCCESS
) {
1283 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
1287 case LDB_REPLY_DONE
:
1289 if ( ! map_check_local_db(ac
->module
)) {
1290 return ldb_module_done(ac
->req
, ares
->controls
,
1291 ares
->response
, LDB_SUCCESS
);
1294 /* reset the pointer to the start of the list */
1295 ac
->r_current
= ac
->r_list
;
1297 /* no entry just return */
1298 if (ac
->r_current
== NULL
) {
1299 ret
= ldb_module_done(ac
->req
, ares
->controls
,
1300 ares
->response
, LDB_SUCCESS
);
1305 ac
->remote_done_ares
= talloc_steal(ac
, ares
);
1307 ret
= map_search_local(ac
);
1308 if (ret
!= LDB_SUCCESS
) {
1309 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
1316 static int map_search_local(struct map_context
*ac
)
1318 struct ldb_request
*search_req
;
1320 if (ac
->r_current
== NULL
|| ac
->r_current
->remote
== NULL
) {
1321 return LDB_ERR_OPERATIONS_ERROR
;
1324 /* Prepare local search request */
1325 /* TODO: use GUIDs here instead? */
1326 search_req
= map_search_base_req(ac
,
1327 ac
->r_current
->remote
->message
->dn
,
1329 ac
, map_local_merge_callback
);
1330 if (search_req
== NULL
) {
1331 return LDB_ERR_OPERATIONS_ERROR
;
1334 return ldb_next_request(ac
->module
, search_req
);
1337 /* Merge the remote and local parts of a search result. */
1338 int map_local_merge_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
1340 struct ldb_context
*ldb
;
1341 struct map_context
*ac
;
1344 ac
= talloc_get_type(req
->context
, struct map_context
);
1345 ldb
= ldb_module_get_ctx(ac
->module
);
1348 return ldb_module_done(ac
->req
, NULL
, NULL
,
1349 LDB_ERR_OPERATIONS_ERROR
);
1351 if (ares
->error
!= LDB_SUCCESS
) {
1352 return ldb_module_done(ac
->req
, ares
->controls
,
1353 ares
->response
, ares
->error
);
1356 switch (ares
->type
) {
1357 case LDB_REPLY_ENTRY
:
1358 /* We have already found a local record */
1359 if (ac
->r_current
->local
) {
1361 ldb_set_errstring(ldb
, "ldb_map: Too many results!");
1362 return ldb_module_done(ac
->req
, NULL
, NULL
,
1363 LDB_ERR_OPERATIONS_ERROR
);
1366 /* Store local result */
1367 ac
->r_current
->local
= talloc_steal(ac
->r_current
, ares
);
1371 case LDB_REPLY_REFERRAL
:
1372 /* ignore referrals */
1376 case LDB_REPLY_DONE
:
1377 /* We don't need the local 'ares', but we will use the remote one from below */
1380 /* No local record found, map and send remote record */
1381 if (ac
->r_current
->local
!= NULL
) {
1382 /* Merge remote into local message */
1383 ret
= ldb_msg_merge_local(ac
->module
,
1384 ac
->r_current
->local
->message
,
1385 ac
->r_current
->remote
->message
);
1386 if (ret
== LDB_SUCCESS
) {
1387 ret
= map_return_entry(ac
, ac
->r_current
->local
);
1389 if (ret
!= LDB_SUCCESS
) {
1390 return ldb_module_done(ac
->req
, NULL
, NULL
,
1391 LDB_ERR_OPERATIONS_ERROR
);
1394 ret
= map_return_entry(ac
, ac
->r_current
->remote
);
1395 if (ret
!= LDB_SUCCESS
) {
1396 return ldb_module_done(ac
->req
,
1401 if (ac
->r_current
->next
!= NULL
) {
1402 ac
->r_current
= ac
->r_current
->next
;
1403 if (ac
->r_current
->remote
->type
== LDB_REPLY_ENTRY
) {
1404 ret
= map_search_local(ac
);
1405 if (ret
!= LDB_SUCCESS
) {
1406 return ldb_module_done(ac
->req
,
1413 /* ok we are done with all search, finally it is time to
1414 * finish operations for this module */
1415 return ldb_module_done(ac
->req
,
1416 ac
->remote_done_ares
->controls
,
1417 ac
->remote_done_ares
->response
,
1418 ac
->remote_done_ares
->error
);