Add LDB_MAP_RENDROP option
[Samba.git] / lib / ldb / ldb_map / ldb_map_outbound.c
blobb6357bdca332c0f6db0bf733bb018548828e180e
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;
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;
201 talloc_free(discard_const_p(char, old->name));
204 /* copy new element */
205 *old = *el;
207 /* and make sure we reference the contents */
208 if (!talloc_reference(msg->elements, el->name)) {
209 return LDB_ERR_OPERATIONS_ERROR;
211 if (!talloc_reference(msg->elements, el->values)) {
212 return LDB_ERR_OPERATIONS_ERROR;
215 return 0;
218 /* Map a message element back into the local partition. */
219 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
220 void *mem_ctx,
221 const struct ldb_map_attribute *map,
222 const char *attr_name,
223 const struct ldb_message_element *old)
225 const struct ldb_map_context *data = map_get_context(module);
226 const char *local_attr_name = attr_name;
227 struct ldb_message_element *el;
228 unsigned int i;
230 el = talloc_zero(mem_ctx, struct ldb_message_element);
231 if (el == NULL) {
232 map_oom(module);
233 return NULL;
236 el->values = talloc_array(el, struct ldb_val, old->num_values);
237 if (el->values == NULL) {
238 talloc_free(el);
239 map_oom(module);
240 return NULL;
243 for (i = 0; data->attribute_maps[i].local_name; i++) {
244 struct ldb_map_attribute *am = &data->attribute_maps[i];
245 if (((am->type == LDB_MAP_RENAME || am->type == LDB_MAP_RENDROP) &&
246 !strcmp(am->u.rename.remote_name, attr_name))
247 || (am->type == LDB_MAP_CONVERT &&
248 !strcmp(am->u.convert.remote_name, attr_name))) {
250 local_attr_name = am->local_name;
251 break;
255 el->name = talloc_strdup(el, local_attr_name);
256 if (el->name == NULL) {
257 talloc_free(el);
258 map_oom(module);
259 return NULL;
262 for (i = 0; i < old->num_values; i++) {
263 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
264 /* Conversions might fail, in which case bail */
265 if (!el->values[i].data) {
266 talloc_free(el);
267 return NULL;
269 el->num_values++;
272 return el;
275 /* Merge a remote message element into a local message. */
276 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
277 struct ldb_message *remote, const char *attr_name)
279 const struct ldb_map_context *data = map_get_context(module);
280 const struct ldb_map_attribute *map;
281 struct ldb_message_element *old, *el=NULL;
282 const char *remote_name = NULL;
283 struct ldb_context *ldb;
285 ldb = ldb_module_get_ctx(module);
287 /* We handle wildcards in ldb_msg_el_merge_wildcard */
288 if (ldb_attr_cmp(attr_name, "*") == 0) {
289 return LDB_SUCCESS;
292 map = map_attr_find_local(data, attr_name);
294 /* Unknown attribute in remote message:
295 * skip, attribute was probably auto-generated */
296 if (map == NULL) {
297 return LDB_SUCCESS;
300 switch (map->type) {
301 case LDB_MAP_IGNORE:
302 break;
303 case LDB_MAP_CONVERT:
304 remote_name = map->u.convert.remote_name;
305 break;
306 case LDB_MAP_KEEP:
307 remote_name = attr_name;
308 break;
309 case LDB_MAP_RENAME:
310 case LDB_MAP_RENDROP:
311 remote_name = map->u.rename.remote_name;
312 break;
313 case LDB_MAP_GENERATE:
314 break;
317 switch (map->type) {
318 case LDB_MAP_IGNORE:
319 return LDB_SUCCESS;
321 case LDB_MAP_CONVERT:
322 if (map->u.convert.convert_remote == NULL) {
323 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
324 "Skipping attribute '%s': "
325 "'convert_remote' not set",
326 attr_name);
327 return LDB_SUCCESS;
329 /* fall through */
330 case LDB_MAP_KEEP:
331 case LDB_MAP_RENAME:
332 case LDB_MAP_RENDROP:
333 old = ldb_msg_find_element(remote, remote_name);
334 if (old) {
335 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
336 } else {
337 return LDB_ERR_NO_SUCH_ATTRIBUTE;
339 break;
341 case LDB_MAP_GENERATE:
342 if (map->u.generate.generate_local == NULL) {
343 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
344 "Skipping attribute '%s': "
345 "'generate_local' not set",
346 attr_name);
347 return LDB_SUCCESS;
350 el = map->u.generate.generate_local(module, local, attr_name, remote);
351 if (!el) {
352 /* Generation failure is probably due to lack of source attributes */
353 return LDB_ERR_NO_SUCH_ATTRIBUTE;
355 break;
358 if (el == NULL) {
359 return LDB_ERR_NO_SUCH_ATTRIBUTE;
362 return ldb_msg_replace(local, el);
365 /* Handle wildcard parts of merging a remote message element into a local message. */
366 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
367 struct ldb_message *remote)
369 const struct ldb_map_context *data = map_get_context(module);
370 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
371 struct ldb_message_element *el=NULL;
372 unsigned int i;
373 int ret;
375 /* Perhaps we have a mapping for "*" */
376 if (map && map->type == LDB_MAP_KEEP) {
377 /* We copy everything over, and hope that anything with a
378 more specific rule is overwritten */
379 for (i = 0; i < remote->num_elements; i++) {
380 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
381 &remote->elements[i]);
382 if (el == NULL) {
383 return LDB_ERR_OPERATIONS_ERROR;
386 ret = ldb_msg_replace(local, el);
387 if (ret) {
388 return ret;
393 /* Now walk the list of possible mappings, and apply each */
394 for (i = 0; data->attribute_maps[i].local_name; i++) {
395 ret = ldb_msg_el_merge(module, local, remote,
396 data->attribute_maps[i].local_name);
397 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
398 continue;
399 } else if (ret) {
400 return ret;
401 } else {
402 continue;
406 return LDB_SUCCESS;
409 /* Mapping messages
410 * ================ */
412 /* Merge two local messages into a single one. */
413 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
415 unsigned int i;
416 int ret;
418 for (i = 0; i < msg2->num_elements; i++) {
419 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
420 if (ret) {
421 return ret;
425 return LDB_SUCCESS;
428 /* Merge a local and a remote message into a single local one. */
429 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
430 struct ldb_message *remote)
432 unsigned int i;
433 int ret;
434 const char * const *attrs = ac->all_attrs;
435 if (!attrs) {
436 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
437 if (ret) {
438 return ret;
442 for (i = 0; attrs && attrs[i]; i++) {
443 if (ldb_attr_cmp(attrs[i], "*") == 0) {
444 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
445 if (ret) {
446 return ret;
448 break;
452 /* Try to map each attribute back;
453 * Add to local message is possible,
454 * Overwrite old local attribute if necessary */
455 for (i = 0; attrs && attrs[i]; i++) {
456 ret = ldb_msg_el_merge(ac->module, local, remote,
457 attrs[i]);
458 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
459 } else if (ret) {
460 return ret;
464 return LDB_SUCCESS;
467 /* Mapping search results
468 * ====================== */
470 /* Map a search result back into the local partition. */
471 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
473 struct ldb_message *msg;
474 struct ldb_dn *dn;
475 int ret;
477 /* There is no result message, skip */
478 if (ares->type != LDB_REPLY_ENTRY) {
479 return 0;
482 /* Create a new result message */
483 msg = ldb_msg_new(ares);
484 if (msg == NULL) {
485 map_oom(ac->module);
486 return LDB_ERR_OPERATIONS_ERROR;
489 /* Merge remote message into new message */
490 ret = ldb_msg_merge_remote(ac, msg, ares->message);
491 if (ret) {
492 talloc_free(msg);
493 return ret;
496 /* Create corresponding local DN */
497 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
498 if (dn == NULL) {
499 talloc_free(msg);
500 return LDB_ERR_OPERATIONS_ERROR;
502 msg->dn = dn;
504 /* Store new message with new DN as the result */
505 talloc_free(ares->message);
506 ares->message = msg;
508 return 0;
511 /* Mapping parse trees
512 * =================== */
514 /* Check whether a parse tree can safely be split in two. */
515 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
517 const struct ldb_parse_tree *subtree = tree;
518 bool negate = false;
520 while (subtree) {
521 switch (subtree->operation) {
522 case LDB_OP_NOT:
523 negate = !negate;
524 subtree = subtree->u.isnot.child;
525 continue;
527 case LDB_OP_AND:
528 return !negate; /* if negate: False */
530 case LDB_OP_OR:
531 return negate; /* if negate: True */
533 default:
534 return true; /* simple parse tree */
538 return true; /* no parse tree */
541 /* Collect a list of attributes required to match a given parse tree. */
542 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
544 const char **new_attrs;
545 unsigned int i;
546 int ret;
548 if (tree == NULL) {
549 return 0;
552 switch (tree->operation) {
553 case LDB_OP_OR:
554 case LDB_OP_AND: /* attributes stored in list of subtrees */
555 for (i = 0; i < tree->u.list.num_elements; i++) {
556 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
557 attrs, tree->u.list.elements[i]);
558 if (ret) {
559 return ret;
562 return 0;
564 case LDB_OP_NOT: /* attributes stored in single subtree */
565 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
567 default: /* single attribute in tree */
568 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
569 talloc_free(*attrs);
570 *attrs = new_attrs;
571 return 0;
575 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
577 /* Select a negated subtree that queries attributes in the local partition */
578 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)
580 struct ldb_parse_tree *child;
581 int ret;
583 /* Prepare new tree */
584 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
585 if (*new == NULL) {
586 map_oom(module);
587 return LDB_ERR_OPERATIONS_ERROR;
590 /* Generate new subtree */
591 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
592 if (ret) {
593 talloc_free(*new);
594 return ret;
597 /* Prune tree without subtree */
598 if (child == NULL) {
599 talloc_free(*new);
600 *new = NULL;
601 return 0;
604 (*new)->u.isnot.child = child;
606 return ret;
609 /* Select a list of subtrees that query attributes in the local partition */
610 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)
612 unsigned int i, j;
613 int ret=0;
615 /* Prepare new tree */
616 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
617 if (*new == NULL) {
618 map_oom(module);
619 return LDB_ERR_OPERATIONS_ERROR;
622 /* Prepare list of subtrees */
623 (*new)->u.list.num_elements = 0;
624 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
625 if ((*new)->u.list.elements == NULL) {
626 map_oom(module);
627 talloc_free(*new);
628 return LDB_ERR_OPERATIONS_ERROR;
631 /* Generate new list of subtrees */
632 j = 0;
633 for (i = 0; i < tree->u.list.num_elements; i++) {
634 struct ldb_parse_tree *child;
635 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
636 if (ret) {
637 talloc_free(*new);
638 return ret;
641 if (child) {
642 (*new)->u.list.elements[j] = child;
643 j++;
647 /* Prune tree without subtrees */
648 if (j == 0) {
649 talloc_free(*new);
650 *new = NULL;
651 return 0;
654 /* Fix subtree list size */
655 (*new)->u.list.num_elements = j;
656 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
658 return ret;
661 /* Select a simple subtree that queries attributes in the local partition */
662 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)
664 /* Prepare new tree */
665 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
666 if (*new == NULL) {
667 map_oom(module);
668 return LDB_ERR_OPERATIONS_ERROR;
671 return 0;
674 /* Select subtrees that query attributes in the local partition */
675 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
677 const struct ldb_map_context *data = map_get_context(module);
679 if (tree == NULL) {
680 return 0;
683 if (tree->operation == LDB_OP_NOT) {
684 return map_subtree_select_local_not(module, mem_ctx, new, tree);
687 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
688 return map_subtree_select_local_list(module, mem_ctx, new, tree);
691 if (map_attr_check_remote(data, tree->u.equality.attr)) {
692 *new = NULL;
693 return 0;
696 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
699 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
701 /* Collect a negated subtree that queries attributes in the remote partition */
702 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)
704 struct ldb_parse_tree *child;
705 int ret;
707 /* Prepare new tree */
708 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
709 if (*new == NULL) {
710 map_oom(module);
711 return LDB_ERR_OPERATIONS_ERROR;
714 /* Generate new subtree */
715 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
716 if (ret) {
717 talloc_free(*new);
718 return ret;
721 /* Prune tree without subtree */
722 if (child == NULL) {
723 talloc_free(*new);
724 *new = NULL;
725 return 0;
728 (*new)->u.isnot.child = child;
730 return ret;
733 /* Collect a list of subtrees that query attributes in the remote partition */
734 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)
736 unsigned int i, j;
737 int ret=0;
739 /* Prepare new tree */
740 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
741 if (*new == NULL) {
742 map_oom(module);
743 return LDB_ERR_OPERATIONS_ERROR;
746 /* Prepare list of subtrees */
747 (*new)->u.list.num_elements = 0;
748 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
749 if ((*new)->u.list.elements == NULL) {
750 map_oom(module);
751 talloc_free(*new);
752 return LDB_ERR_OPERATIONS_ERROR;
755 /* Generate new list of subtrees */
756 j = 0;
757 for (i = 0; i < tree->u.list.num_elements; i++) {
758 struct ldb_parse_tree *child;
759 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
760 if (ret) {
761 talloc_free(*new);
762 return ret;
765 if (child) {
766 (*new)->u.list.elements[j] = child;
767 j++;
771 /* Prune tree without subtrees */
772 if (j == 0) {
773 talloc_free(*new);
774 *new = NULL;
775 return 0;
778 /* Fix subtree list size */
779 (*new)->u.list.num_elements = j;
780 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
782 return ret;
785 /* Collect a simple subtree that queries attributes in the remote partition */
786 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)
788 const char *attr;
790 /* Prepare new tree */
791 *new = talloc(mem_ctx, struct ldb_parse_tree);
792 if (*new == NULL) {
793 map_oom(module);
794 return LDB_ERR_OPERATIONS_ERROR;
796 **new = *tree;
798 if (map->type == LDB_MAP_KEEP) {
799 /* Nothing to do here */
800 return 0;
803 /* Store attribute and value in new tree */
804 switch (tree->operation) {
805 case LDB_OP_PRESENT:
806 attr = map_attr_map_local(*new, map, tree->u.present.attr);
807 (*new)->u.present.attr = attr;
808 break;
809 case LDB_OP_SUBSTRING:
811 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
812 (*new)->u.substring.attr = attr;
813 break;
815 case LDB_OP_EQUALITY:
816 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
817 (*new)->u.equality.attr = attr;
818 break;
819 case LDB_OP_LESS:
820 case LDB_OP_GREATER:
821 case LDB_OP_APPROX:
822 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
823 (*new)->u.comparison.attr = attr;
824 break;
825 case LDB_OP_EXTENDED:
826 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
827 (*new)->u.extended.attr = attr;
828 break;
829 default: /* unknown kind of simple subtree */
830 talloc_free(*new);
831 return LDB_ERR_OPERATIONS_ERROR;
834 if (attr == NULL) {
835 talloc_free(*new);
836 *new = NULL;
837 return 0;
840 if (map->type == LDB_MAP_RENAME || map->type == LDB_MAP_RENDROP) {
841 /* Nothing more to do here, the attribute has been renamed */
842 return 0;
845 /* Store attribute and value in new tree */
846 switch (tree->operation) {
847 case LDB_OP_PRESENT:
848 break;
849 case LDB_OP_SUBSTRING:
851 int i;
852 /* Map value */
853 (*new)->u.substring.chunks = NULL;
854 for (i=0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) {
855 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
856 if (!(*new)->u.substring.chunks) {
857 talloc_free(*new);
858 *new = NULL;
859 return 0;
861 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
862 if (!(*new)->u.substring.chunks[i]) {
863 talloc_free(*new);
864 *new = NULL;
865 return 0;
867 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
868 (*new)->u.substring.chunks[i+1] = NULL;
870 break;
872 case LDB_OP_EQUALITY:
873 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
874 break;
875 case LDB_OP_LESS:
876 case LDB_OP_GREATER:
877 case LDB_OP_APPROX:
878 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
879 break;
880 case LDB_OP_EXTENDED:
881 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
882 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
883 break;
884 default: /* unknown kind of simple subtree */
885 talloc_free(*new);
886 return LDB_ERR_OPERATIONS_ERROR;
889 return 0;
892 /* Collect subtrees that query attributes in the remote partition */
893 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
895 const struct ldb_map_context *data = map_get_context(module);
896 const struct ldb_map_attribute *map;
897 struct ldb_context *ldb;
899 ldb = ldb_module_get_ctx(module);
901 if (tree == NULL) {
902 return 0;
905 if (tree->operation == LDB_OP_NOT) {
906 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
909 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
910 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
913 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
914 *new = NULL;
915 return 0;
918 map = map_attr_find_local(data, tree->u.equality.attr);
919 if (map->convert_operator) {
920 return map->convert_operator(module, mem_ctx, new, tree);
923 if (map->type == LDB_MAP_GENERATE) {
924 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
925 "Skipping attribute '%s': "
926 "'convert_operator' not set",
927 tree->u.equality.attr);
928 *new = NULL;
929 return 0;
932 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
935 /* Split subtrees that query attributes in the local partition from
936 * those that query the remote partition. */
937 static int ldb_parse_tree_partition(struct ldb_module *module,
938 void *mem_ctx,
939 struct ldb_parse_tree **local_tree,
940 struct ldb_parse_tree **remote_tree,
941 const struct ldb_parse_tree *tree)
943 int ret;
945 *local_tree = NULL;
946 *remote_tree = NULL;
948 /* No original tree */
949 if (tree == NULL) {
950 return 0;
953 /* Generate local tree */
954 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
955 if (ret) {
956 return ret;
959 /* Generate remote tree */
960 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
961 if (ret) {
962 talloc_free(*local_tree);
963 return ret;
966 return 0;
969 /* Collect a list of attributes required either explicitly from a
970 * given list or implicitly from a given parse tree; split the
971 * collected list into local and remote parts. */
972 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
973 const char * const *search_attrs,
974 const struct ldb_parse_tree *tree)
976 void *tmp_ctx;
977 const char **tree_attrs;
978 const char **remote_attrs;
979 const char **local_attrs;
980 int ret;
982 /* There is no tree, just partition the searched attributes */
983 if (tree == NULL) {
984 ret = map_attrs_partition(module, ac,
985 &local_attrs, &remote_attrs, search_attrs);
986 if (ret == 0) {
987 ac->local_attrs = local_attrs;
988 ac->remote_attrs = remote_attrs;
989 ac->all_attrs = search_attrs;
991 return ret;
994 /* Create context for temporary memory */
995 tmp_ctx = talloc_new(ac);
996 if (tmp_ctx == NULL) {
997 goto oom;
1000 /* Prepare list of attributes from tree */
1001 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
1002 if (tree_attrs == NULL) {
1003 talloc_free(tmp_ctx);
1004 goto oom;
1006 tree_attrs[0] = NULL;
1008 /* Collect attributes from tree */
1009 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
1010 if (ret) {
1011 goto done;
1014 /* Merge attributes from search operation */
1015 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
1016 if (ret) {
1017 goto done;
1020 /* Split local from remote attributes */
1021 ret = map_attrs_partition(module, ac, &local_attrs,
1022 &remote_attrs, tree_attrs);
1024 if (ret == 0) {
1025 ac->local_attrs = local_attrs;
1026 ac->remote_attrs = remote_attrs;
1027 talloc_steal(ac, tree_attrs);
1028 ac->all_attrs = tree_attrs;
1030 done:
1031 /* Free temporary memory */
1032 talloc_free(tmp_ctx);
1033 return ret;
1035 oom:
1036 map_oom(module);
1037 return LDB_ERR_OPERATIONS_ERROR;
1041 /* Outbound requests: search
1042 * ========================= */
1044 static int map_remote_search_callback(struct ldb_request *req,
1045 struct ldb_reply *ares);
1046 static int map_local_merge_callback(struct ldb_request *req,
1047 struct ldb_reply *ares);
1048 static int map_search_local(struct map_context *ac);
1050 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1052 struct map_reply *mr;
1054 mr = talloc_zero(ac, struct map_reply);
1055 if (mr == NULL) {
1056 map_oom(ac->module);
1057 return LDB_ERR_OPERATIONS_ERROR;
1059 mr->remote = talloc_steal(mr, ares);
1060 if (ac->r_current) {
1061 ac->r_current->next = mr;
1062 } else {
1063 /* first entry */
1064 ac->r_list = mr;
1066 ac->r_current = mr;
1068 return LDB_SUCCESS;
1071 /* Pass a merged search result up the callback chain. */
1072 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1074 struct ldb_message_element *el;
1075 const char * const *attrs;
1076 struct ldb_context *ldb;
1077 unsigned int i;
1078 int ret;
1079 bool matched;
1081 ldb = ldb_module_get_ctx(ac->module);
1083 /* Merged result doesn't match original query, skip */
1084 ret = ldb_match_msg_error(ldb, ares->message,
1085 ac->req->op.search.tree,
1086 ac->req->op.search.base,
1087 ac->req->op.search.scope,
1088 &matched);
1089 if (ret != LDB_SUCCESS) return ret;
1090 if (!matched) {
1091 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1092 "Skipping record '%s': "
1093 "doesn't match original search",
1094 ldb_dn_get_linearized(ares->message->dn));
1095 return LDB_SUCCESS;
1098 /* Limit result to requested attrs */
1099 if (ac->req->op.search.attrs &&
1100 (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1102 attrs = ac->req->op.search.attrs;
1103 i = 0;
1105 while (i < ares->message->num_elements) {
1107 el = &ares->message->elements[i];
1108 if ( ! ldb_attr_in_list(attrs, el->name)) {
1109 ldb_msg_remove_element(ares->message, el);
1110 } else {
1111 i++;
1116 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1119 /* Search a record. */
1120 int ldb_map_search(struct ldb_module *module, struct ldb_request *req)
1122 struct ldb_parse_tree *remote_tree;
1123 struct ldb_parse_tree *local_tree;
1124 struct ldb_request *remote_req;
1125 struct ldb_context *ldb;
1126 struct map_context *ac;
1127 int ret;
1129 const char *wildcard[] = { "*", NULL };
1130 const char * const *attrs;
1132 ldb = ldb_module_get_ctx(module);
1134 /* if we're not yet initialized, go to the next module */
1135 if (!ldb_module_get_private(module))
1136 return ldb_next_request(module, req);
1138 /* Do not manipulate our control entries */
1139 if (ldb_dn_is_special(req->op.search.base)) {
1140 return ldb_next_request(module, req);
1143 /* No mapping requested, skip to next module */
1144 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1145 return ldb_next_request(module, req);
1148 /* TODO: How can we be sure about which partition we are
1149 * targetting when there is no search base? */
1151 /* Prepare context and handle */
1152 ac = map_init_context(module, req);
1153 if (ac == NULL) {
1154 return LDB_ERR_OPERATIONS_ERROR;
1157 /* It is easier to deal with the two different ways of
1158 * expressing the wildcard in the same codepath */
1159 attrs = req->op.search.attrs;
1160 if (attrs == NULL) {
1161 attrs = wildcard;
1164 /* Split local from remote attrs */
1165 ret = map_attrs_collect_and_partition(module, ac,
1166 attrs, req->op.search.tree);
1167 if (ret) {
1168 return LDB_ERR_OPERATIONS_ERROR;
1171 /* Split local from remote tree */
1172 ret = ldb_parse_tree_partition(module, ac,
1173 &local_tree, &remote_tree,
1174 req->op.search.tree);
1175 if (ret) {
1176 return LDB_ERR_OPERATIONS_ERROR;
1179 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1180 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1181 /* The query can't safely be split, enumerate the remote partition */
1182 local_tree = NULL;
1183 remote_tree = NULL;
1186 if (local_tree == NULL) {
1187 /* Construct default local parse tree */
1188 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1189 if (local_tree == NULL) {
1190 map_oom(ac->module);
1191 return LDB_ERR_OPERATIONS_ERROR;
1194 local_tree->operation = LDB_OP_PRESENT;
1195 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1197 if (remote_tree == NULL) {
1198 /* Construct default remote parse tree */
1199 remote_tree = ldb_parse_tree(ac, NULL);
1200 if (remote_tree == NULL) {
1201 return LDB_ERR_OPERATIONS_ERROR;
1205 ac->local_tree = local_tree;
1207 /* Prepare the remote operation */
1208 ret = ldb_build_search_req_ex(&remote_req, ldb, ac,
1209 req->op.search.base,
1210 req->op.search.scope,
1211 remote_tree,
1212 ac->remote_attrs,
1213 req->controls,
1214 ac, map_remote_search_callback,
1215 req);
1216 LDB_REQ_SET_LOCATION(remote_req);
1217 if (ret != LDB_SUCCESS) {
1218 return LDB_ERR_OPERATIONS_ERROR;
1221 return ldb_next_remote_request(module, remote_req);
1224 /* Now, search the local part of a remote search result. */
1225 static int map_remote_search_callback(struct ldb_request *req,
1226 struct ldb_reply *ares)
1228 struct map_context *ac;
1229 int ret;
1231 ac = talloc_get_type(req->context, struct map_context);
1233 if (!ares) {
1234 return ldb_module_done(ac->req, NULL, NULL,
1235 LDB_ERR_OPERATIONS_ERROR);
1237 if (ares->error != LDB_SUCCESS) {
1238 return ldb_module_done(ac->req, ares->controls,
1239 ares->response, ares->error);
1242 switch (ares->type) {
1243 case LDB_REPLY_REFERRAL:
1245 /* ignore referrals */
1246 talloc_free(ares);
1247 return LDB_SUCCESS;
1249 case LDB_REPLY_ENTRY:
1251 /* Map result record into a local message */
1252 ret = map_reply_remote(ac, ares);
1253 if (ret) {
1254 talloc_free(ares);
1255 return ldb_module_done(ac->req, NULL, NULL,
1256 LDB_ERR_OPERATIONS_ERROR);
1259 /* if we have no local db, then we can just return the reply to
1260 * the upper layer, otherwise we must save it and process it
1261 * when all replies ahve been gathered */
1262 if ( ! map_check_local_db(ac->module)) {
1263 ret = map_return_entry(ac, ares);
1264 } else {
1265 ret = map_save_entry(ac,ares);
1268 if (ret != LDB_SUCCESS) {
1269 talloc_free(ares);
1270 return ldb_module_done(ac->req, NULL, NULL, ret);
1272 break;
1274 case LDB_REPLY_DONE:
1276 if ( ! map_check_local_db(ac->module)) {
1277 return ldb_module_done(ac->req, ares->controls,
1278 ares->response, LDB_SUCCESS);
1281 /* reset the pointer to the start of the list */
1282 ac->r_current = ac->r_list;
1284 /* no entry just return */
1285 if (ac->r_current == NULL) {
1286 ret = ldb_module_done(ac->req, ares->controls,
1287 ares->response, LDB_SUCCESS);
1288 talloc_free(ares);
1289 return ret;
1292 ac->remote_done_ares = talloc_steal(ac, ares);
1294 ret = map_search_local(ac);
1295 if (ret != LDB_SUCCESS) {
1296 return ldb_module_done(ac->req, NULL, NULL, ret);
1300 return LDB_SUCCESS;
1303 static int map_search_local(struct map_context *ac)
1305 struct ldb_request *search_req;
1307 if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1308 return LDB_ERR_OPERATIONS_ERROR;
1311 /* Prepare local search request */
1312 /* TODO: use GUIDs here instead? */
1313 search_req = map_search_base_req(ac,
1314 ac->r_current->remote->message->dn,
1315 NULL, NULL,
1316 ac, map_local_merge_callback);
1317 if (search_req == NULL) {
1318 return LDB_ERR_OPERATIONS_ERROR;
1321 return ldb_next_request(ac->module, search_req);
1324 /* Merge the remote and local parts of a search result. */
1325 int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares)
1327 struct ldb_context *ldb;
1328 struct map_context *ac;
1329 int ret;
1331 ac = talloc_get_type(req->context, struct map_context);
1332 ldb = ldb_module_get_ctx(ac->module);
1334 if (!ares) {
1335 return ldb_module_done(ac->req, NULL, NULL,
1336 LDB_ERR_OPERATIONS_ERROR);
1338 if (ares->error != LDB_SUCCESS) {
1339 return ldb_module_done(ac->req, ares->controls,
1340 ares->response, ares->error);
1343 switch (ares->type) {
1344 case LDB_REPLY_ENTRY:
1345 /* We have already found a local record */
1346 if (ac->r_current->local) {
1347 talloc_free(ares);
1348 ldb_set_errstring(ldb, "ldb_map: Too many results!");
1349 return ldb_module_done(ac->req, NULL, NULL,
1350 LDB_ERR_OPERATIONS_ERROR);
1353 /* Store local result */
1354 ac->r_current->local = talloc_steal(ac->r_current, ares);
1356 break;
1358 case LDB_REPLY_REFERRAL:
1359 /* ignore referrals */
1360 talloc_free(ares);
1361 break;
1363 case LDB_REPLY_DONE:
1364 /* We don't need the local 'ares', but we will use the remote one from below */
1365 talloc_free(ares);
1367 /* No local record found, map and send remote record */
1368 if (ac->r_current->local != NULL) {
1369 /* Merge remote into local message */
1370 ret = ldb_msg_merge_local(ac->module,
1371 ac->r_current->local->message,
1372 ac->r_current->remote->message);
1373 if (ret == LDB_SUCCESS) {
1374 ret = map_return_entry(ac, ac->r_current->local);
1376 if (ret != LDB_SUCCESS) {
1377 return ldb_module_done(ac->req, NULL, NULL,
1378 LDB_ERR_OPERATIONS_ERROR);
1380 } else {
1381 ret = map_return_entry(ac, ac->r_current->remote);
1382 if (ret != LDB_SUCCESS) {
1383 return ldb_module_done(ac->req,
1384 NULL, NULL, ret);
1388 if (ac->r_current->next != NULL) {
1389 ac->r_current = ac->r_current->next;
1390 if (ac->r_current->remote->type == LDB_REPLY_ENTRY) {
1391 ret = map_search_local(ac);
1392 if (ret != LDB_SUCCESS) {
1393 return ldb_module_done(ac->req,
1394 NULL, NULL, ret);
1396 break;
1400 /* ok we are done with all search, finally it is time to
1401 * finish operations for this module */
1402 return ldb_module_done(ac->req,
1403 ac->remote_done_ares->controls,
1404 ac->remote_done_ares->response,
1405 ac->remote_done_ares->error);
1408 return LDB_SUCCESS;