drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / lib / ldb / ldb_map / ldb_map_outbound.c
blobe86e29a492dfe40e096545821c187e37a94efae6
1 /*
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
11 ** under the LGPL
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 "replace.h"
29 #include "system/filesys.h"
30 #include "system/time.h"
31 #include "ldb_map.h"
32 #include "ldb_map_private.h"
35 /* Mapping attributes
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);
42 const char **result;
43 unsigned int i, last;
45 if (attrs == NULL)
46 return NULL;
48 last = 0;
49 result = talloc_array(mem_ctx, const char *, 1);
50 if (result == NULL) {
51 goto failed;
53 result[0] = NULL;
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);
60 if (result == NULL) {
61 goto failed;
64 result[last] = talloc_strdup(result, attrs[i]);
65 result[last+1] = NULL;
66 last++;
70 return result;
72 failed:
73 talloc_free(result);
74 map_oom(module);
75 return 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);
83 const char **result;
84 const struct ldb_map_attribute *map;
85 const char *name=NULL;
86 unsigned int i, j, last;
87 int ret;
89 last = 0;
90 result = talloc_array(mem_ctx, const char *, 1);
91 if (result == NULL) {
92 goto failed;
94 result[0] = NULL;
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) {
102 goto failed;
104 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
105 if (ret != LDB_SUCCESS) {
106 goto failed;
109 attrs = new_attrs;
110 break;
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 */
118 name = attrs[i];
119 goto named;
122 /* Add remote names of mapped attrs */
123 map = map_attr_find_local(data, attrs[i]);
124 if (map == NULL) {
125 continue;
128 switch (map->type) {
129 case LDB_MAP_IGNORE:
130 continue;
132 case LDB_MAP_KEEP:
133 name = attrs[i];
134 goto named;
136 case LDB_MAP_RENAME:
137 case LDB_MAP_RENDROP:
138 case LDB_MAP_CONVERT:
139 name = map->u.rename.remote_name;
140 goto named;
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) {
147 goto failed;
150 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
151 result[last+1] = NULL;
152 last++;
154 continue;
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) {
160 goto failed;
163 result[last] = talloc_strdup(result, name);
164 result[last+1] = NULL;
165 last++;
168 return result;
170 failed:
171 talloc_free(result);
172 map_oom(module);
173 return 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);
183 return 0;
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;
193 unsigned j;
194 old = ldb_msg_find_element(msg, el->name);
196 /* no local result, add as new element */
197 if (old == NULL) {
198 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
199 return LDB_ERR_OPERATIONS_ERROR;
202 else {
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;
219 return 0;
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,
224 void *mem_ctx,
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;
232 unsigned int i;
234 el = talloc_zero(mem_ctx, struct ldb_message_element);
235 if (el == NULL) {
236 map_oom(module);
237 return NULL;
240 el->values = talloc_array(el, struct ldb_val, old->num_values);
241 if (el->values == NULL) {
242 talloc_free(el);
243 map_oom(module);
244 return 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;
255 break;
259 el->name = talloc_strdup(el, local_attr_name);
260 if (el->name == NULL) {
261 talloc_free(el);
262 map_oom(module);
263 return 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) {
270 talloc_free(el);
271 return NULL;
273 el->num_values++;
276 return el;
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) {
293 return LDB_SUCCESS;
296 map = map_attr_find_local(data, attr_name);
298 /* Unknown attribute in remote message:
299 * skip, attribute was probably auto-generated */
300 if (map == NULL) {
301 return LDB_SUCCESS;
304 switch (map->type) {
305 case LDB_MAP_IGNORE:
306 break;
307 case LDB_MAP_CONVERT:
308 remote_name = map->u.convert.remote_name;
309 break;
310 case LDB_MAP_KEEP:
311 remote_name = attr_name;
312 break;
313 case LDB_MAP_RENAME:
314 case LDB_MAP_RENDROP:
315 remote_name = map->u.rename.remote_name;
316 break;
317 case LDB_MAP_GENERATE:
318 break;
321 switch (map->type) {
322 case LDB_MAP_IGNORE:
323 return LDB_SUCCESS;
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",
330 attr_name);
331 return LDB_SUCCESS;
334 FALL_THROUGH;
335 case LDB_MAP_KEEP:
336 case LDB_MAP_RENAME:
337 case LDB_MAP_RENDROP:
338 old = ldb_msg_find_element(remote, remote_name);
339 if (old) {
340 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
341 } else {
342 return LDB_ERR_NO_SUCH_ATTRIBUTE;
344 break;
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",
351 attr_name);
352 return LDB_SUCCESS;
355 el = map->u.generate.generate_local(module, local, attr_name, remote);
356 if (!el) {
357 /* Generation failure is probably due to lack of source attributes */
358 return LDB_ERR_NO_SUCH_ATTRIBUTE;
360 break;
363 if (el == NULL) {
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;
377 unsigned int i;
378 int ret;
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]);
387 if (el == NULL) {
388 return LDB_ERR_OPERATIONS_ERROR;
391 ret = ldb_msg_replace(local, el);
392 if (ret) {
393 return ret;
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) {
403 continue;
404 } else if (ret) {
405 return ret;
406 } else {
407 continue;
411 return LDB_SUCCESS;
414 /* Mapping messages
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)
420 unsigned int i;
421 int ret;
423 for (i = 0; i < msg2->num_elements; i++) {
424 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
425 if (ret) {
426 return ret;
430 return LDB_SUCCESS;
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)
437 unsigned int i;
438 int ret;
439 const char * const *attrs = ac->all_attrs;
440 if (!attrs) {
441 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
442 if (ret) {
443 return ret;
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);
450 if (ret) {
451 return ret;
453 break;
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,
462 attrs[i]);
463 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
464 } else if (ret) {
465 return ret;
469 return LDB_SUCCESS;
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;
479 struct ldb_dn *dn;
480 int ret;
482 /* There is no result message, skip */
483 if (ares->type != LDB_REPLY_ENTRY) {
484 return 0;
487 /* Create a new result message */
488 msg = ldb_msg_new(ares);
489 if (msg == NULL) {
490 map_oom(ac->module);
491 return LDB_ERR_OPERATIONS_ERROR;
494 /* Merge remote message into new message */
495 ret = ldb_msg_merge_remote(ac, msg, ares->message);
496 if (ret) {
497 talloc_free(msg);
498 return ret;
501 /* Create corresponding local DN */
502 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
503 if (dn == NULL) {
504 talloc_free(msg);
505 return LDB_ERR_OPERATIONS_ERROR;
507 msg->dn = dn;
509 /* Store new message with new DN as the result */
510 talloc_free(ares->message);
511 ares->message = msg;
513 return 0;
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;
523 bool negate = false;
525 while (subtree) {
526 switch (subtree->operation) {
527 case LDB_OP_NOT:
528 negate = !negate;
529 subtree = subtree->u.isnot.child;
530 continue;
532 case LDB_OP_AND:
533 return !negate; /* if negate: False */
535 case LDB_OP_OR:
536 return negate; /* if negate: True */
538 default:
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;
551 unsigned int i;
552 int ret;
554 if (tree == NULL) {
555 return 0;
558 switch (tree->operation) {
559 case LDB_OP_OR:
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]);
564 if (ret) {
565 return ret;
568 return 0;
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);
579 talloc_free(*attrs);
580 *attrs = new_attrs;
581 return 0;
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;
591 int ret;
593 /* Prepare new tree */
594 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
595 if (*new == NULL) {
596 map_oom(module);
597 return LDB_ERR_OPERATIONS_ERROR;
600 /* Generate new subtree */
601 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
602 if (ret) {
603 talloc_free(*new);
604 return ret;
607 /* Prune tree without subtree */
608 if (child == NULL) {
609 talloc_free(*new);
610 *new = NULL;
611 return 0;
614 (*new)->u.isnot.child = child;
616 return ret;
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)
622 unsigned int i, j;
623 int ret=0;
625 /* Prepare new tree */
626 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
627 if (*new == NULL) {
628 map_oom(module);
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) {
636 map_oom(module);
637 talloc_free(*new);
638 return LDB_ERR_OPERATIONS_ERROR;
641 /* Generate new list of subtrees */
642 j = 0;
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]);
646 if (ret) {
647 talloc_free(*new);
648 return ret;
651 if (child) {
652 (*new)->u.list.elements[j] = child;
653 j++;
657 /* Prune tree without subtrees */
658 if (j == 0) {
659 talloc_free(*new);
660 *new = NULL;
661 return 0;
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);
668 return ret;
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));
676 if (*new == NULL) {
677 map_oom(module);
678 return LDB_ERR_OPERATIONS_ERROR;
681 return 0;
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);
689 if (tree == NULL) {
690 return 0;
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)) {
702 *new = NULL;
703 return 0;
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;
715 int ret;
717 /* Prepare new tree */
718 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
719 if (*new == NULL) {
720 map_oom(module);
721 return LDB_ERR_OPERATIONS_ERROR;
724 /* Generate new subtree */
725 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
726 if (ret) {
727 talloc_free(*new);
728 return ret;
731 /* Prune tree without subtree */
732 if (child == NULL) {
733 talloc_free(*new);
734 *new = NULL;
735 return 0;
738 (*new)->u.isnot.child = child;
740 return ret;
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)
746 unsigned int i, j;
747 int ret=0;
749 /* Prepare new tree */
750 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
751 if (*new == NULL) {
752 map_oom(module);
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) {
760 map_oom(module);
761 talloc_free(*new);
762 return LDB_ERR_OPERATIONS_ERROR;
765 /* Generate new list of subtrees */
766 j = 0;
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]);
770 if (ret) {
771 talloc_free(*new);
772 return ret;
775 if (child) {
776 (*new)->u.list.elements[j] = child;
777 j++;
781 /* Prune tree without subtrees */
782 if (j == 0) {
783 talloc_free(*new);
784 *new = NULL;
785 return 0;
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);
792 return ret;
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)
798 const char *attr;
800 /* Prepare new tree */
801 *new = talloc(mem_ctx, struct ldb_parse_tree);
802 if (*new == NULL) {
803 map_oom(module);
804 return LDB_ERR_OPERATIONS_ERROR;
806 **new = *tree;
808 if (map->type == LDB_MAP_KEEP) {
809 /* Nothing to do here */
810 return 0;
813 /* Store attribute and value in new tree */
814 switch (tree->operation) {
815 case LDB_OP_PRESENT:
816 attr = map_attr_map_local(*new, map, tree->u.present.attr);
817 (*new)->u.present.attr = attr;
818 break;
819 case LDB_OP_SUBSTRING:
821 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
822 (*new)->u.substring.attr = attr;
823 break;
825 case LDB_OP_EQUALITY:
826 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
827 (*new)->u.equality.attr = attr;
828 break;
829 case LDB_OP_LESS:
830 case LDB_OP_GREATER:
831 case LDB_OP_APPROX:
832 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
833 (*new)->u.comparison.attr = attr;
834 break;
835 case LDB_OP_EXTENDED:
836 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
837 (*new)->u.extended.attr = attr;
838 break;
839 default: /* unknown kind of simple subtree */
840 talloc_free(*new);
841 return LDB_ERR_OPERATIONS_ERROR;
844 if (attr == NULL) {
845 talloc_free(*new);
846 *new = NULL;
847 return 0;
850 if (map->type == LDB_MAP_RENAME || map->type == LDB_MAP_RENDROP) {
851 /* Nothing more to do here, the attribute has been renamed */
852 return 0;
855 /* Store attribute and value in new tree */
856 switch (tree->operation) {
857 case LDB_OP_PRESENT:
858 break;
859 case LDB_OP_SUBSTRING:
861 int i;
862 /* Map value */
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) {
867 talloc_free(*new);
868 *new = NULL;
869 return 0;
871 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
872 if (!(*new)->u.substring.chunks[i]) {
873 talloc_free(*new);
874 *new = NULL;
875 return 0;
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;
880 break;
882 case LDB_OP_EQUALITY:
883 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
884 break;
885 case LDB_OP_LESS:
886 case LDB_OP_GREATER:
887 case LDB_OP_APPROX:
888 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
889 break;
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);
893 break;
894 default: /* unknown kind of simple subtree */
895 talloc_free(*new);
896 return LDB_ERR_OPERATIONS_ERROR;
899 return 0;
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);
911 if (tree == NULL) {
912 return 0;
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)) {
924 *new = NULL;
925 return 0;
928 map = map_attr_find_local(data, tree->u.equality.attr);
929 if (map == NULL) {
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);
941 *new = NULL;
942 return 0;
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,
951 void *mem_ctx,
952 struct ldb_parse_tree **local_tree,
953 struct ldb_parse_tree **remote_tree,
954 const struct ldb_parse_tree *tree)
956 int ret;
958 *local_tree = NULL;
959 *remote_tree = NULL;
961 /* No original tree */
962 if (tree == NULL) {
963 return 0;
966 /* Generate local tree */
967 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
968 if (ret) {
969 return ret;
972 /* Generate remote tree */
973 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
974 if (ret) {
975 talloc_free(*local_tree);
976 return ret;
979 return 0;
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)
989 void *tmp_ctx;
990 const char **tree_attrs;
991 const char **remote_attrs;
992 const char **local_attrs;
993 int ret;
995 /* There is no tree, just partition the searched attributes */
996 if (tree == NULL) {
997 ret = map_attrs_partition(module, ac,
998 &local_attrs, &remote_attrs, search_attrs);
999 if (ret == 0) {
1000 ac->local_attrs = local_attrs;
1001 ac->remote_attrs = remote_attrs;
1002 ac->all_attrs = search_attrs;
1004 return ret;
1007 /* Create context for temporary memory */
1008 tmp_ctx = talloc_new(ac);
1009 if (tmp_ctx == NULL) {
1010 goto oom;
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);
1017 goto oom;
1019 tree_attrs[0] = NULL;
1021 /* Collect attributes from tree */
1022 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
1023 if (ret) {
1024 goto done;
1027 /* Merge attributes from search operation */
1028 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
1029 if (ret) {
1030 goto done;
1033 /* Split local from remote attributes */
1034 ret = map_attrs_partition(module, ac, &local_attrs,
1035 &remote_attrs, tree_attrs);
1037 if (ret == 0) {
1038 ac->local_attrs = local_attrs;
1039 ac->remote_attrs = remote_attrs;
1040 talloc_steal(ac, tree_attrs);
1041 ac->all_attrs = tree_attrs;
1043 done:
1044 /* Free temporary memory */
1045 talloc_free(tmp_ctx);
1046 return ret;
1048 oom:
1049 map_oom(module);
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);
1068 if (mr == NULL) {
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;
1075 } else {
1076 /* first entry */
1077 ac->r_list = mr;
1079 ac->r_current = mr;
1081 return LDB_SUCCESS;
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;
1090 unsigned int i;
1091 int ret;
1092 bool matched;
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,
1101 &matched);
1102 if (ret != LDB_SUCCESS) return ret;
1103 if (!matched) {
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));
1108 return LDB_SUCCESS;
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;
1116 i = 0;
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);
1123 } else {
1124 i++;
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;
1140 int ret;
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);
1166 if (ac == NULL) {
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) {
1174 attrs = wildcard;
1177 /* Split local from remote attrs */
1178 ret = map_attrs_collect_and_partition(module, ac,
1179 attrs, req->op.search.tree);
1180 if (ret) {
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);
1188 if (ret) {
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 */
1195 local_tree = NULL;
1196 remote_tree = NULL;
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,
1224 remote_tree,
1225 ac->remote_attrs,
1226 req->controls,
1227 ac, map_remote_search_callback,
1228 req);
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;
1242 int ret;
1244 ac = talloc_get_type(req->context, struct map_context);
1246 if (!ares) {
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 */
1259 talloc_free(ares);
1260 return LDB_SUCCESS;
1262 case LDB_REPLY_ENTRY:
1264 /* Map result record into a local message */
1265 ret = map_reply_remote(ac, ares);
1266 if (ret) {
1267 talloc_free(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);
1277 } else {
1278 ret = map_save_entry(ac,ares);
1281 if (ret != LDB_SUCCESS) {
1282 talloc_free(ares);
1283 return ldb_module_done(ac->req, NULL, NULL, ret);
1285 break;
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);
1301 talloc_free(ares);
1302 return ret;
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);
1313 return LDB_SUCCESS;
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,
1328 NULL, NULL,
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;
1342 int ret;
1344 ac = talloc_get_type(req->context, struct map_context);
1345 ldb = ldb_module_get_ctx(ac->module);
1347 if (!ares) {
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) {
1360 talloc_free(ares);
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);
1369 break;
1371 case LDB_REPLY_REFERRAL:
1372 /* ignore referrals */
1373 talloc_free(ares);
1374 break;
1376 case LDB_REPLY_DONE:
1377 /* We don't need the local 'ares', but we will use the remote one from below */
1378 talloc_free(ares);
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);
1393 } else {
1394 ret = map_return_entry(ac, ac->r_current->remote);
1395 if (ret != LDB_SUCCESS) {
1396 return ldb_module_done(ac->req,
1397 NULL, NULL, ret);
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,
1407 NULL, NULL, ret);
1409 break;
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);
1421 return LDB_SUCCESS;