2 ldb database library - map backend
4 Copyright (C) Jelmer Vernooij 2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "ldb/include/ldb.h"
27 #include "ldb/include/ldb_private.h"
28 #include "ldb/modules/ldb_map.h"
31 * - map_message_outgoing() should:
32 * - modify: not worry about anything simply map and hope everything
34 * - make a list of remote objectclasses that will be used
35 * given the attributes that are available
36 * - only add attribute to the remote message if
37 * it is allowed by the objectclass
42 - special attribute 'isMapped'
44 - split up ldb_message into fallback and mapped parts if is_mappable
46 - search local one for not isMapped entries
47 - remove remote attributes from ldb_parse_tree
49 - per record, search local one for additional data (by dn)
50 - test if (full expression) is now true
54 - rename locally and remotely
57 static struct ldb_val map_convert_local_dn(struct ldb_module *map,
59 const struct ldb_val *val);
60 static struct ldb_val map_convert_remote_dn(struct ldb_module *map,
62 const struct ldb_val *val);
63 static struct ldb_val map_convert_local_objectclass(struct ldb_module *map,
65 const struct ldb_val *val);
66 static struct ldb_val map_convert_remote_objectclass(struct ldb_module *map,
68 const struct ldb_val *val);
70 static const struct ldb_map_attribute builtin_attribute_maps[] = {
77 .convert_local = map_convert_local_dn,
78 .convert_remote = map_convert_remote_dn,
83 .local_name = "objectclass",
87 .remote_name = "objectclass",
88 .convert_local = map_convert_local_objectclass,
89 .convert_remote = map_convert_remote_objectclass,
99 struct ldb_map_context context;
100 const char *last_err_string;
103 static struct ldb_map_context *map_get_privdat(struct ldb_module *module)
105 return &((struct map_private *)module->private_data)->context;
108 static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name)
111 for (i = 0; privdat->objectclass_maps[i].local_name; i++) {
112 if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name))
113 return &privdat->objectclass_maps[i];
119 /* Decide whether a add/modify should be pushed to the
120 * remote LDAP server. We currently only do this if we see an objectClass we know */
121 static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg)
124 struct ldb_message_element *el;
126 if (ldb_dn_is_special(msg->dn))
129 el = ldb_msg_find_element(msg, "objectClass");
131 /* No objectClass... */
136 for (i = 0; i < el->num_values; i++) {
137 if (map_find_objectclass_local(privdat, (char *)el->values[i].data))
144 /* find an attribute by the local name */
145 static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr)
149 for (i = 0; privdat->attribute_maps[i].local_name; i++) {
150 if (!ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr))
151 return &privdat->attribute_maps[i];
157 /* find an attribute by the remote name */
158 static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr)
162 for (i = 0; privdat->attribute_maps[i].local_name; i++) {
163 if (privdat->attribute_maps[i].type == MAP_IGNORE)
166 if (privdat->attribute_maps[i].type == MAP_GENERATE)
169 if (privdat->attribute_maps[i].type == MAP_KEEP &&
170 ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr) == 0)
171 return &privdat->attribute_maps[i];
173 if ((privdat->attribute_maps[i].type == MAP_RENAME ||
174 privdat->attribute_maps[i].type == MAP_CONVERT) &&
175 ldb_attr_cmp(privdat->attribute_maps[i].u.rename.remote_name, attr) == 0)
176 return &privdat->attribute_maps[i];
183 static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_parse_tree *tree)
186 const struct ldb_map_attribute *attr;
187 struct ldb_parse_tree *new_tree;
188 enum ldb_map_attr_type map_type;
189 struct ldb_val value, newvalue;
190 struct ldb_map_context *privdat = map_get_privdat(module);
196 /* Find attr in question and:
197 * - if it has a convert_operator function, run that
198 * - otherwise, replace attr name with required[0] */
200 if (tree->operation == LDB_OP_AND ||
201 tree->operation == LDB_OP_OR) {
203 new_tree = talloc_memdup(ctx, tree, sizeof(*tree));
204 new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements);
205 new_tree->u.list.num_elements = 0;
206 for (i = 0; i < tree->u.list.num_elements; i++) {
207 struct ldb_parse_tree *child = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]);
210 new_tree->u.list.elements[i] = child;
211 new_tree->u.list.num_elements++;
218 if (tree->operation == LDB_OP_NOT) {
219 struct ldb_parse_tree *child;
221 new_tree = talloc_memdup(ctx, tree, sizeof(*tree));
222 child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child);
225 talloc_free(new_tree);
229 new_tree->u.isnot.child = child;
233 /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER,
234 * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED
236 * (all have attr as the first element)
239 attr = map_find_attr_local(privdat, tree->u.equality.attr);
242 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Unable to find local attribute '%s', removing from parse tree\n", tree->u.equality.attr);
243 map_type = MAP_IGNORE;
245 map_type = attr->type;
248 if (attr && attr->convert_operator) {
249 /* Run convert_operator */
250 return attr->convert_operator(privdat, module, tree);
253 if (map_type == MAP_IGNORE) {
254 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Not mapping search on ignored attribute '%s'\n", tree->u.equality.attr);
258 if (map_type == MAP_GENERATE) {
259 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr);
263 if (tree->operation == LDB_OP_EQUALITY) {
264 value = tree->u.equality.value;
265 } else if (tree->operation == LDB_OP_LESS || tree->operation == LDB_OP_GREATER ||
266 tree->operation == LDB_OP_APPROX) {
267 value = tree->u.comparison.value;
268 } else if (tree->operation == LDB_OP_EXTENDED) {
269 value = tree->u.extended.value;
272 new_tree = talloc_memdup(ctx, tree, sizeof(*tree));
274 if (map_type == MAP_KEEP) {
275 new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr);
276 } else { /* MAP_RENAME / MAP_CONVERT */
277 new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name);
280 if (new_tree->operation == LDB_OP_PRESENT)
283 if (new_tree->operation == LDB_OP_SUBSTRING) {
284 new_tree->u.substring.chunks = NULL; /* FIXME! */
288 if (map_type == MAP_CONVERT) {
289 newvalue = attr->u.convert.convert_local(module, new_tree, &value);
291 newvalue = ldb_val_dup(new_tree, &value);
294 if (new_tree->operation == LDB_OP_EQUALITY) {
295 new_tree->u.equality.value = newvalue;
296 } else if (new_tree->operation == LDB_OP_LESS || new_tree->operation == LDB_OP_GREATER ||
297 new_tree->operation == LDB_OP_APPROX) {
298 new_tree->u.comparison.value = newvalue;
299 } else if (new_tree->operation == LDB_OP_EXTENDED) {
300 new_tree->u.extended.value = newvalue;
301 new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id);
307 /* Remote DN -> Local DN */
308 static struct ldb_dn *map_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn)
310 struct ldb_dn *newdn;
316 newdn = talloc_memdup(ctx, dn, sizeof(*dn));
320 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
322 if (!newdn->components)
325 /* For each rdn, map the attribute name and possibly the
328 for (i = 0; i < dn->comp_num; i++) {
329 const struct ldb_map_attribute *attr = map_find_attr_remote(module->private_data, dn->components[i].name);
330 enum ldb_map_attr_type map_type;
332 /* Unknown attribute - leave this dn as is and hope the best... */
333 if (!attr) map_type = MAP_KEEP;
334 else map_type = attr->type;
339 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name);
344 newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name);
345 newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value);
349 newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name);
350 newdn->components[i].value = attr->u.convert.convert_remote(module, ctx, &dn->components[i].value);
354 newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name);
355 newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value);
362 /* Local DN -> Remote DN */
363 static struct ldb_dn *map_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn)
365 struct ldb_dn *newdn;
371 newdn = talloc_memdup(ctx, dn, sizeof(*dn));
375 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
377 if (!newdn->components)
380 /* For each rdn, map the attribute name and possibly the
381 * complete rdn using an equality convert_operator call */
383 for (i = 0; i < dn->comp_num; i++) {
384 const struct ldb_map_attribute *attr = map_find_attr_local(module->private_data, dn->components[i].name);
385 enum ldb_map_attr_type map_type;
387 /* Unknown attribute - leave this dn as is and hope the best... */
388 if (!attr) map_type = MAP_KEEP; else map_type = attr->type;
394 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name);
399 newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name);
400 newdn->components[i].value = attr->u.convert.convert_local(module, newdn->components, &dn->components[i].value);
404 newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name);
405 newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value);
409 newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name);
410 newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value);
418 /* Loop over ldb_map_attribute array and add remote_names */
419 static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[])
423 int ar_size = 0, last_element = 0;
424 struct ldb_map_context *privdat = map_get_privdat(module);
429 /* Start with good guess of number of elements */
430 for (i = 0; attrs[i]; i++);
432 ret = talloc_array(module, const char *, i);
435 for (i = 0; attrs[i]; i++) {
437 const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]);
438 enum ldb_map_attr_type map_type;
441 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]);
442 map_type = MAP_IGNORE;
443 } else map_type = attr->type;
447 case MAP_IGNORE: break;
449 if (last_element >= ar_size) {
450 ret = talloc_realloc(module, ret, const char *, ar_size+1);
453 ret[last_element] = attr->local_name;
459 if (last_element >= ar_size) {
460 ret = talloc_realloc(module, ret, const char *, ar_size+1);
463 ret[last_element] = attr->u.rename.remote_name;
468 /* Add remote_names[] for this attribute to the list of
469 * attributes to request from the remote server */
470 for (j = 0; attr->u.generate.remote_names[j]; j++) {
471 if (last_element >= ar_size) {
472 ret = talloc_realloc(module, ret, const char *, ar_size+1);
475 ret[last_element] = attr->u.generate.remote_names[j];
482 if (last_element >= ar_size) {
483 ret = talloc_realloc(module, ret, const char *, ar_size+1);
487 ret[last_element] = NULL;
492 static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg)
494 struct ldb_map_context *privdat = map_get_privdat(module);
497 const char **ret = talloc_array(module, const char *, 1);
501 for (i = 0; privdat->attribute_maps[i].local_name; i++) {
503 const struct ldb_map_attribute *attr = &privdat->attribute_maps[i];
505 /* If all remote attributes for this attribute are present, add the
506 * local one to the list */
508 switch (attr->type) {
509 case MAP_IGNORE: break;
511 avail = (ldb_msg_find_ldb_val(msg, attr->local_name) != NULL);
516 avail = (ldb_msg_find_ldb_val(msg, attr->u.rename.remote_name) != NULL);
521 for (j = 0; attr->u.generate.remote_names[j]; j++) {
522 avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL);
530 ret = talloc_realloc(module, ret, const char *, count+2);
531 ret[count] = attr->local_name;
539 /* Used for search */
540 static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi)
543 struct ldb_message *msg = talloc_zero(module, struct ldb_message);
544 struct ldb_message_element *elm, *oldelm;
545 struct ldb_map_context *privdat = map_get_privdat(module);
546 const char **newattrs = NULL;
548 msg->dn = map_remote_dn(module, module, mi->dn);
550 ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn));
552 /* Loop over attrs, find in ldb_map_attribute array and
556 /* Generate list of the local attributes that /can/ be generated
557 * using the specific remote attributes */
559 attrs = newattrs = available_local_attributes(module, mi);
562 for (i = 0; attrs[i]; i++) {
563 const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]);
564 enum ldb_map_attr_type map_type;
567 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s' when generating incoming message\n", attrs[i]);
568 map_type = MAP_IGNORE;
569 } else map_type = attr->type;
572 case MAP_IGNORE:break;
574 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Renaming remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name);
575 oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name);
579 elm = talloc(msg, struct ldb_message_element);
580 elm->name = talloc_strdup(elm, attr->local_name);
581 elm->num_values = oldelm->num_values;
582 elm->values = talloc_array(elm, struct ldb_val, elm->num_values);
583 for (j = 0; j < oldelm->num_values; j++)
584 elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]);
586 ldb_msg_add(module->ldb, msg, elm, oldelm->flags);
590 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name);
591 oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name);
595 elm = talloc(msg, struct ldb_message_element);
596 elm->name = talloc_strdup(elm, attr->local_name);
597 elm->num_values = oldelm->num_values;
598 elm->values = talloc_array(elm, struct ldb_val, elm->num_values);
600 for (j = 0; j < oldelm->num_values; j++)
601 elm->values[j] = attr->u.convert.convert_remote(module, elm, &oldelm->values[j]);
603 ldb_msg_add(module->ldb, msg, elm, oldelm->flags);
607 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping remote attribute %s", attr->local_name);
608 oldelm = ldb_msg_find_element(mi, attr->local_name);
609 if (!oldelm) continue;
611 elm = talloc(msg, struct ldb_message_element);
613 elm->num_values = oldelm->num_values;
614 elm->values = talloc_array(elm, struct ldb_val, elm->num_values);
615 for (j = 0; j < oldelm->num_values; j++)
616 elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]);
618 elm->name = talloc_strdup(elm, oldelm->name);
620 ldb_msg_add(module->ldb, msg, elm, oldelm->flags);
624 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating local attribute %s", attr->local_name);
625 elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi);
628 ldb_msg_add(module->ldb, msg, elm, elm->flags);
631 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name);
636 talloc_free(newattrs);
641 /* Used for add, modify */
642 static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp)
644 struct ldb_map_context *privdat = map_get_privdat(module);
645 struct ldb_message_element *elm;
648 *fb = talloc_zero(module, struct ldb_message);
649 (*fb)->dn = talloc_reference(*fb, mo->dn);
651 *mp = talloc_zero(module, struct ldb_message);
652 (*mp)->dn = map_local_dn(module, module, mo->dn);
654 /* Loop over mi and call generate_remote for each attribute */
655 for (i = 0; i < mo->num_elements; i++) {
656 const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name);
657 enum ldb_map_attr_type map_type;
660 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name);
661 map_type = MAP_IGNORE;
663 } else map_type = attr->type;
666 case MAP_IGNORE: /* Add to fallback message */
667 elm = talloc(*fb, struct ldb_message_element);
669 elm->num_values = mo->elements[i].num_values;
670 elm->values = talloc_reference(elm, mo->elements[i].values);
671 elm->name = talloc_strdup(elm, mo->elements[i].name);
673 ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags);
676 elm = talloc(*mp, struct ldb_message_element);
678 elm->name = talloc_strdup(elm, attr->u.rename.remote_name);
679 elm->num_values = mo->elements[i].num_values;
680 elm->values = talloc_reference(elm, mo->elements[i].values);
682 ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags);
686 elm = talloc(*mp, struct ldb_message_element);
688 elm->name = talloc_strdup(elm, attr->u.rename.remote_name);
689 elm->num_values = mo->elements[i].num_values;
690 elm->values = talloc_array(elm, struct ldb_val, elm->num_values);
692 for (j = 0; j < elm->num_values; j++) {
693 elm->values[j] = attr->u.convert.convert_local(module, *mp, &mo->elements[i].values[j]);
696 ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags);
700 elm = talloc(*mp, struct ldb_message_element);
702 elm->num_values = mo->elements[i].num_values;
703 elm->values = talloc_reference(elm, mo->elements[i].values);
704 elm->name = talloc_strdup(elm, mo->elements[i].name);
706 ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags);
710 attr->u.generate.generate_remote(module, attr->local_name, mo, *mp);
715 if ((*fb)->num_elements == 0) {
716 ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE");
719 if ((*mp)->num_elements == 0) {
720 /* No elements, discard.. */
732 static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
734 struct ldb_map_context *privdat = map_get_privdat(module);
735 struct ldb_dn *n_olddn, *n_newdn;
738 n_olddn = map_local_dn(module, module, olddn);
739 n_newdn = map_local_dn(module, module, newdn);
741 mp_ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn);
743 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed");
746 fb_ret = ldb_next_rename_record(module, olddn, newdn);
749 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed");
752 talloc_free(n_olddn);
753 talloc_free(n_newdn);
755 return (fb_ret == -1 && mp_ret == -1)?-1:0;
761 static int map_delete(struct ldb_module *module, const struct ldb_dn *dn)
763 struct ldb_map_context *privdat = map_get_privdat(module);
764 struct ldb_dn *newdn;
767 newdn = map_local_dn(module, module, dn);
769 mp_ret = ldb_delete(privdat->mapped_ldb, newdn);
771 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted");
774 fb_ret = ldb_next_delete_record(module, dn);
776 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted");
781 return (fb_ret == -1 && mp_ret == -1)?-1:0;
784 /* search fallback database */
785 static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base,
786 enum ldb_scope scope, struct ldb_parse_tree *tree,
787 const char * const *attrs, struct ldb_message ***res)
790 struct ldb_parse_tree t_and, t_not, t_present, *childs[2];
792 t_present.operation = LDB_OP_PRESENT;
793 t_present.u.present.attr = talloc_strdup(NULL, "isMapped");
795 t_not.operation = LDB_OP_NOT;
796 t_not.u.isnot.child = &t_present;
800 t_and.operation = LDB_OP_AND;
801 t_and.u.list.num_elements = 2;
802 t_and.u.list.elements = childs;
804 ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res);
806 talloc_free(t_present.u.present.attr);
811 /* Search in the database against which we are mapping */
812 static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base,
813 enum ldb_scope scope, struct ldb_parse_tree *tree,
814 const char * const *attrs, struct ldb_message ***res)
816 struct ldb_parse_tree *new_tree;
817 struct ldb_dn *new_base;
818 struct ldb_message **newres;
819 const char **newattrs;
821 struct ldb_map_context *privdat = map_get_privdat(module);
824 /*- search mapped database */
826 new_tree = ldb_map_parse_tree(module, module, tree);
827 if (new_tree == NULL) {
828 /* All attributes used in the parse tree are
829 * local, apparently. Fall back to enumerating the complete remote
830 * database... Rather a slow search then no results. */
831 new_tree = talloc_zero(module, struct ldb_parse_tree);
832 new_tree->operation = LDB_OP_PRESENT;
833 new_tree->u.present.attr = talloc_strdup(new_tree, "dn");
837 newattrs = ldb_map_attrs(module, attrs);
838 new_base = map_local_dn(module, module, base);
840 mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres);
842 talloc_free(new_base);
843 talloc_free(new_tree);
844 talloc_free(newattrs);
847 struct map_private *map_private = module->private_data;
848 map_private->last_err_string = ldb_errstring(privdat->mapped_ldb);
853 - per returned record, search fallback database for additional data (by dn)
854 - test if (full expression) is now true
857 *res = talloc_array(module, struct ldb_message *, mpret);
861 for (i = 0; i < mpret; i++) {
862 struct ldb_message *merged;
863 struct ldb_message **extrares = NULL;
866 /* Always get special DN's from the fallback database */
867 if (ldb_dn_is_special(newres[i]->dn))
870 merged = ldb_map_message_incoming(module, attrs, newres[i]);
872 /* Merge with additional data from local database */
873 extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares);
875 if (extraret == -1) {
876 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n");
877 } else if (extraret > 1) {
878 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More than one result for extra data!\n");
881 } else if (extraret == 0) {
882 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn));
887 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn));
888 for (j = 0; j < extrares[0]->num_elements; j++) {
889 ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags);
892 ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE");
894 ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE");
897 if (ldb_match_msg(module->ldb, merged, tree, base, scope) != 0) {
898 (*res)[ret] = merged;
901 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match");
912 search for matching records using a ldb_parse_tree
914 static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
915 enum ldb_scope scope, struct ldb_parse_tree *tree,
916 const char * const *attrs, struct ldb_message ***res)
918 struct ldb_message **fbres, **mpres;
922 ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres);
926 /* special dn's are never mapped.. */
927 if (ldb_dn_is_special(base)) {
932 ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres);
938 *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp);
940 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Merging %d mapped and %d fallback messages", ret_mp, ret_fb);
942 for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i];
943 for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i];
945 return ret_fb + ret_mp;
948 search for matching records
950 static int map_search(struct ldb_module *module, const struct ldb_dn *base,
951 enum ldb_scope scope, const char *expression,
952 const char * const *attrs, struct ldb_message ***res)
954 struct map_private *map = module->private_data;
955 struct ldb_parse_tree *tree;
958 tree = ldb_parse_tree(NULL, expression);
960 map->last_err_string = "expression parse failed";
964 ret = map_search_bytree(module, base, scope, tree, attrs, res);
972 static int map_add(struct ldb_module *module, const struct ldb_message *msg)
975 struct ldb_map_context *privdat = map_get_privdat(module);
976 struct ldb_message *fb, *mp;
978 if (!map_is_mappable(privdat, msg)) {
979 return ldb_next_add_record(module, msg);
982 if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1)
986 ret = ldb_next_add_record(module, fb);
988 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed");
996 ret = ldb_add(privdat->mapped_ldb, mp);
998 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed");
1012 static int map_modify(struct ldb_module *module, const struct ldb_message *msg)
1014 struct ldb_map_context *privdat = map_get_privdat(module);
1015 struct ldb_message *fb, *mp;
1018 if (!map_is_mappable(privdat, msg))
1019 return ldb_next_modify_record(module, msg);
1021 if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1)
1025 ret = ldb_next_modify_record(module, fb);
1030 ret = ldb_modify(privdat->mapped_ldb, mp);
1037 static int map_lock(struct ldb_module *module, const char *lockname)
1039 return ldb_next_named_lock(module, lockname);
1042 static int map_unlock(struct ldb_module *module, const char *lockname)
1044 return ldb_next_named_unlock(module, lockname);
1048 return extended error information
1050 static const char *map_errstring(struct ldb_module *module)
1052 struct map_private *map = module->private_data;
1054 if (map->last_err_string)
1055 return map->last_err_string;
1057 return ldb_next_errstring(module);
1060 static const struct ldb_module_ops map_ops = {
1062 .search = map_search,
1063 .search_bytree = map_search_bytree,
1064 .add_record = map_add,
1065 .modify_record = map_modify,
1066 .delete_record = map_delete,
1067 .rename_record = map_rename,
1068 .named_lock = map_lock,
1069 .named_unlock = map_unlock,
1070 .errstring = map_errstring
1073 static char *map_find_url(struct ldb_context *ldb, const char *name)
1075 const char * const attrs[] = { "@MAP_URL" , NULL};
1076 struct ldb_message **msg = NULL;
1077 struct ldb_dn *mods;
1081 mods = ldb_dn_string_compose(ldb, NULL, "@MAP=%s", name);
1083 ldb_debug(ldb, LDB_DEBUG_ERROR, "Can't construct DN");
1087 ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg);
1090 ldb_debug(ldb, LDB_DEBUG_ERROR, "Not enough results found looking for @MAP");
1094 url = talloc_strdup(ldb, ldb_msg_find_string(msg[0], "@MAP_URL", NULL));
1101 /* the init function */
1102 struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name)
1105 struct ldb_module *ctx;
1106 struct map_private *data;
1109 ctx = talloc(ldb, struct ldb_module);
1113 data = talloc(ctx, struct map_private);
1119 data->context.mapped_ldb = ldb_init(data);
1120 ldb_set_debug(data->context.mapped_ldb, ldb->debug_ops.debug, ldb->debug_ops.context);
1121 url = map_find_url(ldb, name);
1124 ldb_debug(ldb, LDB_DEBUG_FATAL, "@MAP=%s not set!\n", name);
1128 if (ldb_connect(data->context.mapped_ldb, url, 0, NULL) != 0) {
1129 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to open mapped database for %s at '%s'\n", name, url);
1135 data->last_err_string = NULL;
1137 /* Get list of attribute maps */
1139 data->context.attribute_maps = NULL;
1141 for (i = 0; attrs[i].local_name; i++) {
1142 data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1);
1143 data->context.attribute_maps[j] = attrs[i];
1147 for (i = 0; builtin_attribute_maps[i].local_name; i++) {
1148 data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1);
1149 data->context.attribute_maps[j] = builtin_attribute_maps[i];
1153 data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1);
1154 memset(&data->context.attribute_maps[j], 0, sizeof(struct ldb_map_attribute));
1156 data->context.objectclass_maps = ocls;
1157 ctx->private_data = data;
1159 ctx->prev = ctx->next = NULL;
1160 ctx->ops = &map_ops;
1165 static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
1167 struct ldb_dn *dn, *newdn;
1168 struct ldb_val *newval;
1170 dn = ldb_dn_explode(ctx, (char *)val->data);
1172 newdn = map_local_dn(module, ctx, dn);
1176 newval = talloc(ctx, struct ldb_val);
1177 newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn);
1178 newval->length = strlen((char *)newval->data);
1185 static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
1187 struct ldb_dn *dn, *newdn;
1188 struct ldb_val *newval;
1190 dn = ldb_dn_explode(ctx, (char *)val->data);
1192 newdn = map_remote_dn(module, ctx, dn);
1196 newval = talloc(ctx, struct ldb_val);
1197 newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn);
1198 newval->length = strlen((char *)newval->data);
1205 static struct ldb_val map_convert_local_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
1208 struct ldb_map_context *map = module->private_data;
1210 for (i = 0; map->objectclass_maps[i].local_name; i++) {
1211 if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) {
1212 struct ldb_val newval;
1213 newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].remote_name);
1214 newval.length = strlen((char *)newval.data);
1216 return ldb_val_dup(ctx, &newval);
1220 return ldb_val_dup(ctx, val);
1223 static struct ldb_val map_convert_remote_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
1226 struct ldb_map_context *map = module->private_data;
1228 for (i = 0; map->objectclass_maps[i].remote_name; i++) {
1229 if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) {
1230 struct ldb_val newval;
1231 newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].local_name);
1232 newval.length = strlen((char *)newval.data);
1234 return ldb_val_dup(ctx, &newval);
1238 return ldb_val_dup(ctx, val);