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/includes.h"
28 #include "ldb/modules/ldb_map.h"
31 - special attribute 'isMapped'
33 - split up ldb_message into fallback and mapped parts if is_mappable
35 - search local one for not isMapped entries
36 - remove remote attributes from ldb_parse_tree
38 - per record, search local one for additional data (by dn)
39 - test if (full expression) is now true
43 - rename locally and remotely
46 static struct ldb_val
map_convert_local_dn(struct ldb_module
*map
,
48 const struct ldb_val
*val
);
49 static struct ldb_val
map_convert_remote_dn(struct ldb_module
*map
,
51 const struct ldb_val
*val
);
52 static struct ldb_val
map_convert_local_objectclass(struct ldb_module
*map
,
54 const struct ldb_val
*val
);
55 static struct ldb_val
map_convert_remote_objectclass(struct ldb_module
*map
,
57 const struct ldb_val
*val
);
59 static const struct ldb_map_attribute builtin_attribute_maps
[] = {
66 .convert_local
= map_convert_local_dn
,
67 .convert_remote
= map_convert_remote_dn
,
72 .local_name
= "objectclass",
76 .remote_name
= "objectclass",
77 .convert_local
= map_convert_local_objectclass
,
78 .convert_remote
= map_convert_remote_objectclass
,
87 static const struct ldb_map_objectclass
*map_find_objectclass_remote(struct ldb_map_context
*privdat
, const char *name
)
90 for (i
= 0; privdat
->objectclass_maps
[i
].remote_name
; i
++) {
91 if (!ldb_attr_cmp(privdat
->objectclass_maps
[i
].remote_name
, name
))
92 return &privdat
->objectclass_maps
[i
];
99 struct ldb_map_context context
;
102 static struct ldb_map_context
*map_get_privdat(struct ldb_module
*module
)
104 return &((struct map_private
*)module
->private_data
)->context
;
107 /* Check whether the given attribute can fit into the specified
108 * message, obeying objectClass restrictions */
109 static int map_msg_valid_attr(struct ldb_module
*module
, const struct ldb_message
*msg
, const char *attr
)
111 struct ldb_map_context
*map
= module
->private_data
;
113 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, "objectClass");
116 ldb_debug(module
->ldb
, LDB_DEBUG_FATAL
, "Can't find objectClass");
120 for (i
= 0; i
< el
->num_values
; i
++) {
121 const struct ldb_map_objectclass
*class = map_find_objectclass_remote(map
, (char *)el
->values
[i
].data
);
126 for (j
= 0; class->musts
[j
]; j
++) {
127 if (!ldb_attr_cmp(class->musts
[j
], attr
))
131 for (j
= 0; class->mays
[j
]; j
++) {
132 if (!ldb_attr_cmp(class->mays
[j
], attr
))
141 /* find an attribute by the local name */
142 static const struct ldb_map_attribute
*map_find_attr_local(struct ldb_map_context
*privdat
, const char *attr
)
146 for (i
= 0; privdat
->attribute_maps
[i
].local_name
; i
++) {
147 if (!ldb_attr_cmp(privdat
->attribute_maps
[i
].local_name
, attr
))
148 return &privdat
->attribute_maps
[i
];
154 /* Check if a given attribute can be created by doing mapping from a local attribute to a remote one */
155 static int map_msg_can_map_attr(struct ldb_module
*module
, const struct ldb_message
*msg
, const char *attr_name
)
157 struct ldb_map_context
*privdat
= module
->private_data
;
160 for (i
= 0; privdat
->attribute_maps
[i
].local_name
; i
++) {
161 switch (privdat
->attribute_maps
[i
].type
) {
162 case MAP_IGNORE
: /* No remote name at all */
165 if (ldb_attr_cmp(attr_name
, privdat
->attribute_maps
[i
].local_name
) == 0)
170 if (ldb_attr_cmp(attr_name
, privdat
->attribute_maps
[i
].u
.rename
.remote_name
) == 0)
174 for (j
= 0; privdat
->attribute_maps
[i
].u
.generate
.remote_names
[j
]; j
++) {
175 if (ldb_attr_cmp(attr_name
, privdat
->attribute_maps
[i
].u
.generate
.remote_names
[j
]) == 0)
186 if (ldb_msg_find_element(msg
, privdat
->attribute_maps
[i
].local_name
))
194 /* find an attribute by the remote name */
195 static const struct ldb_map_attribute
*map_find_attr_remote(struct ldb_map_context
*privdat
, const char *attr
)
199 for (i
= 0; privdat
->attribute_maps
[i
].local_name
; i
++) {
200 if (privdat
->attribute_maps
[i
].type
== MAP_IGNORE
)
203 if (privdat
->attribute_maps
[i
].type
== MAP_GENERATE
)
206 if (privdat
->attribute_maps
[i
].type
== MAP_KEEP
&&
207 ldb_attr_cmp(privdat
->attribute_maps
[i
].local_name
, attr
) == 0)
208 return &privdat
->attribute_maps
[i
];
210 if ((privdat
->attribute_maps
[i
].type
== MAP_RENAME
||
211 privdat
->attribute_maps
[i
].type
== MAP_CONVERT
) &&
212 ldb_attr_cmp(privdat
->attribute_maps
[i
].u
.rename
.remote_name
, attr
) == 0)
213 return &privdat
->attribute_maps
[i
];
220 static struct ldb_parse_tree
*ldb_map_parse_tree(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_parse_tree
*tree
)
223 const struct ldb_map_attribute
*attr
;
224 struct ldb_parse_tree
*new_tree
;
225 enum ldb_map_attr_type map_type
;
226 struct ldb_val value
, newvalue
;
227 struct ldb_map_context
*privdat
= map_get_privdat(module
);
233 /* Find attr in question and:
234 * - if it has a convert_operator function, run that
235 * - otherwise, replace attr name with required[0] */
237 if (tree
->operation
== LDB_OP_AND
||
238 tree
->operation
== LDB_OP_OR
) {
240 new_tree
= talloc_memdup(ctx
, tree
, sizeof(*tree
));
241 new_tree
->u
.list
.elements
= talloc_array(new_tree
, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
242 new_tree
->u
.list
.num_elements
= 0;
243 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
244 struct ldb_parse_tree
*child
= ldb_map_parse_tree(module
, new_tree
, tree
->u
.list
.elements
[i
]);
247 new_tree
->u
.list
.elements
[i
] = child
;
248 new_tree
->u
.list
.num_elements
++;
255 if (tree
->operation
== LDB_OP_NOT
) {
256 struct ldb_parse_tree
*child
;
258 new_tree
= talloc_memdup(ctx
, tree
, sizeof(*tree
));
259 child
= ldb_map_parse_tree(module
, new_tree
, tree
->u
.isnot
.child
);
262 talloc_free(new_tree
);
266 new_tree
->u
.isnot
.child
= child
;
270 /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER,
271 * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED
273 * (all have attr as the first element)
276 attr
= map_find_attr_local(privdat
, tree
->u
.equality
.attr
);
279 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Unable to find local attribute '%s', removing from parse tree\n", tree
->u
.equality
.attr
);
280 map_type
= MAP_IGNORE
;
282 map_type
= attr
->type
;
285 if (attr
&& attr
->convert_operator
) {
286 /* Run convert_operator */
287 return attr
->convert_operator(privdat
, module
, tree
);
290 if (map_type
== MAP_IGNORE
) {
291 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Not mapping search on ignored attribute '%s'\n", tree
->u
.equality
.attr
);
295 if (map_type
== MAP_GENERATE
) {
296 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
);
300 if (tree
->operation
== LDB_OP_EQUALITY
) {
301 value
= tree
->u
.equality
.value
;
302 } else if (tree
->operation
== LDB_OP_LESS
|| tree
->operation
== LDB_OP_GREATER
||
303 tree
->operation
== LDB_OP_APPROX
) {
304 value
= tree
->u
.comparison
.value
;
305 } else if (tree
->operation
== LDB_OP_EXTENDED
) {
306 value
= tree
->u
.extended
.value
;
309 new_tree
= talloc_memdup(ctx
, tree
, sizeof(*tree
));
311 if (map_type
== MAP_KEEP
) {
312 new_tree
->u
.equality
.attr
= talloc_strdup(new_tree
, tree
->u
.equality
.attr
);
313 } else { /* MAP_RENAME / MAP_CONVERT */
314 new_tree
->u
.equality
.attr
= talloc_strdup(new_tree
, attr
->u
.rename
.remote_name
);
317 if (new_tree
->operation
== LDB_OP_PRESENT
)
320 if (new_tree
->operation
== LDB_OP_SUBSTRING
) {
321 new_tree
->u
.substring
.chunks
= NULL
; /* FIXME! */
325 if (map_type
== MAP_CONVERT
) {
326 if (!attr
->u
.convert
.convert_local
)
328 newvalue
= attr
->u
.convert
.convert_local(module
, new_tree
, &value
);
330 newvalue
= ldb_val_dup(new_tree
, &value
);
333 if (new_tree
->operation
== LDB_OP_EQUALITY
) {
334 new_tree
->u
.equality
.value
= newvalue
;
335 } else if (new_tree
->operation
== LDB_OP_LESS
|| new_tree
->operation
== LDB_OP_GREATER
||
336 new_tree
->operation
== LDB_OP_APPROX
) {
337 new_tree
->u
.comparison
.value
= newvalue
;
338 } else if (new_tree
->operation
== LDB_OP_EXTENDED
) {
339 new_tree
->u
.extended
.value
= newvalue
;
340 new_tree
->u
.extended
.rule_id
= talloc_strdup(new_tree
, tree
->u
.extended
.rule_id
);
346 /* Remote DN -> Local DN */
347 static struct ldb_dn
*map_remote_dn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_dn
*dn
)
349 struct ldb_dn
*newdn
;
355 newdn
= talloc_memdup(ctx
, dn
, sizeof(*dn
));
359 newdn
->components
= talloc_array(newdn
, struct ldb_dn_component
, newdn
->comp_num
);
361 if (!newdn
->components
)
364 /* For each rdn, map the attribute name and possibly the
367 for (i
= 0; i
< dn
->comp_num
; i
++) {
368 const struct ldb_map_attribute
*attr
= map_find_attr_remote(module
->private_data
, dn
->components
[i
].name
);
369 enum ldb_map_attr_type map_type
;
371 /* Unknown attribute - leave this dn as is and hope the best... */
372 if (!attr
) map_type
= MAP_KEEP
;
373 else map_type
= attr
->type
;
378 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn
->components
[i
].name
);
383 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, dn
->components
[i
].name
);
384 newdn
->components
[i
].value
= ldb_val_dup(newdn
->components
, &dn
->components
[i
].value
);
388 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, attr
->local_name
);
389 newdn
->components
[i
].value
= attr
->u
.convert
.convert_remote(module
, ctx
, &dn
->components
[i
].value
);
393 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, attr
->local_name
);
394 newdn
->components
[i
].value
= ldb_val_dup(newdn
->components
, &dn
->components
[i
].value
);
401 /* Local DN -> Remote DN */
402 static struct ldb_dn
*map_local_dn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_dn
*dn
)
404 struct ldb_dn
*newdn
;
410 newdn
= talloc_memdup(ctx
, dn
, sizeof(*dn
));
414 newdn
->components
= talloc_array(newdn
, struct ldb_dn_component
, newdn
->comp_num
);
416 if (!newdn
->components
)
419 /* For each rdn, map the attribute name and possibly the
420 * complete rdn using an equality convert_operator call */
422 for (i
= 0; i
< dn
->comp_num
; i
++) {
423 const struct ldb_map_attribute
*attr
= map_find_attr_local(module
->private_data
, dn
->components
[i
].name
);
424 enum ldb_map_attr_type map_type
;
426 /* Unknown attribute - leave this dn as is and hope the best... */
427 if (!attr
) map_type
= MAP_KEEP
; else map_type
= attr
->type
;
433 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn
->components
[i
].name
);
438 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, attr
->u
.convert
.remote_name
);
439 if (attr
->u
.convert
.convert_local
== NULL
) {
440 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "convert_local not set for attribute '%s' used in DN!", dn
->components
[i
].name
);
444 newdn
->components
[i
].value
= attr
->u
.convert
.convert_local(module
, newdn
->components
, &dn
->components
[i
].value
);
448 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, attr
->u
.rename
.remote_name
);
449 newdn
->components
[i
].value
= ldb_val_dup(newdn
->components
, &dn
->components
[i
].value
);
453 newdn
->components
[i
].name
= talloc_strdup(newdn
->components
, dn
->components
[i
].name
);
454 newdn
->components
[i
].value
= ldb_val_dup(newdn
->components
, &dn
->components
[i
].value
);
462 /* Loop over ldb_map_attribute array and add remote_names */
463 static const char **ldb_map_attrs(struct ldb_module
*module
, const char *const attrs
[])
467 int ar_size
= 0, last_element
= 0;
468 struct ldb_map_context
*privdat
= map_get_privdat(module
);
473 /* Start with good guess of number of elements */
474 for (i
= 0; attrs
[i
]; i
++);
476 ret
= talloc_array(module
, const char *, i
);
479 for (i
= 0; attrs
[i
]; i
++) {
481 const struct ldb_map_attribute
*attr
= map_find_attr_local(privdat
, attrs
[i
]);
482 enum ldb_map_attr_type map_type
;
485 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Local attribute '%s' does not have a definition!\n", attrs
[i
]);
486 map_type
= MAP_IGNORE
;
487 } else map_type
= attr
->type
;
491 case MAP_IGNORE
: break;
493 if (last_element
>= ar_size
) {
494 ret
= talloc_realloc(module
, ret
, const char *, ar_size
+1);
497 ret
[last_element
] = attr
->local_name
;
503 if (last_element
>= ar_size
) {
504 ret
= talloc_realloc(module
, ret
, const char *, ar_size
+1);
507 ret
[last_element
] = attr
->u
.rename
.remote_name
;
512 /* Add remote_names[] for this attribute to the list of
513 * attributes to request from the remote server */
514 for (j
= 0; attr
->u
.generate
.remote_names
[j
]; j
++) {
515 if (last_element
>= ar_size
) {
516 ret
= talloc_realloc(module
, ret
, const char *, ar_size
+1);
519 ret
[last_element
] = attr
->u
.generate
.remote_names
[j
];
526 if (last_element
>= ar_size
) {
527 ret
= talloc_realloc(module
, ret
, const char *, ar_size
+1);
531 ret
[last_element
] = NULL
;
536 static const char **available_local_attributes(struct ldb_module
*module
, const struct ldb_message
*msg
)
538 struct ldb_map_context
*privdat
= map_get_privdat(module
);
541 const char **ret
= talloc_array(module
, const char *, 1);
545 for (i
= 0; privdat
->attribute_maps
[i
].local_name
; i
++) {
547 const struct ldb_map_attribute
*attr
= &privdat
->attribute_maps
[i
];
549 /* If all remote attributes for this attribute are present, add the
550 * local one to the list */
552 switch (attr
->type
) {
553 case MAP_IGNORE
: break;
555 avail
= (ldb_msg_find_ldb_val(msg
, attr
->local_name
) != NULL
);
560 avail
= (ldb_msg_find_ldb_val(msg
, attr
->u
.rename
.remote_name
) != NULL
);
565 for (j
= 0; attr
->u
.generate
.remote_names
[j
]; j
++) {
566 avail
&= (BOOL
)(ldb_msg_find_ldb_val(msg
, attr
->u
.generate
.remote_names
[j
]) != NULL
);
574 ret
= talloc_realloc(module
, ret
, const char *, count
+2);
575 ret
[count
] = attr
->local_name
;
583 /* Used for search */
584 static struct ldb_message
*ldb_map_message_incoming(struct ldb_module
*module
, const char * const*attrs
, const struct ldb_message
*mi
)
587 struct ldb_message
*msg
= talloc_zero(module
, struct ldb_message
);
588 struct ldb_message_element
*elm
, *oldelm
;
589 struct ldb_map_context
*privdat
= map_get_privdat(module
);
590 const char **newattrs
= NULL
;
592 msg
->dn
= map_remote_dn(module
, module
, mi
->dn
);
594 /* Loop over attrs, find in ldb_map_attribute array and
598 /* Generate list of the local attributes that /can/ be generated
599 * using the specific remote attributes */
601 attrs
= newattrs
= available_local_attributes(module
, mi
);
604 for (i
= 0; attrs
[i
]; i
++) {
605 const struct ldb_map_attribute
*attr
= map_find_attr_local(privdat
, attrs
[i
]);
606 enum ldb_map_attr_type map_type
;
609 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Unable to find local attribute '%s' when generating incoming message\n", attrs
[i
]);
610 map_type
= MAP_IGNORE
;
611 } else map_type
= attr
->type
;
614 case MAP_IGNORE
:break;
616 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Renaming remote attribute %s to %s", attr
->u
.rename
.remote_name
, attr
->local_name
);
617 oldelm
= ldb_msg_find_element(mi
, attr
->u
.rename
.remote_name
);
621 elm
= talloc(msg
, struct ldb_message_element
);
622 elm
->name
= talloc_strdup(elm
, attr
->local_name
);
623 elm
->num_values
= oldelm
->num_values
;
624 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
625 for (j
= 0; j
< oldelm
->num_values
; j
++)
626 elm
->values
[j
] = ldb_val_dup(elm
, &oldelm
->values
[j
]);
628 ldb_msg_add(msg
, elm
, oldelm
->flags
);
632 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Converting remote attribute %s to %s", attr
->u
.rename
.remote_name
, attr
->local_name
);
633 oldelm
= ldb_msg_find_element(mi
, attr
->u
.rename
.remote_name
);
637 elm
= talloc(msg
, struct ldb_message_element
);
638 elm
->name
= talloc_strdup(elm
, attr
->local_name
);
639 elm
->num_values
= oldelm
->num_values
;
640 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
642 for (j
= 0; j
< oldelm
->num_values
; j
++)
643 elm
->values
[j
] = attr
->u
.convert
.convert_remote(module
, elm
, &oldelm
->values
[j
]);
645 ldb_msg_add(msg
, elm
, oldelm
->flags
);
649 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Keeping remote attribute %s", attr
->local_name
);
650 oldelm
= ldb_msg_find_element(mi
, attr
->local_name
);
651 if (!oldelm
) continue;
653 elm
= talloc(msg
, struct ldb_message_element
);
655 elm
->num_values
= oldelm
->num_values
;
656 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
657 for (j
= 0; j
< oldelm
->num_values
; j
++)
658 elm
->values
[j
] = ldb_val_dup(elm
, &oldelm
->values
[j
]);
660 elm
->name
= talloc_strdup(elm
, oldelm
->name
);
662 ldb_msg_add(msg
, elm
, oldelm
->flags
);
666 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Generating local attribute %s", attr
->local_name
);
667 if (!attr
->u
.generate
.generate_local
)
670 elm
= attr
->u
.generate
.generate_local(module
, msg
, attr
->local_name
, mi
);
674 ldb_msg_add(msg
, elm
, elm
->flags
);
677 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "Unknown attr->type for %s", attr
->local_name
);
682 talloc_free(newattrs
);
690 static int map_rename(struct ldb_module
*module
, struct ldb_request
*req
)
692 const struct ldb_dn
*olddn
= req
->op
.rename
.olddn
;
693 const struct ldb_dn
*newdn
= req
->op
.rename
.newdn
;
694 struct ldb_map_context
*privdat
= map_get_privdat(module
);
695 struct ldb_dn
*n_olddn
, *n_newdn
;
698 n_olddn
= map_local_dn(module
, module
, olddn
);
699 n_newdn
= map_local_dn(module
, module
, newdn
);
701 ret
= ldb_rename(privdat
->mapped_ldb
, n_olddn
, n_newdn
);
703 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Mapped record renamed");
704 ldb_next_request(module
, req
);
706 ret
= ldb_next_request(module
, req
);
709 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Fallback record renamed");
714 talloc_free(n_olddn
);
715 talloc_free(n_newdn
);
723 static int map_delete(struct ldb_module
*module
, struct ldb_request
*req
)
725 const struct ldb_dn
*dn
= req
->op
.del
.dn
;
726 struct ldb_map_context
*privdat
= map_get_privdat(module
);
727 struct ldb_dn
*newdn
;
730 newdn
= map_local_dn(module
, module
, dn
);
732 ret
= ldb_delete(privdat
->mapped_ldb
, newdn
);
734 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Mapped record deleted");
736 ret
= ldb_next_request(module
, req
);
738 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Fallback record deleted");
742 req
->op
.del
.dn
= newdn
;
743 ret
= ldb_next_request(module
, req
);
751 /* search fallback database */
752 static int map_search_fb(struct ldb_module
*module
, struct ldb_request
*req
)
754 struct ldb_parse_tree
*tree
= req
->op
.search
.tree
;
755 struct ldb_parse_tree t_and
, t_not
, t_present
, *childs
[2];
759 t_present
.operation
= LDB_OP_PRESENT
;
760 ismapped
= talloc_strdup(module
, "isMapped");
761 t_present
.u
.present
.attr
= ismapped
;
763 t_not
.operation
= LDB_OP_NOT
;
764 t_not
.u
.isnot
.child
= &t_present
;
768 t_and
.operation
= LDB_OP_AND
;
769 t_and
.u
.list
.num_elements
= 2;
770 t_and
.u
.list
.elements
= childs
;
772 req
->op
.search
.tree
= &t_and
;
773 ret
= ldb_next_request(module
, req
);
774 req
->op
.search
.tree
= tree
;
776 talloc_free(ismapped
);
781 /* Search in the database against which we are mapping */
782 static int map_search_mp(struct ldb_module
*module
, struct ldb_request
*req
)
784 const struct ldb_dn
*base
= req
->op
.search
.base
;
785 enum ldb_scope scope
= req
->op
.search
.scope
;
786 struct ldb_parse_tree
*tree
= req
->op
.search
.tree
;
787 const char * const *attrs
= req
->op
.search
.attrs
;
788 struct ldb_result
*res
;
789 struct ldb_request new_req
;
790 struct ldb_parse_tree
*new_tree
;
791 struct ldb_dn
*new_base
;
792 struct ldb_result
*newres
;
793 const char **newattrs
;
795 struct ldb_map_context
*privdat
= map_get_privdat(module
);
798 /*- search mapped database */
800 new_tree
= ldb_map_parse_tree(module
, module
, tree
);
801 if (new_tree
== NULL
) {
802 /* All attributes used in the parse tree are
803 * local, apparently. Fall back to enumerating the complete remote
804 * database... Rather a slow search then no results. */
805 new_tree
= talloc_zero(module
, struct ldb_parse_tree
);
806 new_tree
->operation
= LDB_OP_PRESENT
;
807 new_tree
->u
.present
.attr
= talloc_strdup(new_tree
, "dn");
811 newattrs
= ldb_map_attrs(module
, attrs
);
812 new_base
= map_local_dn(module
, module
, base
);
814 memset((char *)&(new_req
), 0, sizeof(new_req
));
815 new_req
.operation
= LDB_SEARCH
;
816 new_req
.op
.search
.base
= new_base
;
817 new_req
.op
.search
.scope
= scope
;
818 new_req
.op
.search
.tree
= new_tree
;
819 new_req
.op
.search
.attrs
= newattrs
;
821 mpret
= ldb_request(privdat
->mapped_ldb
, req
);
823 newres
= new_req
.op
.search
.res
;
825 talloc_free(new_base
);
826 talloc_free(new_tree
);
827 talloc_free(newattrs
);
829 if (mpret
!= LDB_SUCCESS
) {
830 ldb_set_errstring(module
->ldb
, talloc_strdup(module
, ldb_errstring(privdat
->mapped_ldb
)));
835 - per returned record, search fallback database for additional data (by dn)
836 - test if (full expression) is now true
839 res
= talloc(module
, struct ldb_result
);
840 req
->op
.search
.res
= res
;
841 res
->msgs
= talloc_array(module
, struct ldb_message
*, newres
->count
);
842 res
->count
= newres
->count
;
846 for (i
= 0; i
< mpret
; i
++) {
847 struct ldb_request mergereq
;
848 struct ldb_message
*merged
;
849 struct ldb_result
*extrares
= NULL
;
852 /* Always get special DN's from the fallback database */
853 if (ldb_dn_is_special(newres
->msgs
[i
]->dn
))
856 merged
= ldb_map_message_incoming(module
, attrs
, newres
->msgs
[i
]);
858 /* Merge with additional data from fallback database */
859 memset((char *)&(mergereq
), 0, sizeof(mergereq
)); /* zero off the request structure */
860 mergereq
.operation
= LDB_SEARCH
;
861 mergereq
.op
.search
.base
= merged
->dn
;
862 mergereq
.op
.search
.scope
= LDB_SCOPE_BASE
;
863 mergereq
.op
.search
.tree
= ldb_parse_tree(module
, "");
864 mergereq
.op
.search
.attrs
= NULL
;
866 extraret
= ldb_next_request(module
, &mergereq
);
868 extrares
= mergereq
.op
.search
.res
;
870 if (extraret
== -1) {
871 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "Error searching for extra data!\n");
872 } else if (extraret
> 1) {
873 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "More than one result for extra data!\n");
876 } else if (extraret
== 0) {
877 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "No extra data found for remote DN: %s", ldb_dn_linearize(merged
, merged
->dn
));
882 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Extra data found for remote DN: %s", ldb_dn_linearize(merged
, merged
->dn
));
883 for (j
= 0; j
< extrares
->msgs
[0]->num_elements
; j
++) {
884 ldb_msg_add(merged
, &(extrares
->msgs
[0]->elements
[j
]), extrares
->msgs
[0]->elements
[j
].flags
);
888 if (ldb_match_msg(module
->ldb
, merged
, tree
, base
, scope
) != 0) {
889 res
->msgs
[ret
] = merged
;
892 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Discarded merged message because it did not match");
904 search for matching records using a ldb_parse_tree
906 static int map_search_bytree(struct ldb_module
*module
, struct ldb_request
*req
)
908 const struct ldb_dn
*base
= req
->op
.search
.base
;
909 struct ldb_result
*fbres
, *mpres
, *res
;
912 ret
= map_search_fb(module
, req
);
913 if (ret
!= LDB_SUCCESS
)
916 /* special dn's are never mapped.. */
917 if (ldb_dn_is_special(base
)) {
921 fbres
= req
->op
.search
.res
;
923 ret
= map_search_mp(module
, req
);
924 if (ret
!= LDB_SUCCESS
) {
928 mpres
= req
->op
.search
.res
;
931 res
= talloc(module
, struct ldb_result
);
932 res
->msgs
= talloc_array(res
, struct ldb_message
*, fbres
->count
+ mpres
->count
);
934 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Merging %d mapped and %d fallback messages", mpres
->count
, fbres
->count
);
936 for (i
= 0; i
< fbres
->count
; i
++) {
937 res
->msgs
[i
] = talloc_steal(res
->msgs
, fbres
->msgs
[i
]);
939 for (i
= 0; i
< mpres
->count
; i
++) {
940 res
->msgs
[fbres
->count
+ i
] = talloc_steal(res
->msgs
, mpres
->msgs
[i
]);
943 res
->count
= fbres
->count
+ mpres
->count
;
947 static int msg_contains_objectclass(const struct ldb_message
*msg
, const char *name
)
949 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, "objectClass");
952 for (i
= 0; i
< el
->num_values
; i
++) {
953 if (ldb_attr_cmp((char *)el
->values
[i
].data
, name
) == 0) {
964 static int map_add(struct ldb_module
*module
, struct ldb_request
*req
)
966 const struct ldb_message
*msg
= req
->op
.add
.message
;
967 struct ldb_map_context
*privdat
= map_get_privdat(module
);
968 struct ldb_message
*fb
, *mp
;
969 struct ldb_message_element
*ocs
;
973 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "ldb_map_add");
975 if (ldb_dn_is_special(msg
->dn
)) {
976 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "ldb_map_add: Added fallback record");
977 return ldb_next_request(module
, req
);
980 mp
= talloc_zero(module
, struct ldb_message
);
981 mp
->dn
= map_local_dn(module
, mp
, msg
->dn
);
983 fb
= talloc_zero(module
, struct ldb_message
);
984 fb
->dn
= talloc_reference(fb
, msg
->dn
);
986 /* We add objectClass, so 'top' should be no problem */
987 ldb_msg_add_string(mp
, "objectClass", "top");
989 /* make a list of remote objectclasses that can be used
990 * given the attributes that are available and add to
992 for (i
= 0; privdat
->objectclass_maps
[i
].local_name
; i
++) {
993 int j
, has_musts
, has_baseclasses
;
995 /* Add this objectClass to the list if all musts are present */
996 for (j
= 0; privdat
->objectclass_maps
[i
].musts
[j
]; j
++) {
997 if (!map_msg_can_map_attr(module
, msg
, privdat
->objectclass_maps
[i
].musts
[j
])) {
998 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "map_add: Not adding objectClass %s because it is not possible to create remote attribute %s", privdat
->objectclass_maps
[i
].local_name
, privdat
->objectclass_maps
[i
].musts
[j
]);
1003 has_musts
= (privdat
->objectclass_maps
[i
].musts
[j
] == NULL
);
1005 /* Check if base classes are present as well */
1006 for (j
= 0; privdat
->objectclass_maps
[i
].base_classes
[j
]; j
++) {
1007 if (!msg_contains_objectclass(mp
, privdat
->objectclass_maps
[i
].base_classes
[j
])) {
1008 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "map_add: Not adding objectClass %s of missing base class %s", privdat
->objectclass_maps
[i
].local_name
, privdat
->objectclass_maps
[i
].base_classes
[j
]);
1013 has_baseclasses
= (privdat
->objectclass_maps
[i
].base_classes
[j
] == NULL
);
1015 /* Apparently, it contains all required elements */
1016 if (has_musts
&& has_baseclasses
) {
1017 ldb_msg_add_string(mp
, "objectClass", privdat
->objectclass_maps
[i
].remote_name
);
1018 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "map_add: Adding objectClass %s", privdat
->objectclass_maps
[i
].remote_name
);
1022 ocs
= ldb_msg_find_element(mp
, "objectClass");
1023 if (ocs
->num_values
== 1) { /* Only top */
1024 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "ldb_map_add: Added fallback record");
1025 return ldb_next_request(module
, req
);
1029 * - try to map as much attributes as possible where allowed and add them to mp_msg
1030 * - add other attributes to fb_msg
1032 for (i
= 0; i
< msg
->num_elements
; i
++) {
1033 const struct ldb_map_attribute
*attr
;
1034 struct ldb_message_element
*elm
= NULL
;
1038 if (ldb_attr_cmp(msg
->elements
[i
].name
, "objectClass") == 0)
1041 /* Loop over all attribute_maps with msg->elements[i].name as local_name */
1042 for (k
= 0; privdat
->attribute_maps
[k
].local_name
; k
++) {
1043 if (ldb_attr_cmp(msg
->elements
[i
].name
, privdat
->attribute_maps
[k
].local_name
) != 0)
1046 attr
= &privdat
->attribute_maps
[k
];
1048 /* Decide whether or not we need to map or fallback */
1049 switch (attr
->type
) {
1051 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Generating from %s", attr
->local_name
);
1052 attr
->u
.generate
.generate_remote(module
, attr
->local_name
, msg
, mp
, fb
);
1056 if (!map_msg_valid_attr(module
, mp
, attr
->local_name
))
1059 case MAP_IGNORE
: continue;
1062 if (!map_msg_valid_attr(module
, mp
, attr
->u
.rename
.remote_name
))
1067 switch (attr
->type
) {
1069 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Keeping %s", attr
->local_name
);
1070 elm
= talloc(fb
, struct ldb_message_element
);
1072 elm
->num_values
= msg
->elements
[i
].num_values
;
1073 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1075 for (j
= 0; j
< elm
->num_values
; j
++) {
1076 elm
->values
[j
] = ldb_val_dup(elm
, &msg
->elements
[i
].values
[j
]);
1079 elm
->name
= talloc_strdup(elm
, msg
->elements
[i
].name
);
1083 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Renaming %s -> %s", attr
->local_name
, attr
->u
.rename
.remote_name
);
1084 elm
= talloc(mp
, struct ldb_message_element
);
1086 elm
->name
= talloc_strdup(elm
, attr
->u
.rename
.remote_name
);
1087 elm
->num_values
= msg
->elements
[i
].num_values
;
1088 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1090 for (j
= 0; j
< elm
->num_values
; j
++) {
1091 elm
->values
[j
] = ldb_val_dup(elm
, &msg
->elements
[i
].values
[j
]);
1096 if (attr
->u
.convert
.convert_local
== NULL
)
1098 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Converting %s -> %s", attr
->local_name
, attr
->u
.convert
.remote_name
);
1099 elm
= talloc(mp
, struct ldb_message_element
);
1101 elm
->name
= talloc_strdup(elm
, attr
->u
.rename
.remote_name
);
1102 elm
->num_values
= msg
->elements
[i
].num_values
;
1103 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1105 for (j
= 0; j
< elm
->num_values
; j
++) {
1106 elm
->values
[j
] = attr
->u
.convert
.convert_local(module
, mp
, &msg
->elements
[i
].values
[j
]);
1113 ldb_debug(module
->ldb
, LDB_DEBUG_FATAL
, "This line should never be reached");
1117 ldb_msg_add(mp
, elm
, 0);
1122 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Fallback storing %s", msg
->elements
[i
].name
);
1123 elm
= talloc(fb
, struct ldb_message_element
);
1125 elm
->num_values
= msg
->elements
[i
].num_values
;
1126 elm
->values
= talloc_reference(elm
, msg
->elements
[i
].values
);
1127 elm
->name
= talloc_strdup(elm
, msg
->elements
[i
].name
);
1129 ldb_msg_add(fb
, elm
, 0);
1133 ret
= ldb_add(privdat
->mapped_ldb
, mp
);
1135 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Adding mapped record failed: %s", ldb_errstring(privdat
->mapped_ldb
));
1139 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "ldb_map_add: Added mapped record");
1141 ldb_msg_add_string(fb
, "isMapped", "TRUE");
1143 req
->op
.add
.message
= fb
;
1144 ret
= ldb_next_request(module
, req
);
1145 req
->op
.add
.message
= msg
;
1147 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Adding fallback record failed: %s", ldb_errstring(module
->ldb
));
1161 static int map_modify(struct ldb_module
*module
, struct ldb_request
*req
)
1163 const struct ldb_message
*msg
= req
->op
.mod
.message
;
1164 struct ldb_map_context
*privdat
= map_get_privdat(module
);
1165 struct ldb_message
*fb
, *mp
;
1166 struct ldb_message_element
*elm
;
1170 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "ldb_map_modify");
1172 if (ldb_dn_is_special(msg
->dn
))
1173 return ldb_next_request(module
, req
);
1175 fb
= talloc_zero(module
, struct ldb_message
);
1176 fb
->dn
= talloc_reference(fb
, msg
->dn
);
1178 mp
= talloc_zero(module
, struct ldb_message
);
1179 mp
->dn
= map_local_dn(module
, mp
, msg
->dn
);
1181 /* Loop over mi and call generate_remote for each attribute */
1182 for (i
= 0; i
< msg
->num_elements
; i
++) {
1183 const struct ldb_map_attribute
*attr
;
1187 if (ldb_attr_cmp(msg
->elements
[i
].name
, "isMapped") == 0)
1190 for (k
= 0; privdat
->attribute_maps
[k
].local_name
; k
++)
1192 if (ldb_attr_cmp(privdat
->attribute_maps
[k
].local_name
, msg
->elements
[i
].name
) != 0)
1195 attr
= &privdat
->attribute_maps
[k
];
1197 switch (attr
->type
) {
1198 case MAP_IGNORE
: continue;
1200 elm
= talloc(mp
, struct ldb_message_element
);
1202 elm
->name
= talloc_strdup(elm
, attr
->u
.rename
.remote_name
);
1203 elm
->num_values
= msg
->elements
[i
].num_values
;
1204 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1205 for (j
= 0; j
< elm
->num_values
; j
++) {
1206 elm
->values
[j
] = msg
->elements
[i
].values
[j
];
1209 ldb_msg_add(mp
, elm
, msg
->elements
[i
].flags
);
1214 if (!attr
->u
.convert
.convert_local
)
1216 elm
= talloc(mp
, struct ldb_message_element
);
1218 elm
->name
= talloc_strdup(elm
, attr
->u
.rename
.remote_name
);
1219 elm
->num_values
= msg
->elements
[i
].num_values
;
1220 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1222 for (j
= 0; j
< elm
->num_values
; j
++) {
1223 elm
->values
[j
] = attr
->u
.convert
.convert_local(module
, mp
, &msg
->elements
[i
].values
[j
]);
1226 ldb_msg_add(mp
, elm
, msg
->elements
[i
].flags
);
1231 elm
= talloc(mp
, struct ldb_message_element
);
1233 elm
->num_values
= msg
->elements
[i
].num_values
;
1234 elm
->values
= talloc_array(elm
, struct ldb_val
, elm
->num_values
);
1235 for (j
= 0; j
< elm
->num_values
; j
++) {
1236 elm
->values
[j
] = msg
->elements
[i
].values
[j
];
1239 elm
->name
= talloc_strdup(elm
, msg
->elements
[i
].name
);
1241 ldb_msg_add(mp
, elm
, msg
->elements
[i
].flags
);
1246 attr
->u
.generate
.generate_remote(module
, attr
->local_name
, msg
, mp
, fb
);
1252 if (mapped
== 0) {/* Add to fallback message */
1253 elm
= talloc(fb
, struct ldb_message_element
);
1255 elm
->num_values
= msg
->elements
[i
].num_values
;
1256 elm
->values
= talloc_reference(elm
, msg
->elements
[i
].values
);
1257 elm
->name
= talloc_strdup(elm
, msg
->elements
[i
].name
);
1259 ldb_msg_add(fb
, elm
, msg
->elements
[i
].flags
);
1263 if (fb
->num_elements
> 0) {
1264 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Modifying fallback record with %d elements", fb
->num_elements
);
1265 req
->op
.mod
.message
= fb
;
1266 fb_ret
= ldb_next_request(module
, req
);
1268 ldb_msg_add_string(fb
, "isMapped", "TRUE");
1269 req
->operation
= LDB_ADD
;
1270 req
->op
.add
.message
= fb
;
1271 fb_ret
= ldb_next_request(module
, req
);
1272 req
->operation
= LDB_MODIFY
;
1274 req
->op
.mod
.message
= msg
;
1278 if (mp
->num_elements
> 0) {
1279 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "Modifying mapped record with %d elements", mp
->num_elements
);
1280 mp_ret
= ldb_modify(privdat
->mapped_ldb
, mp
);
1284 return (mp_ret
== -1 || fb_ret
== -1)?-1:0;
1288 static int map_request(struct ldb_module
*module
, struct ldb_request
*req
)
1290 switch (req
->operation
) {
1293 return map_search_bytree(module
, req
);
1296 return map_add(module
, req
);
1299 return map_modify(module
, req
);
1302 return map_delete(module
, req
);
1305 return map_rename(module
, req
);
1308 return ldb_next_request(module
, req
);
1314 static const struct ldb_module_ops map_ops
= {
1316 .request
= map_request
1319 static char *map_find_url(struct ldb_context
*ldb
, const char *name
)
1321 const char * const attrs
[] = { "@MAP_URL" , NULL
};
1322 struct ldb_result
*result
= NULL
;
1323 struct ldb_dn
*mods
;
1327 mods
= ldb_dn_string_compose(ldb
, NULL
, "@MAP=%s", name
);
1329 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Can't construct DN");
1333 ret
= ldb_search(ldb
, mods
, LDB_SCOPE_BASE
, "", attrs
, &result
);
1335 if (ret
!= LDB_SUCCESS
|| result
->count
== 0) {
1336 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Not enough results found looking for @MAP");
1340 url
= talloc_strdup(ldb
, ldb_msg_find_string(result
->msgs
[0], "@MAP_URL", NULL
));
1342 talloc_free(result
);
1347 /* the init function */
1348 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
)
1351 struct ldb_module
*ctx
;
1352 struct map_private
*data
;
1355 ctx
= talloc(ldb
, struct ldb_module
);
1359 data
= talloc(ctx
, struct map_private
);
1365 data
->context
.mapped_ldb
= ldb_init(data
);
1366 ldb_set_debug(data
->context
.mapped_ldb
, ldb
->debug_ops
.debug
, ldb
->debug_ops
.context
);
1367 url
= map_find_url(ldb
, name
);
1370 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "@MAP=%s not set!\n", name
);
1374 if (ldb_connect(data
->context
.mapped_ldb
, url
, 0, NULL
) != 0) {
1375 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "Unable to open mapped database for %s at '%s'\n", name
, url
);
1381 /* Get list of attribute maps */
1383 data
->context
.attribute_maps
= NULL
;
1385 for (i
= 0; attrs
[i
].local_name
; i
++) {
1386 data
->context
.attribute_maps
= talloc_realloc(data
, data
->context
.attribute_maps
, struct ldb_map_attribute
, j
+1);
1387 data
->context
.attribute_maps
[j
] = attrs
[i
];
1391 for (i
= 0; builtin_attribute_maps
[i
].local_name
; i
++) {
1392 data
->context
.attribute_maps
= talloc_realloc(data
, data
->context
.attribute_maps
, struct ldb_map_attribute
, j
+1);
1393 data
->context
.attribute_maps
[j
] = builtin_attribute_maps
[i
];
1397 data
->context
.attribute_maps
= talloc_realloc(data
, data
->context
.attribute_maps
, struct ldb_map_attribute
, j
+1);
1398 memset(&data
->context
.attribute_maps
[j
], 0, sizeof(struct ldb_map_attribute
));
1400 data
->context
.objectclass_maps
= ocls
;
1401 ctx
->private_data
= data
;
1403 ctx
->prev
= ctx
->next
= NULL
;
1404 ctx
->ops
= &map_ops
;
1409 static struct ldb_val
map_convert_local_dn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
1411 struct ldb_dn
*dn
, *newdn
;
1412 struct ldb_val
*newval
;
1414 dn
= ldb_dn_explode(ctx
, (char *)val
->data
);
1416 newdn
= map_local_dn(module
, ctx
, dn
);
1420 newval
= talloc(ctx
, struct ldb_val
);
1421 newval
->data
= (uint8_t *)ldb_dn_linearize(ctx
, newdn
);
1423 newval
->length
= strlen((char *)newval
->data
);
1433 static struct ldb_val
map_convert_remote_dn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
1435 struct ldb_dn
*dn
, *newdn
;
1436 struct ldb_val
*newval
;
1438 dn
= ldb_dn_explode(ctx
, (char *)val
->data
);
1440 newdn
= map_remote_dn(module
, ctx
, dn
);
1444 newval
= talloc(ctx
, struct ldb_val
);
1445 newval
->data
= (uint8_t *)ldb_dn_linearize(ctx
, newdn
);
1447 newval
->length
= strlen((char *)newval
->data
);
1457 static struct ldb_val
map_convert_local_objectclass(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
1460 struct ldb_map_context
*map
= module
->private_data
;
1462 for (i
= 0; map
->objectclass_maps
[i
].local_name
; i
++) {
1463 if (!strcmp(map
->objectclass_maps
[i
].local_name
, (char *)val
->data
)) {
1464 struct ldb_val newval
;
1465 newval
.data
= (uint8_t*)talloc_strdup(ctx
, map
->objectclass_maps
[i
].remote_name
);
1466 newval
.length
= strlen((char *)newval
.data
);
1468 return ldb_val_dup(ctx
, &newval
);
1472 return ldb_val_dup(ctx
, val
);
1475 static struct ldb_val
map_convert_remote_objectclass(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
1478 struct ldb_map_context
*map
= module
->private_data
;
1480 for (i
= 0; map
->objectclass_maps
[i
].remote_name
; i
++) {
1481 if (!strcmp(map
->objectclass_maps
[i
].remote_name
, (char *)val
->data
)) {
1482 struct ldb_val newval
;
1483 newval
.data
= (uint8_t*)talloc_strdup(ctx
, map
->objectclass_maps
[i
].local_name
);
1484 newval
.length
= strlen((char *)newval
.data
);
1486 return ldb_val_dup(ctx
, &newval
);
1490 return ldb_val_dup(ctx
, val
);