cd33f2904363714277c32666f2f567a61c6f8b8e
[kamenim/samba.git] / source4 / lib / ldb / modules / 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
8    * NOTICE: this module is NOT released under the GNU LGPL license as
9    * other ldb code. This module is release under the GNU GPL v2 or
10    * later license.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include "includes.h"
28 #include "ldb/include/includes.h"
29
30 #include "ldb/modules/ldb_map.h"
31 #include "ldb/modules/ldb_map_private.h"
32
33
34 /* Mapping attributes
35  * ================== */
36
37 /* Select attributes that stay in the local partition. */
38 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
39 {
40         const struct ldb_map_context *data = map_get_context(module);
41         const char **result;
42         int i, last;
43
44         if (attrs == NULL)
45                 return NULL;
46
47         last = 0;
48         result = talloc_array(mem_ctx, const char *, 1);
49         if (result == NULL) {
50                 goto failed;
51         }
52         result[0] = NULL;
53
54         for (i = 0; attrs[i]; i++) {
55                 /* Wildcards and ignored attributes are kept locally */
56                 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
57                     (!map_attr_check_remote(data, attrs[i]))) {
58                         result = talloc_realloc(mem_ctx, result, const char *, last+2);
59                         if (result == NULL) {
60                                 goto failed;
61                         }
62
63                         result[last] = talloc_strdup(result, attrs[i]);
64                         result[last+1] = NULL;
65                         last++;
66                 }
67         }
68
69         return result;
70
71 failed:
72         talloc_free(result);
73         map_oom(module);
74         return NULL;
75 }
76
77 /* Collect attributes that are mapped into the remote partition. */
78 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
79 {
80         const struct ldb_map_context *data = map_get_context(module);
81         const char **result;
82         const struct ldb_map_attribute *map;
83         const char *name=NULL;
84         int i, j, last;
85         int ret;
86
87         last = 0;
88         result = talloc_array(mem_ctx, const char *, 1);
89         if (result == NULL) {
90                 goto failed;
91         }
92         result[0] = NULL;
93
94         for (i = 0; attrs[i]; i++) {
95                 /* Wildcards are kept remotely, too */
96                 if (ldb_attr_cmp(attrs[i], "*") == 0) {
97                         const char **new_attrs = NULL;
98                         ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
99                         if (ret != LDB_SUCCESS) {
100                                 goto failed;
101                         }
102                         ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
103                         if (ret != LDB_SUCCESS) {
104                                 goto failed;
105                         }
106
107                         attrs = new_attrs;
108                         break;
109                 }
110         }
111
112         for (i = 0; attrs[i]; i++) {
113                 /* Wildcards are kept remotely, too */
114                 if (ldb_attr_cmp(attrs[i], "*") == 0) {
115                         /* Add all 'include in wildcard' attributes */
116                         name = attrs[i];
117                         goto named;
118                 }
119
120                 /* Add remote names of mapped attrs */
121                 map = map_attr_find_local(data, attrs[i]);
122                 if (map == NULL) {
123                         continue;
124                 }
125
126                 switch (map->type) {
127                 case MAP_IGNORE:
128                         continue;
129
130                 case MAP_KEEP:
131                         name = attrs[i];
132                         goto named;
133
134                 case MAP_RENAME:
135                 case MAP_CONVERT:
136                         name = map->u.rename.remote_name;
137                         goto named;
138
139                 case MAP_GENERATE:
140                         /* Add all remote names of "generate" attrs */
141                         for (j = 0; map->u.generate.remote_names[j]; j++) {
142                                 result = talloc_realloc(mem_ctx, result, const char *, last+2);
143                                 if (result == NULL) {
144                                         goto failed;
145                                 }
146
147                                 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
148                                 result[last+1] = NULL;
149                                 last++;
150                         }
151                         continue;
152                 }
153
154         named:  /* We found a single remote name, add that */
155                 result = talloc_realloc(mem_ctx, result, const char *, last+2);
156                 if (result == NULL) {
157                         goto failed;
158                 }
159
160                 result[last] = talloc_strdup(result, name);
161                 result[last+1] = NULL;
162                 last++;
163         }
164
165         return result;
166
167 failed:
168         talloc_free(result);
169         map_oom(module);
170         return NULL;
171 }
172
173 /* Split attributes that stay in the local partition from those that
174  * are mapped into the remote partition. */
175 static int map_attrs_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
176 {
177         *local_attrs = map_attrs_select_local(module, local_ctx, attrs);
178         *remote_attrs = map_attrs_collect_remote(module, remote_ctx, attrs);
179
180         return 0;
181 }
182
183 /* Mapping message elements
184  * ======================== */
185
186 /* Add an element to a message, overwriting any old identically named elements. */
187 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
188 {
189         struct ldb_message_element *old;
190
191         old = ldb_msg_find_element(msg, el->name);
192
193         /* no local result, add as new element */
194         if (old == NULL) {
195                 if (ldb_msg_add_empty(msg, el->name, 0) != 0) {
196                         return -1;
197                 }
198
199                 old = ldb_msg_find_element(msg, el->name);
200                 if (old == NULL) {
201                         return -1;
202                 }
203         }
204
205         /* copy new element */
206         *old = *el;
207
208         /* and make sure we reference the contents */
209         if (!talloc_reference(msg->elements, el->name)) {
210                 return -1;
211         }
212         if (!talloc_reference(msg->elements, el->values)) {
213                 return -1;
214         }
215
216         return 0;
217 }
218
219 /* Map a message element back into the local partition. */
220 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
221 {
222         struct ldb_message_element *el;
223         int i;
224
225         el = talloc_zero(mem_ctx, struct ldb_message_element);
226         if (el == NULL) {
227                 map_oom(module);
228                 return NULL;
229         }
230
231         el->num_values = old->num_values;
232         el->values = talloc_array(el, struct ldb_val, el->num_values);
233         if (el->values == NULL) {
234                 talloc_free(el);
235                 map_oom(module);
236                 return NULL;
237         }
238
239         el->name = map_attr_map_remote(el, map, old->name);
240
241         for (i = 0; i < el->num_values; i++) {
242                 el->values[i] = ldb_val_map_remote(module, el->values, map, old->values[i]);
243         }
244
245         return el;
246 }
247
248 /* Merge a remote message element into a local message. */
249 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const char *attr_name, const struct ldb_message_element *old)
250 {
251         const struct ldb_map_context *data = map_get_context(module);
252         const struct ldb_map_attribute *map = map_attr_find_remote(data, attr_name);
253         struct ldb_message_element *el=NULL;
254
255         /* Unknown attribute in remote message:
256          * skip, attribute was probably auto-generated */
257         if (map == NULL) {
258                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
259                           "Skipping attribute '%s': no mapping found\n",
260                           old->name);
261                 return 0;
262         }
263
264         switch (map->type) {
265         case MAP_IGNORE:
266                 return -1;
267
268         case MAP_CONVERT:
269                 if (map->u.convert.convert_remote == NULL) {
270                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
271                                   "Skipping attribute '%s': "
272                                   "'convert_remote' not set\n",
273                                   old->name);
274                         return 0;
275                 }
276                 /* fall through */
277         case MAP_KEEP:
278         case MAP_RENAME:
279                 el = ldb_msg_el_map_remote(module, local, map, old);
280                 break;
281
282         case MAP_GENERATE:
283                 if (map->u.generate.generate_local == NULL) {
284                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
285                                   "Skipping attribute '%s': "
286                                   "'generate_local' not set\n",
287                                   old->name);
288                         return 0;
289                 }
290
291                 el = map->u.generate.generate_local(module, local, old->name, remote);
292                 break;
293         }
294
295         if (el == NULL) {
296                 return -1;
297         }
298
299         return ldb_msg_replace(local, el);
300 }
301
302 /* Mapping messages
303  * ================ */
304
305 /* Merge two local messages into a single one. */
306 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
307 {
308         int i, ret;
309
310         for (i = 0; i < msg2->num_elements; i++) {
311                 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
312                 if (ret) {
313                         return ret;
314                 }
315         }
316
317         return 0;
318 }
319
320 /* Merge a local and a remote message into a single local one. */
321 static int ldb_msg_merge_remote(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote)
322 {
323         int i, ret;
324
325         /* Try to map each attribute back;
326          * Add to local message is possible,
327          * Overwrite old local attribute if necessary */
328         for (i = 0; i < remote->num_elements; i++) {
329                 ret = ldb_msg_el_merge(module, local, remote, remote->elements[i].name, &remote->elements[i]);
330                 if (ret) {
331                         return ret;
332                 }
333         }
334
335         return 0;
336 }
337
338 /* Mapping search results
339  * ====================== */
340
341 /* Map a search result back into the local partition. */
342 static int map_reply_remote(struct ldb_module *module, struct ldb_reply *ares)
343 {
344         struct ldb_message *msg;
345         struct ldb_dn *dn;
346         int ret;
347
348         /* There is no result message, skip */
349         if (ares->type != LDB_REPLY_ENTRY) {
350                 return 0;
351         }
352
353         /* Create a new result message */
354         msg = ldb_msg_new(ares);
355         if (msg == NULL) {
356                 map_oom(module);
357                 return -1;
358         }
359
360         /* Merge remote message into new message */
361         ret = ldb_msg_merge_remote(module, msg, ares->message);
362         if (ret) {
363                 talloc_free(msg);
364                 return ret;
365         }
366
367         /* Create corresponding local DN */
368         dn = ldb_dn_map_rebase_remote(module, msg, ares->message->dn);
369         if (dn == NULL) {
370                 talloc_free(msg);
371                 return -1;
372         }
373         msg->dn = dn;
374
375         /* Store new message with new DN as the result */
376         talloc_free(ares->message);
377         ares->message = msg;
378
379         return 0;
380 }
381
382 /* Mapping parse trees
383  * =================== */
384
385 /* Check whether a parse tree can safely be split in two. */
386 static BOOL ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
387 {
388         const struct ldb_parse_tree *subtree = tree;
389         BOOL negate = False;
390
391         while (subtree) {
392                 switch (subtree->operation) {
393                 case LDB_OP_NOT:
394                         negate = !negate;
395                         subtree = subtree->u.isnot.child;
396                         continue;
397
398                 case LDB_OP_AND:
399                         return !negate; /* if negate: False */
400
401                 case LDB_OP_OR:
402                         return negate;  /* if negate: True */
403
404                 default:
405                         return True;    /* simple parse tree */
406                 }
407         }
408
409         return True;                    /* no parse tree */
410 }
411
412 /* Collect a list of attributes required to match a given parse tree. */
413 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
414 {
415         const char **new_attrs;
416         int i, ret;
417
418         if (tree == NULL) {
419                 return 0;
420         }
421
422         switch (tree->operation) {
423         case LDB_OP_OR:
424         case LDB_OP_AND:                /* attributes stored in list of subtrees */
425                 for (i = 0; i < tree->u.list.num_elements; i++) {
426                         ret = ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.list.elements[i]);
427                         if (ret) {
428                                 return ret;
429                         }
430                 }
431                 return 0;
432
433         case LDB_OP_NOT:                /* attributes stored in single subtree */
434                 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
435
436         default:                        /* single attribute in tree */
437                 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
438                 talloc_free(*attrs);
439                 *attrs = new_attrs;
440                 return 0;
441         }
442
443         return -1;
444 }
445
446 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
447
448 /* Select a negated subtree that queries attributes in the local partition */
449 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)
450 {
451         struct ldb_parse_tree *child;
452         int ret;
453
454         /* Prepare new tree */
455         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
456         if (*new == NULL) {
457                 map_oom(module);
458                 return -1;
459         }
460
461         /* Generate new subtree */
462         ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
463         if (ret) {
464                 talloc_free(*new);
465                 return ret;
466         }
467
468         /* Prune tree without subtree */
469         if (child == NULL) {
470                 talloc_free(*new);
471                 *new = NULL;
472                 return 0;
473         }
474
475         (*new)->u.isnot.child = child;
476
477         return ret;
478 }
479
480 /* Select a list of subtrees that query attributes in the local partition */
481 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)
482 {
483         int i, j, ret=0;
484
485         /* Prepare new tree */
486         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
487         if (*new == NULL) {
488                 map_oom(module);
489                 return -1;
490         }
491
492         /* Prepare list of subtrees */
493         (*new)->u.list.num_elements = 0;
494         (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
495         if ((*new)->u.list.elements == NULL) {
496                 map_oom(module);
497                 talloc_free(*new);
498                 return -1;
499         }
500
501         /* Generate new list of subtrees */
502         j = 0;
503         for (i = 0; i < tree->u.list.num_elements; i++) {
504                 struct ldb_parse_tree *child;
505                 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
506                 if (ret) {
507                         talloc_free(*new);
508                         return ret;
509                 }
510
511                 if (child) {
512                         (*new)->u.list.elements[j] = child;
513                         j++;
514                 }
515         }
516
517         /* Prune tree without subtrees */
518         if (j == 0) {
519                 talloc_free(*new);
520                 *new = NULL;
521                 return 0;
522         }
523
524         /* Fix subtree list size */
525         (*new)->u.list.num_elements = j;
526         (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
527
528         return ret;
529 }
530
531 /* Select a simple subtree that queries attributes in the local partition */
532 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)
533 {
534         /* Prepare new tree */
535         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
536         if (*new == NULL) {
537                 map_oom(module);
538                 return -1;
539         }
540
541         return 0;
542 }
543
544 /* Select subtrees that query attributes in the local partition */
545 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
546 {
547         const struct ldb_map_context *data = map_get_context(module);
548
549         if (tree == NULL) {
550                 return 0;
551         }
552
553         if (tree->operation == LDB_OP_NOT) {
554                 return map_subtree_select_local_not(module, mem_ctx, new, tree);
555         }
556
557         if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
558                 return map_subtree_select_local_list(module, mem_ctx, new, tree);
559         }
560
561         if (map_attr_check_remote(data, tree->u.equality.attr)) {
562                 *new = NULL;
563                 return 0;
564         }
565
566         return map_subtree_select_local_simple(module, mem_ctx, new, tree);
567 }
568
569 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
570
571 /* Collect a negated subtree that queries attributes in the remote partition */
572 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)
573 {
574         struct ldb_parse_tree *child;
575         int ret;
576
577         /* Prepare new tree */
578         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
579         if (*new == NULL) {
580                 map_oom(module);
581                 return -1;
582         }
583
584         /* Generate new subtree */
585         ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
586         if (ret) {
587                 talloc_free(*new);
588                 return ret;
589         }
590
591         /* Prune tree without subtree */
592         if (child == NULL) {
593                 talloc_free(*new);
594                 *new = NULL;
595                 return 0;
596         }
597
598         (*new)->u.isnot.child = child;
599
600         return ret;
601 }
602
603 /* Collect a list of subtrees that query attributes in the remote partition */
604 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)
605 {
606         int i, j, ret=0;
607
608         /* Prepare new tree */
609         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
610         if (*new == NULL) {
611                 map_oom(module);
612                 return -1;
613         }
614
615         /* Prepare list of subtrees */
616         (*new)->u.list.num_elements = 0;
617         (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
618         if ((*new)->u.list.elements == NULL) {
619                 map_oom(module);
620                 talloc_free(*new);
621                 return -1;
622         }
623
624         /* Generate new list of subtrees */
625         j = 0;
626         for (i = 0; i < tree->u.list.num_elements; i++) {
627                 struct ldb_parse_tree *child;
628                 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
629                 if (ret) {
630                         talloc_free(*new);
631                         return ret;
632                 }
633
634                 if (child) {
635                         (*new)->u.list.elements[j] = child;
636                         j++;
637                 }
638         }
639
640         /* Prune tree without subtrees */
641         if (j == 0) {
642                 talloc_free(*new);
643                 *new = NULL;
644                 return 0;
645         }
646
647         /* Fix subtree list size */
648         (*new)->u.list.num_elements = j;
649         (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
650
651         return ret;
652 }
653
654 /* Collect a simple subtree that queries attributes in the remote partition */
655 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)
656 {
657         const char *attr;
658
659         /* Prepare new tree */
660         *new = talloc(mem_ctx, struct ldb_parse_tree);
661         if (*new == NULL) {
662                 map_oom(module);
663                 return -1;
664         }
665         **new = *tree;
666         
667         if (map->type == MAP_KEEP) {
668                 /* Nothing to do here */
669                 return 0;
670         }
671
672         /* Store attribute and value in new tree */
673         switch (tree->operation) {
674         case LDB_OP_PRESENT:
675                 attr = map_attr_map_local(*new, map, tree->u.present.attr);
676                 (*new)->u.present.attr = attr;
677                 break;
678         case LDB_OP_SUBSTRING:
679         {
680                 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
681                 (*new)->u.substring.attr = attr;
682                 break;
683         }
684         case LDB_OP_EQUALITY:
685                 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
686                 (*new)->u.equality.attr = attr;
687                 break;
688         case LDB_OP_LESS:
689         case LDB_OP_GREATER:
690         case LDB_OP_APPROX:
691                 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
692                 (*new)->u.comparison.attr = attr;
693                 break;
694         case LDB_OP_EXTENDED:
695                 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
696                 (*new)->u.extended.attr = attr;
697                 break;
698         default:                        /* unknown kind of simple subtree */
699                 talloc_free(*new);
700                 return -1;
701         }
702
703         if (attr == NULL) {
704                 talloc_free(*new);
705                 *new = NULL;
706                 return 0;
707         }
708
709         if (map->type == MAP_RENAME) {
710                 /* Nothing more to do here, the attribute has been renamed */
711                 return 0;
712         }
713
714         /* Store attribute and value in new tree */
715         switch (tree->operation) {
716         case LDB_OP_PRESENT:
717                 break;
718         case LDB_OP_SUBSTRING:
719         {
720                 int i;
721                 /* Map value */
722                 (*new)->u.substring.chunks = NULL;
723                 for (i=0; tree->u.substring.chunks[i]; i++) {
724                         (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
725                         if (!(*new)->u.substring.chunks) {
726                                 talloc_free(*new);
727                                 *new = NULL;
728                                 return 0;
729                         }
730                         (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
731                         if (!(*new)->u.substring.chunks[i]) {
732                                 talloc_free(*new);
733                                 *new = NULL;
734                                 return 0;
735                         }
736                         *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, *tree->u.substring.chunks[i]);
737                         (*new)->u.substring.chunks[i+1] = NULL;
738                 }
739                 break;
740         }
741         case LDB_OP_EQUALITY:
742                 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, tree->u.equality.value);
743                 break;
744         case LDB_OP_LESS:
745         case LDB_OP_GREATER:
746         case LDB_OP_APPROX:
747                 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, tree->u.comparison.value);
748                 break;
749         case LDB_OP_EXTENDED:
750                 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, tree->u.extended.value);
751                 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
752                 break;
753         default:                        /* unknown kind of simple subtree */
754                 talloc_free(*new);
755                 return -1;
756         }
757
758         return 0;
759 }
760
761 /* Collect subtrees that query attributes in the remote partition */
762 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
763 {
764         const struct ldb_map_context *data = map_get_context(module);
765         const struct ldb_map_attribute *map;
766
767         if (tree == NULL) {
768                 return 0;
769         }
770
771         if (tree->operation == LDB_OP_NOT) {
772                 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
773         }
774
775         if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
776                 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
777         }
778
779         if (!map_attr_check_remote(data, tree->u.equality.attr)) {
780                 *new = NULL;
781                 return 0;
782         }
783
784         map = map_attr_find_local(data, tree->u.equality.attr);
785         if (map->convert_operator) {
786                 return map->convert_operator(module, mem_ctx, new, tree);
787         }
788
789         if (map->type == MAP_GENERATE) {
790                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
791                           "Skipping attribute '%s': "
792                           "'convert_operator' not set\n",
793                           tree->u.equality.attr);
794                 *new = NULL;
795                 return 0;
796         }
797
798         return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
799 }
800
801 /* Split subtrees that query attributes in the local partition from
802  * those that query the remote partition. */
803 static int ldb_parse_tree_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, struct ldb_parse_tree **local_tree, struct ldb_parse_tree **remote_tree, const struct ldb_parse_tree *tree)
804 {
805         int ret;
806
807         *local_tree = NULL;
808         *remote_tree = NULL;
809
810         /* No original tree */
811         if (tree == NULL) {
812                 return 0;
813         }
814
815         /* Generate local tree */
816         ret = map_subtree_select_local(module, local_ctx, local_tree, tree);
817         if (ret) {
818                 return ret;
819         }
820
821         /* Generate remote tree */
822         ret = map_subtree_collect_remote(module, remote_ctx, remote_tree, tree);
823         if (ret) {
824                 talloc_free(*local_tree);
825                 return ret;
826         }
827
828         return 0;
829 }
830
831 /* Collect a list of attributes required either explicitly from a
832  * given list or implicitly  from a given parse tree; split the
833  * collected list into local and remote parts. */
834 static int map_attrs_collect_and_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *search_attrs, const struct ldb_parse_tree *tree)
835 {
836         void *tmp_ctx;
837         const char **tree_attrs;
838         int ret;
839
840         /* Clear initial lists of partitioned attributes */
841         *local_attrs = NULL;
842         *remote_attrs = NULL;
843
844         /* There is no tree, just partition the searched attributes */
845         if (tree == NULL) {
846                 return map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, search_attrs);
847         }
848
849         /* Create context for temporary memory */
850         tmp_ctx = talloc_new(local_ctx);
851         if (tmp_ctx == NULL) {
852                 goto oom;
853         }
854
855         /* Prepare list of attributes from tree */
856         tree_attrs = talloc_array(tmp_ctx, const char *, 1);
857         if (tree_attrs == NULL) {
858                 talloc_free(tmp_ctx);
859                 goto oom;
860         }
861         tree_attrs[0] = NULL;
862
863         /* Collect attributes from tree */
864         ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
865         if (ret) {
866                 goto done;
867         }
868
869         /* Merge attributes from search operation */
870         ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
871         if (ret) {
872                 goto done;
873         }
874
875         /* Split local from remote attributes */
876         ret = map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, tree_attrs);
877
878 done:
879         /* Free temporary memory */
880         talloc_free(tmp_ctx);
881         return ret;
882
883 oom:
884         map_oom(module);
885         return -1;
886 }
887
888
889 /* Outbound requests: search
890  * ========================= */
891
892 /* Pass a merged search result up the callback chain. */
893 int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, struct ldb_reply *ares)
894 {
895         int i;
896
897         /* No callback registered, stop */
898         if (req->callback == NULL) {
899                 return LDB_SUCCESS;
900         }
901
902         /* Only records need special treatment */
903         if (ares->type != LDB_REPLY_ENTRY) {
904                 return req->callback(ldb, req->context, ares);
905         }
906
907         /* Merged result doesn't match original query, skip */
908         if (!ldb_match_msg(ldb, ares->message, req->op.search.tree, req->op.search.base, req->op.search.scope)) {
909                 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
910                           "Skipping record '%s': "
911                           "doesn't match original search\n",
912                           ldb_dn_linearize(ldb, ares->message->dn));
913                 return LDB_SUCCESS;
914         }
915
916         /* Limit result to requested attrs */
917         if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) {
918                 for (i = 0; i < ares->message->num_elements; i++) {
919                         const struct ldb_message_element *el = &ares->message->elements[i];
920                         if (!ldb_attr_in_list(req->op.search.attrs, el->name)) {
921                                 ldb_msg_remove_attr(ares->message, el->name);
922                         }
923                 }
924         }
925
926         return req->callback(ldb, req->context, ares);
927 }
928
929 /* Merge the remote and local parts of a search result. */
930 int map_local_merge_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
931 {
932         struct map_search_context *sc;
933         int ret;
934
935         if (context == NULL || ares == NULL) {
936                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
937                                                        "NULL Context or Result in `map_local_merge_callback`"));
938                 return LDB_ERR_OPERATIONS_ERROR;
939         }
940
941         sc = talloc_get_type(context, struct map_search_context);
942
943         switch (ares->type) {
944         case LDB_REPLY_ENTRY:
945                 /* We have already found a local record */
946                 if (sc->local_res) {
947                         ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
948                                                                "Too many results to base search for local entry"));
949                         talloc_free(ares);
950                         return LDB_ERR_OPERATIONS_ERROR;
951                 }
952
953                 /* Store local result */
954                 sc->local_res = ares;
955
956                 /* Merge remote into local message */
957                 ret = ldb_msg_merge_local(sc->ac->module, ares->message, sc->remote_res->message);
958                 if (ret) {
959                         talloc_free(ares);
960                         return LDB_ERR_OPERATIONS_ERROR;
961                 }
962
963                 return map_up_callback(ldb, sc->ac->orig_req, ares);
964
965         case LDB_REPLY_DONE:
966                 /* No local record found, continue with remote record */
967                 if (sc->local_res == NULL) {
968                         return map_up_callback(ldb, sc->ac->orig_req, sc->remote_res);
969                 }
970                 return LDB_SUCCESS;
971
972         default:
973                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
974                                                        "Unexpected result type in base search for local entry"));
975                 talloc_free(ares);
976                 return LDB_ERR_OPERATIONS_ERROR;
977         }
978 }
979
980 /* Search the local part of a remote search result. */
981 int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
982 {
983         struct map_context *ac;
984         struct map_search_context *sc;
985         struct ldb_request *req;
986         int ret;
987
988         if (context == NULL || ares == NULL) {
989                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
990                                                        "NULL Context or Result in `map_remote_search_callback`"));
991                 return LDB_ERR_OPERATIONS_ERROR;
992         }
993
994         ac = talloc_get_type(context, struct map_context);
995
996         /* It's not a record, stop searching */
997         if (ares->type != LDB_REPLY_ENTRY) {
998                 return map_up_callback(ldb, ac->orig_req, ares);
999         }
1000
1001         /* Map result record into a local message */
1002         ret = map_reply_remote(ac->module, ares);
1003         if (ret) {
1004                 talloc_free(ares);
1005                 return LDB_ERR_OPERATIONS_ERROR;
1006         }
1007
1008         /* There is no local db, stop searching */
1009         if (!map_check_local_db(ac->module)) {
1010                 return map_up_callback(ldb, ac->orig_req, ares);
1011         }
1012
1013         /* Prepare local search context */
1014         sc = map_init_search_context(ac, ares);
1015         if (sc == NULL) {
1016                 talloc_free(ares);
1017                 return LDB_ERR_OPERATIONS_ERROR;
1018         }
1019
1020         /* Prepare local search request */
1021         /* TODO: use GUIDs here instead? */
1022
1023         ac->search_reqs = talloc_realloc(ac, ac->search_reqs, struct ldb_request *, ac->num_searches + 2);
1024         if (ac->search_reqs == NULL) {
1025                 talloc_free(ares);
1026                 return LDB_ERR_OPERATIONS_ERROR;
1027         }
1028
1029         ac->search_reqs[ac->num_searches]
1030                 = req = map_search_base_req(ac, ares->message->dn, 
1031                                             NULL, NULL, sc, map_local_merge_callback);
1032         if (req == NULL) {
1033                 talloc_free(sc);
1034                 talloc_free(ares);
1035                 return LDB_ERR_OPERATIONS_ERROR;
1036         }
1037         ac->num_searches++;
1038         ac->search_reqs[ac->num_searches] = NULL;
1039
1040         return ldb_next_request(ac->module, req);
1041 }
1042
1043 /* Search a record. */
1044 int map_search(struct ldb_module *module, struct ldb_request *req)
1045 {
1046         struct ldb_handle *h;
1047         struct map_context *ac;
1048         struct ldb_parse_tree *local_tree, *remote_tree;
1049         const char **local_attrs, **remote_attrs;
1050         int ret;
1051
1052         const char *wildcard[] = { "*", NULL };
1053         const char * const *attrs;
1054
1055         /* Do not manipulate our control entries */
1056         if (ldb_dn_is_special(req->op.search.base))
1057                 return ldb_next_request(module, req);
1058
1059         /* No mapping requested, skip to next module */
1060         if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1061                 return ldb_next_request(module, req);
1062         }
1063
1064         /* TODO: How can we be sure about which partition we are
1065          *       targetting when there is no search base? */
1066
1067         /* Prepare context and handle */
1068         h = map_init_handle(req, module);
1069         if (h == NULL) {
1070                 return LDB_ERR_OPERATIONS_ERROR;
1071         }
1072         ac = talloc_get_type(h->private_data, struct map_context);
1073
1074         ac->search_reqs = talloc_array(ac, struct ldb_request *, 2);
1075         if (ac->search_reqs == NULL) {
1076                 talloc_free(h);
1077                 return LDB_ERR_OPERATIONS_ERROR;
1078         }
1079         ac->num_searches = 1;
1080         ac->search_reqs[1] = NULL;
1081
1082         /* Prepare the remote operation */
1083         ac->search_reqs[0] = talloc(ac, struct ldb_request);
1084         if (ac->search_reqs[0] == NULL) {
1085                 goto oom;
1086         }
1087
1088         *(ac->search_reqs[0]) = *req;   /* copy the request */
1089
1090         ac->search_reqs[0]->handle = h; /* return our own handle to deal with this call */
1091
1092         ac->search_reqs[0]->context = ac;
1093         ac->search_reqs[0]->callback = map_remote_search_callback;
1094
1095         /* It is easier to deal with the two different ways of
1096          * expressing the wildcard in the same codepath */
1097         attrs = req->op.search.attrs;
1098         if (attrs == NULL) {
1099                 attrs = wildcard;
1100         }
1101
1102         /* Split local from remote attrs */
1103         ret = map_attrs_collect_and_partition(module, ac, ac->search_reqs[0], &local_attrs, &remote_attrs, attrs, req->op.search.tree);
1104         if (ret) {
1105                 goto failed;
1106         }
1107
1108         ac->local_attrs = local_attrs;
1109         ac->search_reqs[0]->op.search.attrs = remote_attrs;
1110
1111         /* Split local from remote tree */
1112         ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], &local_tree, &remote_tree, req->op.search.tree);
1113         if (ret) {
1114                 goto failed;
1115         }
1116
1117         if (((local_tree != NULL) && (remote_tree != NULL)) &&
1118             (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1119                 /* The query can't safely be split, enumerate the remote partition */
1120                 local_tree = NULL;
1121                 remote_tree = NULL;
1122         }
1123
1124         if (local_tree == NULL) {
1125                 /* Construct default local parse tree */
1126                 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1127                 if (local_tree == NULL) {
1128                         map_oom(ac->module);
1129                         goto failed;
1130                 }
1131
1132                 local_tree->operation = LDB_OP_PRESENT;
1133                 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1134         }
1135         if (remote_tree == NULL) {
1136                 /* Construct default remote parse tree */
1137                 remote_tree = ldb_parse_tree(ac->search_reqs[0], NULL);
1138                 if (remote_tree == NULL) {
1139                         goto failed;
1140                 }
1141         }
1142
1143         ac->local_tree = local_tree;
1144         ac->search_reqs[0]->op.search.tree = remote_tree;
1145
1146         ldb_set_timeout_from_prev_req(module->ldb, req, ac->search_reqs[0]);
1147
1148         h->state = LDB_ASYNC_INIT;
1149         h->status = LDB_SUCCESS;
1150
1151         ac->step = MAP_SEARCH_REMOTE;
1152
1153         ret = ldb_next_remote_request(module, ac->search_reqs[0]);
1154         if (ret == LDB_SUCCESS) {
1155                 req->handle = h;
1156         }
1157         return ret;
1158
1159 oom:
1160         map_oom(module);
1161 failed:
1162         talloc_free(h);
1163         return LDB_ERR_OPERATIONS_ERROR;
1164 }