s4-dbcheck: support the 'none' option for prompts
[kai/samba.git] / source4 / lib / ldb / ldb_map / ldb_map_outbound.c
1 /*
2    ldb database mapping module
3
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
8
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
12    
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.
17
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.
22
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/>.
25
26 */
27
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"
33
34
35 /* Mapping attributes
36  * ================== */
37
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)
40 {
41         const struct ldb_map_context *data = map_get_context(module);
42         const char **result;
43         unsigned int i, last;
44
45         if (attrs == NULL)
46                 return NULL;
47
48         last = 0;
49         result = talloc_array(mem_ctx, const char *, 1);
50         if (result == NULL) {
51                 goto failed;
52         }
53         result[0] = NULL;
54
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;
62                         }
63
64                         result[last] = talloc_strdup(result, attrs[i]);
65                         result[last+1] = NULL;
66                         last++;
67                 }
68         }
69
70         return result;
71
72 failed:
73         talloc_free(result);
74         map_oom(module);
75         return NULL;
76 }
77
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)
81 {
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;
88
89         last = 0;
90         result = talloc_array(mem_ctx, const char *, 1);
91         if (result == NULL) {
92                 goto failed;
93         }
94         result[0] = NULL;
95
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;
103                         }
104                         ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
105                         if (ret != LDB_SUCCESS) {
106                                 goto failed;
107                         }
108
109                         attrs = new_attrs;
110                         break;
111                 }
112         }
113
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;
120                 }
121
122                 /* Add remote names of mapped attrs */
123                 map = map_attr_find_local(data, attrs[i]);
124                 if (map == NULL) {
125                         continue;
126                 }
127
128                 switch (map->type) {
129                 case LDB_MAP_IGNORE:
130                         continue;
131
132                 case LDB_MAP_KEEP:
133                         name = attrs[i];
134                         goto named;
135
136                 case LDB_MAP_RENAME:
137                 case LDB_MAP_CONVERT:
138                         name = map->u.rename.remote_name;
139                         goto named;
140
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;
147                                 }
148
149                                 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
150                                 result[last+1] = NULL;
151                                 last++;
152                         }
153                         continue;
154                 }
155
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;
160                 }
161
162                 result[last] = talloc_strdup(result, name);
163                 result[last+1] = NULL;
164                 last++;
165         }
166
167         return result;
168
169 failed:
170         talloc_free(result);
171         map_oom(module);
172         return NULL;
173 }
174
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)
178 {
179         *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
180         *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
181
182         return 0;
183 }
184
185 /* Mapping message elements
186  * ======================== */
187
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)
190 {
191         struct ldb_message_element *old;
192
193         old = ldb_msg_find_element(msg, el->name);
194
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;
199                 }
200                 talloc_free(discard_const_p(char, old->name));
201         }
202
203         /* copy new element */
204         *old = *el;
205
206         /* and make sure we reference the contents */
207         if (!talloc_reference(msg->elements, el->name)) {
208                 return -1;
209         }
210         if (!talloc_reference(msg->elements, el->values)) {
211                 return -1;
212         }
213
214         return 0;
215 }
216
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)
223 {
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;
228
229         el = talloc_zero(mem_ctx, struct ldb_message_element);
230         if (el == NULL) {
231                 map_oom(module);
232                 return NULL;
233         }
234
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;
240         }
241
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))) {
248
249                         local_attr_name = am->local_name;
250                         break;
251                 }
252         }
253
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;
259         }
260
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;
267                 }
268                 el->num_values++;
269         }
270
271         return el;
272 }
273
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)
277 {
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;
283
284         ldb = ldb_module_get_ctx(module);
285
286         /* We handle wildcards in ldb_msg_el_merge_wildcard */
287         if (ldb_attr_cmp(attr_name, "*") == 0) {
288                 return LDB_SUCCESS;
289         }
290
291         map = map_attr_find_local(data, attr_name);
292
293         /* Unknown attribute in remote message:
294          * skip, attribute was probably auto-generated */
295         if (map == NULL) {
296                 return LDB_SUCCESS;
297         }
298
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;
313         }
314
315         switch (map->type) {
316         case LDB_MAP_IGNORE:
317                 return LDB_SUCCESS;
318
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;
326                 }
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;
335                 }
336                 break;
337
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;
345                 }
346
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;
351                 }
352                 break;
353         }
354
355         if (el == NULL) {
356                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
357         }
358
359         return ldb_msg_replace(local, el);
360 }
361
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)
365 {
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;
371
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;
381                         }
382                         
383                         ret = ldb_msg_replace(local, el);
384                         if (ret) {
385                                 return ret;
386                         }
387                 }
388         }
389         
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;
400                 }
401         }
402
403         return LDB_SUCCESS;
404 }
405
406 /* Mapping messages
407  * ================ */
408
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)
411 {
412         unsigned int i;
413         int ret;
414
415         for (i = 0; i < msg2->num_elements; i++) {
416                 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
417                 if (ret) {
418                         return ret;
419                 }
420         }
421
422         return LDB_SUCCESS;
423 }
424
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)
428 {
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;
436                 }
437         }
438
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;
444                         }
445                         break;
446                 }
447         }
448
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;
458                 }
459         }
460
461         return LDB_SUCCESS;
462 }
463
464 /* Mapping search results
465  * ====================== */
466
467 /* Map a search result back into the local partition. */
468 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
469 {
470         struct ldb_message *msg;
471         struct ldb_dn *dn;
472         int ret;
473
474         /* There is no result message, skip */
475         if (ares->type != LDB_REPLY_ENTRY) {
476                 return 0;
477         }
478
479         /* Create a new result message */
480         msg = ldb_msg_new(ares);
481         if (msg == NULL) {
482                 map_oom(ac->module);
483                 return -1;
484         }
485
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;
491         }
492
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;
498         }
499         msg->dn = dn;
500
501         /* Store new message with new DN as the result */
502         talloc_free(ares->message);
503         ares->message = msg;
504
505         return 0;
506 }
507
508 /* Mapping parse trees
509  * =================== */
510
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)
513 {
514         const struct ldb_parse_tree *subtree = tree;
515         bool negate = false;
516
517         while (subtree) {
518                 switch (subtree->operation) {
519                 case LDB_OP_NOT:
520                         negate = !negate;
521                         subtree = subtree->u.isnot.child;
522                         continue;
523
524                 case LDB_OP_AND:
525                         return !negate; /* if negate: False */
526
527                 case LDB_OP_OR:
528                         return negate;  /* if negate: True */
529
530                 default:
531                         return true;    /* simple parse tree */
532                 }
533         }
534
535         return true;                    /* no parse tree */
536 }
537
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)
540 {
541         const char **new_attrs;
542         unsigned int i;
543         int ret;
544
545         if (tree == NULL) {
546                 return 0;
547         }
548
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;
557                         }
558                 }
559                 return 0;
560
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);
563
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;
569         }
570 }
571
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);
573
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)
576 {
577         struct ldb_parse_tree *child;
578         int ret;
579
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;
585         }
586
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;
592         }
593
594         /* Prune tree without subtree */
595         if (child == NULL) {
596                 talloc_free(*new);
597                 *new = NULL;
598                 return 0;
599         }
600
601         (*new)->u.isnot.child = child;
602
603         return ret;
604 }
605
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)
608 {
609         unsigned int i, j;
610         int ret=0;
611
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;
617         }
618
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;
626         }
627
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;
636                 }
637
638                 if (child) {
639                         (*new)->u.list.elements[j] = child;
640                         j++;
641                 }
642         }
643
644         /* Prune tree without subtrees */
645         if (j == 0) {
646                 talloc_free(*new);
647                 *new = NULL;
648                 return 0;
649         }
650
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);
654
655         return ret;
656 }
657
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)
660 {
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;
666         }
667
668         return 0;
669 }
670
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)
673 {
674         const struct ldb_map_context *data = map_get_context(module);
675
676         if (tree == NULL) {
677                 return 0;
678         }
679
680         if (tree->operation == LDB_OP_NOT) {
681                 return map_subtree_select_local_not(module, mem_ctx, new, tree);
682         }
683
684         if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
685                 return map_subtree_select_local_list(module, mem_ctx, new, tree);
686         }
687
688         if (map_attr_check_remote(data, tree->u.equality.attr)) {
689                 *new = NULL;
690                 return 0;
691         }
692
693         return map_subtree_select_local_simple(module, mem_ctx, new, tree);
694 }
695
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);
697
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)
700 {
701         struct ldb_parse_tree *child;
702         int ret;
703
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;
709         }
710
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;
716         }
717
718         /* Prune tree without subtree */
719         if (child == NULL) {
720                 talloc_free(*new);
721                 *new = NULL;
722                 return 0;
723         }
724
725         (*new)->u.isnot.child = child;
726
727         return ret;
728 }
729
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)
732 {
733         unsigned int i, j;
734         int ret=0;
735
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;
741         }
742
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;
750         }
751
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;
760                 }
761
762                 if (child) {
763                         (*new)->u.list.elements[j] = child;
764                         j++;
765                 }
766         }
767
768         /* Prune tree without subtrees */
769         if (j == 0) {
770                 talloc_free(*new);
771                 *new = NULL;
772                 return 0;
773         }
774
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);
778
779         return ret;
780 }
781
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)
784 {
785         const char *attr;
786
787         /* Prepare new tree */
788         *new = talloc(mem_ctx, struct ldb_parse_tree);
789         if (*new == NULL) {
790                 map_oom(module);
791                 return -1;
792         }
793         **new = *tree;
794         
795         if (map->type == LDB_MAP_KEEP) {
796                 /* Nothing to do here */
797                 return 0;
798         }
799
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:
807         {
808                 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
809                 (*new)->u.substring.attr = attr;
810                 break;
811         }
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;
829         }
830
831         if (attr == NULL) {
832                 talloc_free(*new);
833                 *new = NULL;
834                 return 0;
835         }
836
837         if (map->type == LDB_MAP_RENAME) {
838                 /* Nothing more to do here, the attribute has been renamed */
839                 return 0;
840         }
841
842         /* Store attribute and value in new tree */
843         switch (tree->operation) {
844         case LDB_OP_PRESENT:
845                 break;
846         case LDB_OP_SUBSTRING:
847         {
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;
857                         }
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;
863                         }
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;
866                 }
867                 break;
868         }
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;
884         }
885
886         return 0;
887 }
888
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)
891 {
892         const struct ldb_map_context *data = map_get_context(module);
893         const struct ldb_map_attribute *map;
894         struct ldb_context *ldb;
895
896         ldb = ldb_module_get_ctx(module);
897
898         if (tree == NULL) {
899                 return 0;
900         }
901
902         if (tree->operation == LDB_OP_NOT) {
903                 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
904         }
905
906         if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
907                 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
908         }
909
910         if (!map_attr_check_remote(data, tree->u.equality.attr)) {
911                 *new = NULL;
912                 return 0;
913         }
914
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);
918         }
919
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;
927         }
928
929         return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
930 }
931
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)
939 {
940         int ret;
941
942         *local_tree = NULL;
943         *remote_tree = NULL;
944
945         /* No original tree */
946         if (tree == NULL) {
947                 return 0;
948         }
949
950         /* Generate local tree */
951         ret = map_subtree_select_local(module, mem_ctx, local_tree, tree);
952         if (ret) {
953                 return ret;
954         }
955
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;
961         }
962
963         return 0;
964 }
965
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)
972 {
973         void *tmp_ctx;
974         const char **tree_attrs;
975         const char **remote_attrs;
976         const char **local_attrs;
977         int ret;
978
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;
987                 }
988                 return ret; 
989         }
990
991         /* Create context for temporary memory */
992         tmp_ctx = talloc_new(ac);
993         if (tmp_ctx == NULL) {
994                 goto oom;
995         }
996
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;
1002         }
1003         tree_attrs[0] = NULL;
1004
1005         /* Collect attributes from tree */
1006         ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
1007         if (ret) {
1008                 goto done;
1009         }
1010
1011         /* Merge attributes from search operation */
1012         ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
1013         if (ret) {
1014                 goto done;
1015         }
1016
1017         /* Split local from remote attributes */
1018         ret = map_attrs_partition(module, ac, &local_attrs, 
1019                                   &remote_attrs, tree_attrs);
1020         
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;
1026         }
1027 done:
1028         /* Free temporary memory */
1029         talloc_free(tmp_ctx);
1030         return ret;
1031
1032 oom:
1033         map_oom(module);
1034         return -1;
1035 }
1036
1037
1038 /* Outbound requests: search
1039  * ========================= */
1040
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);
1046
1047 static int map_save_entry(struct map_context *ac, struct ldb_reply *ares)
1048 {
1049         struct map_reply *mr;
1050
1051         mr = talloc_zero(ac, struct map_reply);
1052         if (mr == NULL) {
1053                 map_oom(ac->module);
1054                 return LDB_ERR_OPERATIONS_ERROR;
1055         }
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;
1062         }
1063         ac->r_current = mr;
1064
1065         return LDB_SUCCESS;
1066 }
1067
1068 /* Pass a merged search result up the callback chain. */
1069 int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
1070 {
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;
1077
1078         ldb = ldb_module_get_ctx(ac->module);
1079
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;
1093         }
1094
1095         /* Limit result to requested attrs */
1096         if (ac->req->op.search.attrs &&
1097             (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) {
1098
1099                 attrs = ac->req->op.search.attrs;
1100                 i = 0;
1101
1102                 while (i < ares->message->num_elements) {
1103
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++;
1109                         }
1110                 }
1111         }
1112
1113         return ldb_module_send_entry(ac->req, ares->message, ares->controls);
1114 }
1115
1116 /* Search a record. */
1117 int ldb_map_search(struct ldb_module *module, struct ldb_request *req)
1118 {
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;
1125
1126         const char *wildcard[] = { "*", NULL };
1127         const char * const *attrs;
1128
1129         ldb = ldb_module_get_ctx(module);
1130
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);
1134
1135         /* Do not manipulate our control entries */
1136         if (ldb_dn_is_special(req->op.search.base)) {
1137                 return ldb_next_request(module, req);
1138         }
1139
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);
1143         }
1144
1145         /* TODO: How can we be sure about which partition we are
1146          *       targetting when there is no search base? */
1147
1148         /* Prepare context and handle */
1149         ac = map_init_context(module, req);
1150         if (ac == NULL) {
1151                 return LDB_ERR_OPERATIONS_ERROR;
1152         }
1153
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;
1159         }
1160
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;
1166         }
1167
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;
1174         }
1175
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;
1181         }
1182
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;
1189                 }
1190
1191                 local_tree->operation = LDB_OP_PRESENT;
1192                 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1193         }
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;
1199                 }
1200         }
1201
1202         ac->local_tree = local_tree;
1203
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;
1216         }
1217
1218         return ldb_next_remote_request(module, remote_req);
1219 }
1220
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)
1224 {
1225         struct map_context *ac;
1226         int ret;
1227
1228         ac = talloc_get_type(req->context, struct map_context);
1229
1230         if (!ares) {
1231                 return ldb_module_done(ac->req, NULL, NULL,
1232                                         LDB_ERR_OPERATIONS_ERROR);
1233         }
1234         if (ares->error != LDB_SUCCESS) {
1235                 return ldb_module_done(ac->req, ares->controls,
1236                                         ares->response, ares->error);
1237         }
1238
1239         switch (ares->type) {
1240         case LDB_REPLY_REFERRAL:
1241
1242                 /* ignore referrals */
1243                 talloc_free(ares);
1244                 return LDB_SUCCESS;
1245
1246         case LDB_REPLY_ENTRY:
1247
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);
1254                 }
1255
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);
1263                 }
1264
1265                 if (ret != LDB_SUCCESS) {
1266                         talloc_free(ares);
1267                         return ldb_module_done(ac->req, NULL, NULL,
1268                                                 LDB_ERR_OPERATIONS_ERROR);
1269                 }
1270                 break;
1271
1272         case LDB_REPLY_DONE:
1273
1274                 if ( ! map_check_local_db(ac->module)) {
1275                         return ldb_module_done(ac->req, ares->controls,
1276                                                 ares->response, LDB_SUCCESS);
1277                 }
1278
1279                 /* reset the pointer to the start of the list */
1280                 ac->r_current = ac->r_list;
1281
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;
1288                 }
1289
1290                 ac->remote_done_ares = talloc_steal(ac, ares);
1291
1292                 ret = map_search_local(ac);
1293                 if (ret != LDB_SUCCESS) {
1294                         return ldb_module_done(ac->req, NULL, NULL, ret);
1295                 }
1296         }
1297
1298         return LDB_SUCCESS;
1299 }
1300
1301 static int map_search_local(struct map_context *ac)
1302 {
1303         struct ldb_request *search_req;
1304
1305         if (ac->r_current == NULL || ac->r_current->remote == NULL) {
1306                 return LDB_ERR_OPERATIONS_ERROR;
1307         }
1308
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;
1317         }
1318
1319         return ldb_next_request(ac->module, search_req);
1320 }
1321
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)
1324 {
1325         struct ldb_context *ldb;
1326         struct map_context *ac;
1327         int ret;
1328
1329         ac = talloc_get_type(req->context, struct map_context);
1330         ldb = ldb_module_get_ctx(ac->module);
1331
1332         if (!ares) {
1333                 return ldb_module_done(ac->req, NULL, NULL,
1334                                         LDB_ERR_OPERATIONS_ERROR);
1335         }
1336         if (ares->error != LDB_SUCCESS) {
1337                 return ldb_module_done(ac->req, ares->controls,
1338                                         ares->response, ares->error);
1339         }
1340
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);
1349                 }
1350
1351                 /* Store local result */
1352                 ac->r_current->local = talloc_steal(ac->r_current, ares);
1353
1354                 break;
1355
1356         case LDB_REPLY_REFERRAL:
1357                 /* ignore referrals */
1358                 talloc_free(ares);
1359                 break;
1360
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);
1364
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);
1373                         }
1374                         if (ret != LDB_SUCCESS) {
1375                                 return ldb_module_done(ac->req, NULL, NULL,
1376                                                         LDB_ERR_OPERATIONS_ERROR);
1377                         }
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);
1383                         }
1384                 }
1385
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);
1393                                 }
1394                                 break;
1395                         }
1396                 }
1397
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);
1404         }
1405
1406         return LDB_SUCCESS;
1407 }