s3:net_idmap_delete do not lock two records at the same time
[Samba/gebeck_regimport.git] / lib / ldb / ldb_map / ldb_map_outbound.c
blob2c517a625dcf4447e412442ed56bdcd49d390eea
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_CONVERT:
138 name = map->u.rename.remote_name;
139 goto named;
141 case LDB_MAP_GENERATE:
142 /* Add all remote names of "generate" attrs */
143 for (j = 0; map->u.generate.remote_names[j]; j++) {
144 result = talloc_realloc(mem_ctx, result, const char *, last+2);
145 if (result == NULL) {
146 goto failed;
149 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
150 result[last+1] = NULL;
151 last++;
153 continue;
156 named: /* We found a single remote name, add that */
157 result = talloc_realloc(mem_ctx, result, const char *, last+2);
158 if (result == NULL) {
159 goto failed;
162 result[last] = talloc_strdup(result, name);
163 result[last+1] = NULL;
164 last++;
167 return result;
169 failed:
170 talloc_free(result);
171 map_oom(module);
172 return NULL;
175 /* Split attributes that stay in the local partition from those that
176 * are mapped into the remote partition. */
177 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
179 *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
180 *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
182 return 0;
185 /* Mapping message elements
186 * ======================== */
188 /* Add an element to a message, overwriting any old identically named elements. */
189 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
191 struct ldb_message_element *old;
193 old = ldb_msg_find_element(msg, el->name);
195 /* no local result, add as new element */
196 if (old == NULL) {
197 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
198 return -1;
200 talloc_free(discard_const_p(char, old->name));
203 /* copy new element */
204 *old = *el;
206 /* and make sure we reference the contents */
207 if (!talloc_reference(msg->elements, el->name)) {
208 return -1;
210 if (!talloc_reference(msg->elements, el->values)) {
211 return -1;
214 return 0;
217 /* Map a message element back into the local partition. */
218 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module,
219 void *mem_ctx,
220 const struct ldb_map_attribute *map,
221 const char *attr_name,
222 const struct ldb_message_element *old)
224 const struct ldb_map_context *data = map_get_context(module);
225 const char *local_attr_name = attr_name;
226 struct ldb_message_element *el;
227 unsigned int i;
229 el = talloc_zero(mem_ctx, struct ldb_message_element);
230 if (el == NULL) {
231 map_oom(module);
232 return NULL;
235 el->values = talloc_array(el, struct ldb_val, old->num_values);
236 if (el->values == NULL) {
237 talloc_free(el);
238 map_oom(module);
239 return NULL;
242 for (i = 0; data->attribute_maps[i].local_name; i++) {
243 struct ldb_map_attribute *am = &data->attribute_maps[i];
244 if ((am->type == LDB_MAP_RENAME &&
245 !strcmp(am->u.rename.remote_name, attr_name))
246 || (am->type == LDB_MAP_CONVERT &&
247 !strcmp(am->u.convert.remote_name, attr_name))) {
249 local_attr_name = am->local_name;
250 break;
254 el->name = talloc_strdup(el, local_attr_name);
255 if (el->name == NULL) {
256 talloc_free(el);
257 map_oom(module);
258 return NULL;
261 for (i = 0; i < old->num_values; i++) {
262 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
263 /* Conversions might fail, in which case bail */
264 if (!el->values[i].data) {
265 talloc_free(el);
266 return NULL;
268 el->num_values++;
271 return el;
274 /* Merge a remote message element into a local message. */
275 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local,
276 struct ldb_message *remote, const char *attr_name)
278 const struct ldb_map_context *data = map_get_context(module);
279 const struct ldb_map_attribute *map;
280 struct ldb_message_element *old, *el=NULL;
281 const char *remote_name = NULL;
282 struct ldb_context *ldb;
284 ldb = ldb_module_get_ctx(module);
286 /* We handle wildcards in ldb_msg_el_merge_wildcard */
287 if (ldb_attr_cmp(attr_name, "*") == 0) {
288 return LDB_SUCCESS;
291 map = map_attr_find_local(data, attr_name);
293 /* Unknown attribute in remote message:
294 * skip, attribute was probably auto-generated */
295 if (map == NULL) {
296 return LDB_SUCCESS;
299 switch (map->type) {
300 case LDB_MAP_IGNORE:
301 break;
302 case LDB_MAP_CONVERT:
303 remote_name = map->u.convert.remote_name;
304 break;
305 case LDB_MAP_KEEP:
306 remote_name = attr_name;
307 break;
308 case LDB_MAP_RENAME:
309 remote_name = map->u.rename.remote_name;
310 break;
311 case LDB_MAP_GENERATE:
312 break;
315 switch (map->type) {
316 case LDB_MAP_IGNORE:
317 return LDB_SUCCESS;
319 case LDB_MAP_CONVERT:
320 if (map->u.convert.convert_remote == NULL) {
321 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
322 "Skipping attribute '%s': "
323 "'convert_remote' not set",
324 attr_name);
325 return LDB_SUCCESS;
327 /* fall through */
328 case LDB_MAP_KEEP:
329 case LDB_MAP_RENAME:
330 old = ldb_msg_find_element(remote, remote_name);
331 if (old) {
332 el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
333 } else {
334 return LDB_ERR_NO_SUCH_ATTRIBUTE;
336 break;
338 case LDB_MAP_GENERATE:
339 if (map->u.generate.generate_local == NULL) {
340 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
341 "Skipping attribute '%s': "
342 "'generate_local' not set",
343 attr_name);
344 return LDB_SUCCESS;
347 el = map->u.generate.generate_local(module, local, attr_name, remote);
348 if (!el) {
349 /* Generation failure is probably due to lack of source attributes */
350 return LDB_ERR_NO_SUCH_ATTRIBUTE;
352 break;
355 if (el == NULL) {
356 return LDB_ERR_NO_SUCH_ATTRIBUTE;
359 return ldb_msg_replace(local, el);
362 /* Handle wildcard parts of merging a remote message element into a local message. */
363 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local,
364 struct ldb_message *remote)
366 const struct ldb_map_context *data = map_get_context(module);
367 const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
368 struct ldb_message_element *el=NULL;
369 unsigned int i;
370 int ret;
372 /* Perhaps we have a mapping for "*" */
373 if (map && map->type == LDB_MAP_KEEP) {
374 /* We copy everything over, and hope that anything with a
375 more specific rule is overwritten */
376 for (i = 0; i < remote->num_elements; i++) {
377 el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
378 &remote->elements[i]);
379 if (el == NULL) {
380 return LDB_ERR_OPERATIONS_ERROR;
383 ret = ldb_msg_replace(local, el);
384 if (ret) {
385 return ret;
390 /* Now walk the list of possible mappings, and apply each */
391 for (i = 0; data->attribute_maps[i].local_name; i++) {
392 ret = ldb_msg_el_merge(module, local, remote,
393 data->attribute_maps[i].local_name);
394 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
395 continue;
396 } else if (ret) {
397 return ret;
398 } else {
399 continue;
403 return LDB_SUCCESS;
406 /* Mapping messages
407 * ================ */
409 /* Merge two local messages into a single one. */
410 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
412 unsigned int i;
413 int ret;
415 for (i = 0; i < msg2->num_elements; i++) {
416 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
417 if (ret) {
418 return ret;
422 return LDB_SUCCESS;
425 /* Merge a local and a remote message into a single local one. */
426 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local,
427 struct ldb_message *remote)
429 unsigned int i;
430 int ret;
431 const char * const *attrs = ac->all_attrs;
432 if (!attrs) {
433 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
434 if (ret) {
435 return ret;
439 for (i = 0; attrs && attrs[i]; i++) {
440 if (ldb_attr_cmp(attrs[i], "*") == 0) {
441 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
442 if (ret) {
443 return ret;
445 break;
449 /* Try to map each attribute back;
450 * Add to local message is possible,
451 * Overwrite old local attribute if necessary */
452 for (i = 0; attrs && attrs[i]; i++) {
453 ret = ldb_msg_el_merge(ac->module, local, remote,
454 attrs[i]);
455 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
456 } else if (ret) {
457 return ret;
461 return LDB_SUCCESS;
464 /* Mapping search results
465 * ====================== */
467 /* Map a search result back into the local partition. */
468 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
470 struct ldb_message *msg;
471 struct ldb_dn *dn;
472 int ret;
474 /* There is no result message, skip */
475 if (ares->type != LDB_REPLY_ENTRY) {
476 return 0;
479 /* Create a new result message */
480 msg = ldb_msg_new(ares);
481 if (msg == NULL) {
482 map_oom(ac->module);
483 return -1;
486 /* Merge remote message into new message */
487 ret = ldb_msg_merge_remote(ac, msg, ares->message);
488 if (ret) {
489 talloc_free(msg);
490 return ret;
493 /* Create corresponding local DN */
494 dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
495 if (dn == NULL) {
496 talloc_free(msg);
497 return -1;
499 msg->dn = dn;
501 /* Store new message with new DN as the result */
502 talloc_free(ares->message);
503 ares->message = msg;
505 return 0;
508 /* Mapping parse trees
509 * =================== */
511 /* Check whether a parse tree can safely be split in two. */
512 static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
514 const struct ldb_parse_tree *subtree = tree;
515 bool negate = false;
517 while (subtree) {
518 switch (subtree->operation) {
519 case LDB_OP_NOT:
520 negate = !negate;
521 subtree = subtree->u.isnot.child;
522 continue;
524 case LDB_OP_AND:
525 return !negate; /* if negate: False */
527 case LDB_OP_OR:
528 return negate; /* if negate: True */
530 default:
531 return true; /* simple parse tree */
535 return true; /* no parse tree */
538 /* Collect a list of attributes required to match a given parse tree. */
539 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
541 const char **new_attrs;
542 unsigned int i;
543 int ret;
545 if (tree == NULL) {
546 return 0;
549 switch (tree->operation) {
550 case LDB_OP_OR:
551 case LDB_OP_AND: /* attributes stored in list of subtrees */
552 for (i = 0; i < tree->u.list.num_elements; i++) {
553 ret = ldb_parse_tree_collect_attrs(module, mem_ctx,
554 attrs, tree->u.list.elements[i]);
555 if (ret) {
556 return ret;
559 return 0;
561 case LDB_OP_NOT: /* attributes stored in single subtree */
562 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
564 default: /* single attribute in tree */
565 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
566 talloc_free(*attrs);
567 *attrs = new_attrs;
568 return 0;
572 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
574 /* Select a negated subtree that queries attributes in the local partition */
575 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)
577 struct ldb_parse_tree *child;
578 int ret;
580 /* Prepare new tree */
581 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
582 if (*new == NULL) {
583 map_oom(module);
584 return -1;
587 /* Generate new subtree */
588 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
589 if (ret) {
590 talloc_free(*new);
591 return ret;
594 /* Prune tree without subtree */
595 if (child == NULL) {
596 talloc_free(*new);
597 *new = NULL;
598 return 0;
601 (*new)->u.isnot.child = child;
603 return ret;
606 /* Select a list of subtrees that query attributes in the local partition */
607 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)
609 unsigned int i, j;
610 int ret=0;
612 /* Prepare new tree */
613 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
614 if (*new == NULL) {
615 map_oom(module);
616 return -1;
619 /* Prepare list of subtrees */
620 (*new)->u.list.num_elements = 0;
621 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
622 if ((*new)->u.list.elements == NULL) {
623 map_oom(module);
624 talloc_free(*new);
625 return -1;
628 /* Generate new list of subtrees */
629 j = 0;
630 for (i = 0; i < tree->u.list.num_elements; i++) {
631 struct ldb_parse_tree *child;
632 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
633 if (ret) {
634 talloc_free(*new);
635 return ret;
638 if (child) {
639 (*new)->u.list.elements[j] = child;
640 j++;
644 /* Prune tree without subtrees */
645 if (j == 0) {
646 talloc_free(*new);
647 *new = NULL;
648 return 0;
651 /* Fix subtree list size */
652 (*new)->u.list.num_elements = j;
653 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
655 return ret;
658 /* Select a simple subtree that queries attributes in the local partition */
659 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)
661 /* Prepare new tree */
662 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
663 if (*new == NULL) {
664 map_oom(module);
665 return -1;
668 return 0;
671 /* Select subtrees that query attributes in the local partition */
672 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
674 const struct ldb_map_context *data = map_get_context(module);
676 if (tree == NULL) {
677 return 0;
680 if (tree->operation == LDB_OP_NOT) {
681 return map_subtree_select_local_not(module, mem_ctx, new, tree);
684 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
685 return map_subtree_select_local_list(module, mem_ctx, new, tree);
688 if (map_attr_check_remote(data, tree->u.equality.attr)) {
689 *new = NULL;
690 return 0;
693 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
696 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
698 /* Collect a negated subtree that queries attributes in the remote partition */
699 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)
701 struct ldb_parse_tree *child;
702 int ret;
704 /* Prepare new tree */
705 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
706 if (*new == NULL) {
707 map_oom(module);
708 return -1;
711 /* Generate new subtree */
712 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
713 if (ret) {
714 talloc_free(*new);
715 return ret;
718 /* Prune tree without subtree */
719 if (child == NULL) {
720 talloc_free(*new);
721 *new = NULL;
722 return 0;
725 (*new)->u.isnot.child = child;
727 return ret;
730 /* Collect a list of subtrees that query attributes in the remote partition */
731 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)
733 unsigned int i, j;
734 int ret=0;
736 /* Prepare new tree */
737 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
738 if (*new == NULL) {
739 map_oom(module);
740 return -1;
743 /* Prepare list of subtrees */
744 (*new)->u.list.num_elements = 0;
745 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
746 if ((*new)->u.list.elements == NULL) {
747 map_oom(module);
748 talloc_free(*new);
749 return -1;
752 /* Generate new list of subtrees */
753 j = 0;
754 for (i = 0; i < tree->u.list.num_elements; i++) {
755 struct ldb_parse_tree *child;
756 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
757 if (ret) {
758 talloc_free(*new);
759 return ret;
762 if (child) {
763 (*new)->u.list.elements[j] = child;
764 j++;
768 /* Prune tree without subtrees */
769 if (j == 0) {
770 talloc_free(*new);
771 *new = NULL;
772 return 0;
775 /* Fix subtree list size */
776 (*new)->u.list.num_elements = j;
777 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
779 return ret;
782 /* Collect a simple subtree that queries attributes in the remote partition */
783 int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree, const struct ldb_map_attribute *map)
785 const char *attr;
787 /* Prepare new tree */
788 *new = talloc(mem_ctx, struct ldb_parse_tree);
789 if (*new == NULL) {
790 map_oom(module);
791 return -1;
793 **new = *tree;
795 if (map->type == LDB_MAP_KEEP) {
796 /* Nothing to do here */
797 return 0;
800 /* Store attribute and value in new tree */
801 switch (tree->operation) {
802 case LDB_OP_PRESENT:
803 attr = map_attr_map_local(*new, map, tree->u.present.attr);
804 (*new)->u.present.attr = attr;
805 break;
806 case LDB_OP_SUBSTRING:
808 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
809 (*new)->u.substring.attr = attr;
810 break;
812 case LDB_OP_EQUALITY:
813 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
814 (*new)->u.equality.attr = attr;
815 break;
816 case LDB_OP_LESS:
817 case LDB_OP_GREATER:
818 case LDB_OP_APPROX:
819 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
820 (*new)->u.comparison.attr = attr;
821 break;
822 case LDB_OP_EXTENDED:
823 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
824 (*new)->u.extended.attr = attr;
825 break;
826 default: /* unknown kind of simple subtree */
827 talloc_free(*new);
828 return -1;
831 if (attr == NULL) {
832 talloc_free(*new);
833 *new = NULL;
834 return 0;
837 if (map->type == LDB_MAP_RENAME) {
838 /* Nothing more to do here, the attribute has been renamed */
839 return 0;
842 /* Store attribute and value in new tree */
843 switch (tree->operation) {
844 case LDB_OP_PRESENT:
845 break;
846 case LDB_OP_SUBSTRING:
848 int i;
849 /* Map value */
850 (*new)->u.substring.chunks = NULL;
851 for (i=0; tree->u.substring.chunks[i]; i++) {
852 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
853 if (!(*new)->u.substring.chunks) {
854 talloc_free(*new);
855 *new = NULL;
856 return 0;
858 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
859 if (!(*new)->u.substring.chunks[i]) {
860 talloc_free(*new);
861 *new = NULL;
862 return 0;
864 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
865 (*new)->u.substring.chunks[i+1] = NULL;
867 break;
869 case LDB_OP_EQUALITY:
870 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
871 break;
872 case LDB_OP_LESS:
873 case LDB_OP_GREATER:
874 case LDB_OP_APPROX:
875 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
876 break;
877 case LDB_OP_EXTENDED:
878 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
879 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
880 break;
881 default: /* unknown kind of simple subtree */
882 talloc_free(*new);
883 return -1;
886 return 0;
889 /* Collect subtrees that query attributes in the remote partition */
890 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
892 const struct ldb_map_context *data = map_get_context(module);
893 const struct ldb_map_attribute *map;
894 struct ldb_context *ldb;
896 ldb = ldb_module_get_ctx(module);
898 if (tree == NULL) {
899 return 0;
902 if (tree->operation == LDB_OP_NOT) {
903 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
906 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
907 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
910 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
911 *new = NULL;
912 return 0;
915 map = map_attr_find_local(data, tree->u.equality.attr);
916 if (map->convert_operator) {
917 return map->convert_operator(module, mem_ctx, new, tree);
920 if (map->type == LDB_MAP_GENERATE) {
921 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
922 "Skipping attribute '%s': "
923 "'convert_operator' not set",
924 tree->u.equality.attr);
925 *new = NULL;
926 return 0;
929 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
932 /* Split subtrees that query attributes in the local partition from
933 * those that query the remote partition. */
934 static int ldb_parse_tree_partition(struct ldb_module *module,
935 void *mem_ctx,
936 struct ldb_parse_tree **local_tree,
937 struct ldb_parse_tree **remote_tree,
938 const struct ldb_parse_tree *tree)
940 int ret;
942 *local_tree = NULL;
943 *remote_tree = NULL;
945 /* No original tree */
946 if (tree == NULL) {
947 return 0;
950 /* Generate local tree */
951 ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
952 if (ret) {
953 return ret;
956 /* Generate remote tree */
957 ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree);
958 if (ret) {
959 talloc_free(*local_tree);
960 return ret;
963 return 0;
966 /* Collect a list of attributes required either explicitly from a
967 * given list or implicitly from a given parse tree; split the
968 * collected list into local and remote parts. */
969 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
970 const char * const *search_attrs,
971 const struct ldb_parse_tree *tree)
973 void *tmp_ctx;
974 const char **tree_attrs;
975 const char **remote_attrs;
976 const char **local_attrs;
977 int ret;
979 /* There is no tree, just partition the searched attributes */
980 if (tree == NULL) {
981 ret = map_attrs_partition(module, ac,
982 &local_attrs, &remote_attrs, search_attrs);
983 if (ret == 0) {
984 ac->local_attrs = local_attrs;
985 ac->remote_attrs = remote_attrs;
986 ac->all_attrs = search_attrs;
988 return ret;
991 /* Create context for temporary memory */
992 tmp_ctx = talloc_new(ac);
993 if (tmp_ctx == NULL) {
994 goto oom;
997 /* Prepare list of attributes from tree */
998 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
999 if (tree_attrs == NULL) {
1000 talloc_free(tmp_ctx);
1001 goto oom;
1003 tree_attrs[0] = NULL;
1005 /* Collect attributes from tree */
1006 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
1007 if (ret) {
1008 goto done;
1011 /* Merge attributes from search operation */
1012 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
1013 if (ret) {
1014 goto done;
1017 /* Split local from remote attributes */
1018 ret = map_attrs_partition(module, ac, &local_attrs,
1019 &remote_attrs, tree_attrs);
1021 if (ret == 0) {
1022 ac->local_attrs = local_attrs;
1023 ac->remote_attrs = remote_attrs;
1024 talloc_steal(ac, tree_attrs);
1025 ac->all_attrs = tree_attrs;
1027 done:
1028 /* Free temporary memory */
1029 talloc_free(tmp_ctx);
1030 return ret;
1032 oom:
1033 map_oom(module);
1034 return -1;
1038 /* Outbound requests: search
1039 * ========================= */
1041 static int map_remote_search_callback(struct ldb_request *req,
1042 struct ldb_reply *ares);
1043 static int map_local_merge_callback(struct ldb_request *req,
1044 struct ldb_reply *ares);
1045 static int map_search_local(struct map_context *ac);
1047 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1049 struct map_reply *mr;
1051 mr = talloc_zero(ac, struct map_reply);
1052 if (mr == NULL) {
1053 map_oom(ac->module);
1054 return LDB_ERR_OPERATIONS_ERROR;
1056 mr->remote = talloc_steal(mr, ares);
1057 if (ac->r_current) {
1058 ac->r_current->next = mr;
1059 } else {
1060 /* first entry */
1061 ac->r_list = mr;
1063 ac->r_current = mr;
1065 return LDB_SUCCESS;
1068 /* Pass a merged search result up the callback chain. */
1069 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1071 struct ldb_message_element *el;
1072 const char * const *attrs;
1073 struct ldb_context *ldb;
1074 unsigned int i;
1075 int ret;
1076 bool matched;
1078 ldb = ldb_module_get_ctx(ac->module);
1080 /* Merged result doesn't match original query, skip */
1081 ret = ldb_match_msg_error(ldb, ares->message,
1082 ac->req->op.search.tree,
1083 ac->req->op.search.base,
1084 ac->req->op.search.scope,
1085 &matched);
1086 if (ret != LDB_SUCCESS) return ret;
1087 if (!matched) {
1088 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1089 "Skipping record '%s': "
1090 "doesn't match original search",
1091 ldb_dn_get_linearized(ares->message->dn));
1092 return LDB_SUCCESS;
1095 /* Limit result to requested attrs */
1096 if (ac->req->op.search.attrs &&
1097 (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1099 attrs = ac->req->op.search.attrs;
1100 i = 0;
1102 while (i < ares->message->num_elements) {
1104 el = &ares->message->elements[i];
1105 if ( ! ldb_attr_in_list(attrs, el->name)) {
1106 ldb_msg_remove_element(ares->message, el);
1107 } else {
1108 i++;
1113 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1116 /* Search a record. */
1117 int ldb_map_search(struct ldb_module *module, struct ldb_request *req)
1119 struct ldb_parse_tree *remote_tree;
1120 struct ldb_parse_tree *local_tree;
1121 struct ldb_request *remote_req;
1122 struct ldb_context *ldb;
1123 struct map_context *ac;
1124 int ret;
1126 const char *wildcard[] = { "*", NULL };
1127 const char * const *attrs;
1129 ldb = ldb_module_get_ctx(module);
1131 /* if we're not yet initialized, go to the next module */
1132 if (!ldb_module_get_private(module))
1133 return ldb_next_request(module, req);
1135 /* Do not manipulate our control entries */
1136 if (ldb_dn_is_special(req->op.search.base)) {
1137 return ldb_next_request(module, req);
1140 /* No mapping requested, skip to next module */
1141 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1142 return ldb_next_request(module, req);
1145 /* TODO: How can we be sure about which partition we are
1146 * targetting when there is no search base? */
1148 /* Prepare context and handle */
1149 ac = map_init_context(module, req);
1150 if (ac == NULL) {
1151 return LDB_ERR_OPERATIONS_ERROR;
1154 /* It is easier to deal with the two different ways of
1155 * expressing the wildcard in the same codepath */
1156 attrs = req->op.search.attrs;
1157 if (attrs == NULL) {
1158 attrs = wildcard;
1161 /* Split local from remote attrs */
1162 ret = map_attrs_collect_and_partition(module, ac,
1163 attrs, req->op.search.tree);
1164 if (ret) {
1165 return LDB_ERR_OPERATIONS_ERROR;
1168 /* Split local from remote tree */
1169 ret = ldb_parse_tree_partition(module, ac,
1170 &local_tree, &remote_tree,
1171 req->op.search.tree);
1172 if (ret) {
1173 return LDB_ERR_OPERATIONS_ERROR;
1176 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1177 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1178 /* The query can't safely be split, enumerate the remote partition */
1179 local_tree = NULL;
1180 remote_tree = NULL;
1183 if (local_tree == NULL) {
1184 /* Construct default local parse tree */
1185 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1186 if (local_tree == NULL) {
1187 map_oom(ac->module);
1188 return LDB_ERR_OPERATIONS_ERROR;
1191 local_tree->operation = LDB_OP_PRESENT;
1192 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1194 if (remote_tree == NULL) {
1195 /* Construct default remote parse tree */
1196 remote_tree = ldb_parse_tree(ac, NULL);
1197 if (remote_tree == NULL) {
1198 return LDB_ERR_OPERATIONS_ERROR;
1202 ac->local_tree = local_tree;
1204 /* Prepare the remote operation */
1205 ret = ldb_build_search_req_ex(&remote_req, ldb, ac,
1206 req->op.search.base,
1207 req->op.search.scope,
1208 remote_tree,
1209 ac->remote_attrs,
1210 req->controls,
1211 ac, map_remote_search_callback,
1212 req);
1213 LDB_REQ_SET_LOCATION(remote_req);
1214 if (ret != LDB_SUCCESS) {
1215 return LDB_ERR_OPERATIONS_ERROR;
1218 return ldb_next_remote_request(module, remote_req);
1221 /* Now, search the local part of a remote search result. */
1222 static int map_remote_search_callback(struct ldb_request *req,
1223 struct ldb_reply *ares)
1225 struct map_context *ac;
1226 int ret;
1228 ac = talloc_get_type(req->context, struct map_context);
1230 if (!ares) {
1231 return ldb_module_done(ac->req, NULL, NULL,
1232 LDB_ERR_OPERATIONS_ERROR);
1234 if (ares->error != LDB_SUCCESS) {
1235 return ldb_module_done(ac->req, ares->controls,
1236 ares->response, ares->error);
1239 switch (ares->type) {
1240 case LDB_REPLY_REFERRAL:
1242 /* ignore referrals */
1243 talloc_free(ares);
1244 return LDB_SUCCESS;
1246 case LDB_REPLY_ENTRY:
1248 /* Map result record into a local message */
1249 ret = map_reply_remote(ac, ares);
1250 if (ret) {
1251 talloc_free(ares);
1252 return ldb_module_done(ac->req, NULL, NULL,
1253 LDB_ERR_OPERATIONS_ERROR);
1256 /* if we have no local db, then we can just return the reply to
1257 * the upper layer, otherwise we must save it and process it
1258 * when all replies ahve been gathered */
1259 if ( ! map_check_local_db(ac->module)) {
1260 ret = map_return_entry(ac, ares);
1261 } else {
1262 ret = map_save_entry(ac,ares);
1265 if (ret != LDB_SUCCESS) {
1266 talloc_free(ares);
1267 return ldb_module_done(ac->req, NULL, NULL,
1268 LDB_ERR_OPERATIONS_ERROR);
1270 break;
1272 case LDB_REPLY_DONE:
1274 if ( ! map_check_local_db(ac->module)) {
1275 return ldb_module_done(ac->req, ares->controls,
1276 ares->response, LDB_SUCCESS);
1279 /* reset the pointer to the start of the list */
1280 ac->r_current = ac->r_list;
1282 /* no entry just return */
1283 if (ac->r_current == NULL) {
1284 ret = ldb_module_done(ac->req, ares->controls,
1285 ares->response, LDB_SUCCESS);
1286 talloc_free(ares);
1287 return ret;
1290 ac->remote_done_ares = talloc_steal(ac, ares);
1292 ret = map_search_local(ac);
1293 if (ret != LDB_SUCCESS) {
1294 return ldb_module_done(ac->req, NULL, NULL, ret);
1298 return LDB_SUCCESS;
1301 static int map_search_local(struct map_context *ac)
1303 struct ldb_request *search_req;
1305 if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1306 return LDB_ERR_OPERATIONS_ERROR;
1309 /* Prepare local search request */
1310 /* TODO: use GUIDs here instead? */
1311 search_req = map_search_base_req(ac,
1312 ac->r_current->remote->message->dn,
1313 NULL, NULL,
1314 ac, map_local_merge_callback);
1315 if (search_req == NULL) {
1316 return LDB_ERR_OPERATIONS_ERROR;
1319 return ldb_next_request(ac->module, search_req);
1322 /* Merge the remote and local parts of a search result. */
1323 int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares)
1325 struct ldb_context *ldb;
1326 struct map_context *ac;
1327 int ret;
1329 ac = talloc_get_type(req->context, struct map_context);
1330 ldb = ldb_module_get_ctx(ac->module);
1332 if (!ares) {
1333 return ldb_module_done(ac->req, NULL, NULL,
1334 LDB_ERR_OPERATIONS_ERROR);
1336 if (ares->error != LDB_SUCCESS) {
1337 return ldb_module_done(ac->req, ares->controls,
1338 ares->response, ares->error);
1341 switch (ares->type) {
1342 case LDB_REPLY_ENTRY:
1343 /* We have already found a local record */
1344 if (ac->r_current->local) {
1345 talloc_free(ares);
1346 ldb_set_errstring(ldb, "ldb_map: Too many results!");
1347 return ldb_module_done(ac->req, NULL, NULL,
1348 LDB_ERR_OPERATIONS_ERROR);
1351 /* Store local result */
1352 ac->r_current->local = talloc_steal(ac->r_current, ares);
1354 break;
1356 case LDB_REPLY_REFERRAL:
1357 /* ignore referrals */
1358 talloc_free(ares);
1359 break;
1361 case LDB_REPLY_DONE:
1362 /* We don't need the local 'ares', but we will use the remote one from below */
1363 talloc_free(ares);
1365 /* No local record found, map and send remote record */
1366 if (ac->r_current->local != NULL) {
1367 /* Merge remote into local message */
1368 ret = ldb_msg_merge_local(ac->module,
1369 ac->r_current->local->message,
1370 ac->r_current->remote->message);
1371 if (ret == LDB_SUCCESS) {
1372 ret = map_return_entry(ac, ac->r_current->local);
1374 if (ret != LDB_SUCCESS) {
1375 return ldb_module_done(ac->req, NULL, NULL,
1376 LDB_ERR_OPERATIONS_ERROR);
1378 } else {
1379 ret = map_return_entry(ac, ac->r_current->remote);
1380 if (ret != LDB_SUCCESS) {
1381 return ldb_module_done(ac->req,
1382 NULL, NULL, ret);
1386 if (ac->r_current->next != NULL) {
1387 ac->r_current = ac->r_current->next;
1388 if (ac->r_current->remote->type == LDB_REPLY_ENTRY) {
1389 ret = map_search_local(ac);
1390 if (ret != LDB_SUCCESS) {
1391 return ldb_module_done(ac->req,
1392 NULL, NULL, ret);
1394 break;
1398 /* ok we are done with all search, finally it is time to
1399 * finish operations for this module */
1400 return ldb_module_done(ac->req,
1401 ac->remote_done_ares->controls,
1402 ac->remote_done_ares->response,
1403 ac->remote_done_ares->error);
1406 return LDB_SUCCESS;