2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Simo Sorce <idra@samba.org> 2008
8 ** NOTE! The following LGPL license applies to the ldb
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "ldb_includes.h"
29 #include "ldb_map_private.h"
32 /* Mapping message elements
33 * ======================== */
35 /* Map a message element into the remote partition. */
36 static struct ldb_message_element *ldb_msg_el_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
38 struct ldb_message_element *el;
41 el = talloc_zero(mem_ctx, struct ldb_message_element);
47 el->num_values = old->num_values;
48 el->values = talloc_array(el, struct ldb_val, el->num_values);
49 if (el->values == NULL) {
55 el->name = map_attr_map_local(el, map, old->name);
57 for (i = 0; i < el->num_values; i++) {
58 el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
64 /* Add a message element either to a local or to a remote message,
65 * depending on whether it goes into the local or remote partition. */
66 static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg, const char *attr_name, /* const char * const names[], */ const struct ldb_message_element *old)
68 const struct ldb_map_context *data = map_get_context(module);
69 const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
70 struct ldb_message_element *el=NULL;
71 struct ldb_context *ldb = ldb_module_get_ctx(module);
73 /* Unknown attribute: ignore */
75 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
76 "Not mapping attribute '%s': no mapping found",
86 if (map->u.convert.convert_local == NULL) {
87 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
88 "Not mapping attribute '%s': "
89 "'convert_local' not set",
96 el = ldb_msg_el_map_local(module, remote, map, old);
99 case LDB_MAP_GENERATE:
100 if (map->u.generate.generate_remote == NULL) {
101 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
102 "Not mapping attribute '%s': "
103 "'generate_remote' not set",
108 /* TODO: if this attr requires context:
109 * make sure all context attrs are mappable (in 'names')
110 * make sure all context attrs have already been mapped?
111 * maybe postpone generation until they have been mapped?
114 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
122 return ldb_msg_add(remote, el, old->flags);
125 el = talloc(local, struct ldb_message_element);
131 *el = *old; /* copy the old element */
133 return ldb_msg_add(local, el, old->flags);
137 * ================ */
139 /* Check whether a message will be (partially) mapped into the remote partition. */
140 static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
142 const struct ldb_map_context *data = map_get_context(module);
146 for (i = 0; i < msg->num_elements; i++) {
147 ret = map_attr_check_remote(data, msg->elements[i].name);
156 /* Split message elements that stay in the local partition from those
157 * that are mapped into the remote partition. */
158 static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
160 /* const char * const names[]; */
161 struct ldb_context *ldb;
165 ldb = ldb_module_get_ctx(module);
167 for (i = 0; i < msg->num_elements; i++) {
168 /* Skip 'IS_MAPPED' */
169 if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
170 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
171 "Skipping attribute '%s'",
172 msg->elements[i].name);
176 ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
186 static int map_add_do_local(struct map_context *ac);
187 static int map_modify_do_local(struct map_context *ac);
188 static int map_delete_do_local(struct map_context *ac);
189 static int map_rename_do_local(struct map_context *ac);
190 static int map_rename_do_fixup(struct map_context *ac);
191 static int map_rename_local_callback(struct ldb_request *req,
192 struct ldb_reply *ares);
195 /*****************************************************************************
196 * COMMON INBOUND functions
197 *****************************************************************************/
199 /* Store the DN of a single search result in context. */
200 static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares)
202 struct ldb_context *ldb;
203 struct map_context *ac;
206 ac = talloc_get_type(req->context, struct map_context);
207 ldb = ldb_module_get_ctx(ac->module);
210 return ldb_module_done(ac->req, NULL, NULL,
211 LDB_ERR_OPERATIONS_ERROR);
213 if (ares->error != LDB_SUCCESS) {
214 return ldb_module_done(ac->req, ares->controls,
215 ares->response, ares->error);
218 /* We are interested only in the single reply */
220 case LDB_REPLY_ENTRY:
221 /* We have already found a remote DN */
223 ldb_set_errstring(ldb,
224 "Too many results!");
225 return ldb_module_done(ac->req, NULL, NULL,
226 LDB_ERR_OPERATIONS_ERROR);
230 ac->local_dn = talloc_steal(ac, ares->message->dn);
235 switch (ac->req->operation) {
237 ret = map_modify_do_local(ac);
240 ret = map_delete_do_local(ac);
243 ret = map_rename_do_local(ac);
246 /* if we get here we have definitely a problem */
247 ret = LDB_ERR_OPERATIONS_ERROR;
249 if (ret != LDB_SUCCESS) {
250 return ldb_module_done(ac->req, NULL, NULL,
251 LDB_ERR_OPERATIONS_ERROR);
255 /* ignore referrals */
263 /* Build a request to search the local record by its DN. */
264 static int map_search_self_req(struct ldb_request **req,
265 struct map_context *ac,
268 /* attrs[] is returned from this function in
269 * ac->search_req->op.search.attrs, so it must be static, as
270 * otherwise the compiler can put it on the stack */
271 static const char * const attrs[] = { IS_MAPPED, NULL };
272 struct ldb_parse_tree *tree;
274 /* Limit search to records with 'IS_MAPPED' present */
275 tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
278 return LDB_ERR_OPERATIONS_ERROR;
281 *req = map_search_base_req(ac, dn, attrs, tree,
282 ac, map_search_self_callback);
284 return LDB_ERR_OPERATIONS_ERROR;
290 static int map_op_local_callback(struct ldb_request *req,
291 struct ldb_reply *ares)
293 struct ldb_context *ldb;
294 struct map_context *ac;
297 ac = talloc_get_type(req->context, struct map_context);
298 ldb = ldb_module_get_ctx(ac->module);
301 return ldb_module_done(ac->req, NULL, NULL,
302 LDB_ERR_OPERATIONS_ERROR);
304 if (ares->error != LDB_SUCCESS) {
305 return ldb_module_done(ac->req, ares->controls,
306 ares->response, ares->error);
309 if (ares->type != LDB_REPLY_DONE) {
310 ldb_set_errstring(ldb, "Invalid reply type!");
311 return ldb_module_done(ac->req, NULL, NULL,
312 LDB_ERR_OPERATIONS_ERROR);
315 /* Do the remote request. */
316 ret = ldb_next_remote_request(ac->module, ac->remote_req);
317 if (ret != LDB_SUCCESS) {
318 return ldb_module_done(ac->req, NULL, NULL,
319 LDB_ERR_OPERATIONS_ERROR);
325 static int map_op_remote_callback(struct ldb_request *req,
326 struct ldb_reply *ares)
328 struct ldb_context *ldb;
329 struct map_context *ac;
331 ac = talloc_get_type(req->context, struct map_context);
332 ldb = ldb_module_get_ctx(ac->module);
335 return ldb_module_done(ac->req, NULL, NULL,
336 LDB_ERR_OPERATIONS_ERROR);
338 if (ares->error != LDB_SUCCESS) {
339 return ldb_module_done(ac->req, ares->controls,
340 ares->response, ares->error);
343 if (ares->type != LDB_REPLY_DONE) {
344 ldb_set_errstring(ldb, "Invalid reply type!");
345 return ldb_module_done(ac->req, NULL, NULL,
346 LDB_ERR_OPERATIONS_ERROR);
349 return ldb_module_done(ac->req, ares->controls,
350 ares->response, ares->error);
354 /*****************************************************************************
356 *****************************************************************************/
360 int map_add(struct ldb_module *module, struct ldb_request *req)
362 const struct ldb_message *msg = req->op.add.message;
363 struct ldb_context *ldb;
364 struct map_context *ac;
365 struct ldb_message *remote_msg;
368 ldb = ldb_module_get_ctx(module);
370 /* Do not manipulate our control entries */
371 if (ldb_dn_is_special(msg->dn)) {
372 return ldb_next_request(module, req);
375 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
376 if (!ldb_dn_check_local(module, msg->dn)) {
377 return ldb_next_request(module, req);
380 /* No mapping needed, fail */
381 if (!ldb_msg_check_remote(module, msg)) {
382 return LDB_ERR_OPERATIONS_ERROR;
385 /* Prepare context and handle */
386 ac = map_init_context(module, req);
388 return LDB_ERR_OPERATIONS_ERROR;
392 /* Prepare the local message */
393 ac->local_msg = ldb_msg_new(ac);
394 if (ac->local_msg == NULL) {
396 return LDB_ERR_OPERATIONS_ERROR;
398 ac->local_msg->dn = msg->dn;
400 /* Prepare the remote message */
401 remote_msg = ldb_msg_new(ac);
402 if (remote_msg == NULL) {
404 return LDB_ERR_OPERATIONS_ERROR;
406 remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
408 /* Split local from remote message */
409 ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
411 /* Prepare the remote operation */
412 ret = ldb_build_add_req(&ac->remote_req, ldb,
415 ac, map_op_remote_callback,
417 LDB_REQ_SET_LOCATION(ac->remote_req);
418 if (ret != LDB_SUCCESS) {
419 return LDB_ERR_OPERATIONS_ERROR;
422 if ((ac->local_msg->num_elements == 0) ||
423 ( ! map_check_local_db(ac->module))) {
424 /* No local data or db, just run the remote request */
425 return ldb_next_remote_request(ac->module, ac->remote_req);
428 /* Store remote DN in 'IS_MAPPED' */
429 /* TODO: use GUIDs here instead */
430 ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
432 if (ret != LDB_SUCCESS) {
433 return LDB_ERR_OPERATIONS_ERROR;
436 return map_add_do_local(ac);
439 /* Add the local record. */
440 static int map_add_do_local(struct map_context *ac)
442 struct ldb_request *local_req;
443 struct ldb_context *ldb;
446 ldb = ldb_module_get_ctx(ac->module);
448 /* Prepare the local operation */
449 ret = ldb_build_add_req(&local_req, ldb, ac,
453 map_op_local_callback,
455 LDB_REQ_SET_LOCATION(local_req);
456 if (ret != LDB_SUCCESS) {
457 return LDB_ERR_OPERATIONS_ERROR;
459 return ldb_next_request(ac->module, local_req);
462 /*****************************************************************************
464 *****************************************************************************/
466 /* Modify a record. */
467 int map_modify(struct ldb_module *module, struct ldb_request *req)
469 const struct ldb_message *msg = req->op.mod.message;
470 struct ldb_request *search_req;
471 struct ldb_message *remote_msg;
472 struct ldb_context *ldb;
473 struct map_context *ac;
476 ldb = ldb_module_get_ctx(module);
478 /* Do not manipulate our control entries */
479 if (ldb_dn_is_special(msg->dn)) {
480 return ldb_next_request(module, req);
483 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
484 if (!ldb_dn_check_local(module, msg->dn)) {
485 return ldb_next_request(module, req);
488 /* No mapping needed, skip to next module */
489 /* TODO: What if the remote part exists, the local doesn't,
490 * and this request wants to modify local data and thus
491 * add the local record? */
492 if (!ldb_msg_check_remote(module, msg)) {
493 return LDB_ERR_OPERATIONS_ERROR;
496 /* Prepare context and handle */
497 ac = map_init_context(module, req);
499 return LDB_ERR_OPERATIONS_ERROR;
502 /* Prepare the local message */
503 ac->local_msg = ldb_msg_new(ac);
504 if (ac->local_msg == NULL) {
506 return LDB_ERR_OPERATIONS_ERROR;
508 ac->local_msg->dn = msg->dn;
510 /* Prepare the remote message */
511 remote_msg = ldb_msg_new(ac->remote_req);
512 if (remote_msg == NULL) {
514 return LDB_ERR_OPERATIONS_ERROR;
516 remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
518 /* Split local from remote message */
519 ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
521 /* Prepare the remote operation */
522 ret = ldb_build_mod_req(&ac->remote_req, ldb,
525 ac, map_op_remote_callback,
527 LDB_REQ_SET_LOCATION(ac->remote_req);
528 if (ret != LDB_SUCCESS) {
529 return LDB_ERR_OPERATIONS_ERROR;
532 if ((ac->local_msg->num_elements == 0) ||
533 ( ! map_check_local_db(ac->module))) {
534 /* No local data or db, just run the remote request */
535 return ldb_next_remote_request(ac->module, ac->remote_req);
538 /* prepare the search operation */
539 ret = map_search_self_req(&search_req, ac, msg->dn);
540 if (ret != LDB_SUCCESS) {
541 return LDB_ERR_OPERATIONS_ERROR;
544 return ldb_next_request(module, search_req);
547 /* Modify the local record. */
548 static int map_modify_do_local(struct map_context *ac)
550 struct ldb_request *local_req;
551 struct ldb_context *ldb;
554 ldb = ldb_module_get_ctx(ac->module);
556 if (ac->local_dn == NULL) {
557 /* No local record present, add it instead */
558 /* Add local 'IS_MAPPED' */
559 /* TODO: use GUIDs here instead */
560 if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED,
561 LDB_FLAG_MOD_ADD, NULL) != 0) {
562 return LDB_ERR_OPERATIONS_ERROR;
564 ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
565 ac->remote_req->op.mod.message->dn);
567 return LDB_ERR_OPERATIONS_ERROR;
570 /* Prepare the local operation */
571 ret = ldb_build_add_req(&local_req, ldb, ac,
575 map_op_local_callback,
577 LDB_REQ_SET_LOCATION(local_req);
578 if (ret != LDB_SUCCESS) {
579 return LDB_ERR_OPERATIONS_ERROR;
582 /* Prepare the local operation */
583 ret = ldb_build_mod_req(&local_req, ldb, ac,
587 map_op_local_callback,
589 LDB_REQ_SET_LOCATION(local_req);
590 if (ret != LDB_SUCCESS) {
591 return LDB_ERR_OPERATIONS_ERROR;
595 return ldb_next_request(ac->module, local_req);
598 /*****************************************************************************
600 *****************************************************************************/
602 /* Delete a record. */
603 int map_delete(struct ldb_module *module, struct ldb_request *req)
605 struct ldb_request *search_req;
606 struct ldb_context *ldb;
607 struct map_context *ac;
610 ldb = ldb_module_get_ctx(module);
612 /* Do not manipulate our control entries */
613 if (ldb_dn_is_special(req->op.del.dn)) {
614 return ldb_next_request(module, req);
617 /* No mapping requested (perhaps no DN mapping specified).
618 * Skip to next module */
619 if (!ldb_dn_check_local(module, req->op.del.dn)) {
620 return ldb_next_request(module, req);
623 /* Prepare context and handle */
624 ac = map_init_context(module, req);
626 return LDB_ERR_OPERATIONS_ERROR;
629 /* Prepare the remote operation */
630 ret = ldb_build_del_req(&ac->remote_req, ldb, ac,
631 ldb_dn_map_local(module, ac, req->op.del.dn),
634 map_op_remote_callback,
636 LDB_REQ_SET_LOCATION(ac->remote_req);
637 if (ret != LDB_SUCCESS) {
638 return LDB_ERR_OPERATIONS_ERROR;
641 /* No local db, just run the remote request */
642 if (!map_check_local_db(ac->module)) {
643 /* Do the remote request. */
644 return ldb_next_remote_request(ac->module, ac->remote_req);
647 /* Prepare the search operation */
648 ret = map_search_self_req(&search_req, ac, req->op.del.dn);
649 if (ret != LDB_SUCCESS) {
651 return LDB_ERR_OPERATIONS_ERROR;
654 return ldb_next_request(module, search_req);
657 /* Delete the local record. */
658 static int map_delete_do_local(struct map_context *ac)
660 struct ldb_request *local_req;
661 struct ldb_context *ldb;
664 ldb = ldb_module_get_ctx(ac->module);
666 /* No local record, continue remotely */
667 if (ac->local_dn == NULL) {
668 /* Do the remote request. */
669 return ldb_next_remote_request(ac->module, ac->remote_req);
672 /* Prepare the local operation */
673 ret = ldb_build_del_req(&local_req, ldb, ac,
677 map_op_local_callback,
679 LDB_REQ_SET_LOCATION(local_req);
680 if (ret != LDB_SUCCESS) {
681 return LDB_ERR_OPERATIONS_ERROR;
683 return ldb_next_request(ac->module, local_req);
686 /*****************************************************************************
688 *****************************************************************************/
690 /* Rename a record. */
691 int map_rename(struct ldb_module *module, struct ldb_request *req)
693 struct ldb_request *search_req;
694 struct ldb_context *ldb;
695 struct map_context *ac;
698 ldb = ldb_module_get_ctx(module);
700 /* Do not manipulate our control entries */
701 if (ldb_dn_is_special(req->op.rename.olddn)) {
702 return ldb_next_request(module, req);
705 /* No mapping requested (perhaps no DN mapping specified).
706 * Skip to next module */
707 if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
708 (!ldb_dn_check_local(module, req->op.rename.newdn))) {
709 return ldb_next_request(module, req);
712 /* Rename into/out of the mapped partition requested, bail out */
713 if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
714 !ldb_dn_check_local(module, req->op.rename.newdn)) {
715 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
718 /* Prepare context and handle */
719 ac = map_init_context(module, req);
721 return LDB_ERR_OPERATIONS_ERROR;
724 /* Prepare the remote operation */
725 ret = ldb_build_rename_req(&ac->remote_req, ldb, ac,
726 ldb_dn_map_local(module, ac, req->op.rename.olddn),
727 ldb_dn_map_local(module, ac, req->op.rename.newdn),
729 ac, map_op_remote_callback,
731 LDB_REQ_SET_LOCATION(ac->remote_req);
732 if (ret != LDB_SUCCESS) {
733 return LDB_ERR_OPERATIONS_ERROR;
736 /* No local db, just run the remote request */
737 if (!map_check_local_db(ac->module)) {
738 /* Do the remote request. */
739 return ldb_next_remote_request(ac->module, ac->remote_req);
742 /* Prepare the search operation */
743 ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
744 if (ret != LDB_SUCCESS) {
746 return LDB_ERR_OPERATIONS_ERROR;
749 return ldb_next_request(module, search_req);
752 /* Rename the local record. */
753 static int map_rename_do_local(struct map_context *ac)
755 struct ldb_request *local_req;
756 struct ldb_context *ldb;
759 ldb = ldb_module_get_ctx(ac->module);
761 /* No local record, continue remotely */
762 if (ac->local_dn == NULL) {
763 /* Do the remote request. */
764 return ldb_next_remote_request(ac->module, ac->remote_req);
767 /* Prepare the local operation */
768 ret = ldb_build_rename_req(&local_req, ldb, ac,
769 ac->req->op.rename.olddn,
770 ac->req->op.rename.newdn,
773 map_rename_local_callback,
775 LDB_REQ_SET_LOCATION(local_req);
776 if (ret != LDB_SUCCESS) {
777 return LDB_ERR_OPERATIONS_ERROR;
780 return ldb_next_request(ac->module, local_req);
783 static int map_rename_local_callback(struct ldb_request *req,
784 struct ldb_reply *ares)
786 struct ldb_context *ldb;
787 struct map_context *ac;
790 ac = talloc_get_type(req->context, struct map_context);
791 ldb = ldb_module_get_ctx(ac->module);
794 return ldb_module_done(ac->req, NULL, NULL,
795 LDB_ERR_OPERATIONS_ERROR);
797 if (ares->error != LDB_SUCCESS) {
798 return ldb_module_done(ac->req, ares->controls,
799 ares->response, ares->error);
802 if (ares->type != LDB_REPLY_DONE) {
803 ldb_set_errstring(ldb, "Invalid reply type!");
804 return ldb_module_done(ac->req, NULL, NULL,
805 LDB_ERR_OPERATIONS_ERROR);
808 /* proceed with next step */
809 ret = map_rename_do_fixup(ac);
810 if (ret != LDB_SUCCESS) {
811 return ldb_module_done(ac->req, NULL, NULL,
812 LDB_ERR_OPERATIONS_ERROR);
818 /* Update the local 'IS_MAPPED' attribute. */
819 static int map_rename_do_fixup(struct map_context *ac)
821 struct ldb_request *local_req;
823 /* Prepare the fixup operation */
824 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
825 local_req = map_build_fixup_req(ac,
826 ac->req->op.rename.newdn,
827 ac->remote_req->op.rename.newdn,
829 map_op_local_callback);
830 if (local_req == NULL) {
831 return LDB_ERR_OPERATIONS_ERROR;
834 return ldb_next_request(ac->module, local_req);