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