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