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