dsdb: improve debug message
[nivanova/samba-autobuild/.git] / lib / ldb / ldb_map / ldb_map_inbound.c
1 /*
2    ldb database mapping module
3
4    Copyright (C) Jelmer Vernooij 2005
5    Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6    Copyright (C) Simo Sorce <idra@samba.org> 2008
7
8      ** NOTE! The following LGPL license applies to the ldb
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11    
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.
16
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.
21
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/>.
24
25 */
26
27 #include "replace.h"
28 #include "system/filesys.h"
29 #include "system/time.h"
30 #include "ldb_map.h"
31 #include "ldb_map_private.h"
32
33
34 /* Mapping message elements
35  * ======================== */
36
37 /* Map a message element into the remote partition. */
38 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)
39 {
40         struct ldb_message_element *el;
41         unsigned int i;
42
43         el = talloc_zero(mem_ctx, struct ldb_message_element);
44         if (el == NULL) {
45                 map_oom(module);
46                 return NULL;
47         }
48
49         el->num_values = old->num_values;
50         el->values = talloc_array(el, struct ldb_val, el->num_values);
51         if (el->values == NULL) {
52                 talloc_free(el);
53                 map_oom(module);
54                 return NULL;
55         }
56
57         el->name = map_attr_map_local(el, map, old->name);
58
59         for (i = 0; i < el->num_values; i++) {
60                 el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
61         }
62
63         return el;
64 }
65
66 /* Add a message element either to a local or to a remote message,
67  * depending on whether it goes into the local or remote partition. */
68 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)
69 {
70         const struct ldb_map_context *data = map_get_context(module);
71         const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
72         struct ldb_message_element *el=NULL;
73         struct ldb_context *ldb = ldb_module_get_ctx(module);
74
75         /* Unknown attribute: ignore */
76         if (map == NULL) {
77                 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
78                           "Not mapping attribute '%s': no mapping found",
79                           old->name);
80                 goto local;
81         }
82
83         switch (map->type) {
84         case LDB_MAP_IGNORE:
85                 goto local;
86
87         case LDB_MAP_CONVERT:
88                 if (map->u.convert.convert_local == NULL) {
89                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
90                                   "Not mapping attribute '%s': "
91                                   "'convert_local' not set",
92                                   map->local_name);
93                         goto local;
94                 }
95                 /* fall through */
96         case LDB_MAP_KEEP:
97         case LDB_MAP_RENAME:
98                 el = ldb_msg_el_map_local(module, remote, map, old);
99                 break;
100
101         case LDB_MAP_GENERATE:
102                 if (map->u.generate.generate_remote == NULL) {
103                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
104                                   "Not mapping attribute '%s': "
105                                   "'generate_remote' not set",
106                                   map->local_name);
107                         goto local;
108                 }
109
110                 /* TODO: if this attr requires context:
111                  *       make sure all context attrs are mappable (in 'names')
112                  *       make sure all context attrs have already been mapped?
113                  *       maybe postpone generation until they have been mapped?
114                  */
115
116                 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
117                 return 0;
118         }
119
120         if (el == NULL) {
121                 return -1;
122         }
123
124         return ldb_msg_add(remote, el, old->flags);
125
126 local:
127         el = talloc(local, struct ldb_message_element);
128         if (el == NULL) {
129                 map_oom(module);
130                 return -1;
131         }
132
133         *el = *old;                     /* copy the old element */
134
135         return ldb_msg_add(local, el, old->flags);
136 }
137
138 /* Mapping messages
139  * ================ */
140
141 /* Check whether a message will be (partially) mapped into the remote partition. */
142 static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
143 {
144         const struct ldb_map_context *data = map_get_context(module);
145         bool ret;
146         unsigned int i;
147
148         for (i = 0; i < msg->num_elements; i++) {
149                 ret = map_attr_check_remote(data, msg->elements[i].name);
150                 if (ret) {
151                         return ret;
152                 }
153         }
154
155         return false;
156 }
157
158 /* Split message elements that stay in the local partition from those
159  * that are mapped into the remote partition. */
160 static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
161 {
162         /* const char * const names[]; */
163         struct ldb_context *ldb;
164         unsigned int i;
165         int ret;
166
167         ldb = ldb_module_get_ctx(module);
168
169         for (i = 0; i < msg->num_elements; i++) {
170                 /* Skip 'IS_MAPPED' */
171                 if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
172                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
173                                   "Skipping attribute '%s'",
174                                   msg->elements[i].name);
175                         continue;
176                 }
177
178                 ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
179                 if (ret) {
180                         return ret;
181                 }
182         }
183
184         return 0;
185 }
186
187
188 static int map_add_do_local(struct map_context *ac);
189 static int map_modify_do_local(struct map_context *ac);
190 static int map_delete_do_local(struct map_context *ac);
191 static int map_rename_do_local(struct map_context *ac);
192 static int map_rename_do_fixup(struct map_context *ac);
193 static int map_rename_local_callback(struct ldb_request *req,
194                                      struct ldb_reply *ares);
195
196
197 /*****************************************************************************
198  * COMMON INBOUND functions
199 *****************************************************************************/
200
201 /* Store the DN of a single search result in context. */
202 static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares)
203 {
204         struct ldb_context *ldb;
205         struct map_context *ac;
206         int ret;
207
208         ac = talloc_get_type(req->context, struct map_context);
209         ldb = ldb_module_get_ctx(ac->module);
210
211         if (!ares) {
212                 return ldb_module_done(ac->req, NULL, NULL,
213                                         LDB_ERR_OPERATIONS_ERROR);
214         }
215         if (ares->error != LDB_SUCCESS) {
216                 return ldb_module_done(ac->req, ares->controls,
217                                         ares->response, ares->error);
218         }
219
220         /* We are interested only in the single reply */
221         switch(ares->type) {
222         case LDB_REPLY_ENTRY:
223                 /* We have already found a remote DN */
224                 if (ac->local_dn) {
225                         ldb_set_errstring(ldb,
226                                           "Too many results!");
227                         return ldb_module_done(ac->req, NULL, NULL,
228                                                 LDB_ERR_OPERATIONS_ERROR);
229                 }
230
231                 /* Store local DN */
232                 ac->local_dn = talloc_steal(ac, ares->message->dn);
233                 break;
234
235         case LDB_REPLY_DONE:
236
237                 switch (ac->req->operation) {
238                 case LDB_MODIFY:
239                         ret = map_modify_do_local(ac);
240                         break;
241                 case LDB_DELETE:
242                         ret = map_delete_do_local(ac);
243                         break;
244                 case LDB_RENAME:
245                         ret = map_rename_do_local(ac);
246                         break;
247                 default:
248                         /* if we get here we have definitely a problem */
249                         ret = LDB_ERR_OPERATIONS_ERROR;
250                 }
251                 if (ret != LDB_SUCCESS) {
252                         return ldb_module_done(ac->req, NULL, NULL,
253                                                 LDB_ERR_OPERATIONS_ERROR);
254                 }
255
256         default:
257                 /* ignore referrals */
258                 break;
259         }
260
261         talloc_free(ares);
262         return LDB_SUCCESS;
263 }
264
265 /* Build a request to search the local record by its DN. */
266 static int map_search_self_req(struct ldb_request **req,
267                                 struct map_context *ac,
268                                 struct ldb_dn *dn)
269 {
270         /* attrs[] is returned from this function in
271          * ac->search_req->op.search.attrs, so it must be static, as
272          * otherwise the compiler can put it on the stack */
273         static const char * const attrs[] = { IS_MAPPED, NULL };
274         struct ldb_parse_tree *tree;
275
276         /* Limit search to records with 'IS_MAPPED' present */
277         tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
278         if (tree == NULL) {
279                 map_oom(ac->module);
280                 return LDB_ERR_OPERATIONS_ERROR;
281         }
282
283         *req = map_search_base_req(ac, dn, attrs, tree,
284                                    ac, map_search_self_callback);
285         if (*req == NULL) {
286                 return LDB_ERR_OPERATIONS_ERROR;
287         }
288
289         return LDB_SUCCESS;
290 }
291
292 static int map_op_local_callback(struct ldb_request *req,
293                                  struct ldb_reply *ares)
294 {
295         struct ldb_context *ldb;
296         struct map_context *ac;
297         int ret;
298
299         ac = talloc_get_type(req->context, struct map_context);
300         ldb = ldb_module_get_ctx(ac->module);
301
302         if (!ares) {
303                 return ldb_module_done(ac->req, NULL, NULL,
304                                         LDB_ERR_OPERATIONS_ERROR);
305         }
306         if (ares->error != LDB_SUCCESS) {
307                 return ldb_module_done(ac->req, ares->controls,
308                                         ares->response, ares->error);
309         }
310
311         if (ares->type != LDB_REPLY_DONE) {
312                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
313                 return ldb_module_done(ac->req, NULL, NULL,
314                                         LDB_ERR_OPERATIONS_ERROR);
315         }
316
317         /* Do the remote request. */
318         ret = ldb_next_remote_request(ac->module, ac->remote_req);
319         if (ret != LDB_SUCCESS) {
320                 return ldb_module_done(ac->req, NULL, NULL,
321                                         LDB_ERR_OPERATIONS_ERROR);
322         }
323
324         return LDB_SUCCESS;
325 }
326
327 static int map_op_remote_callback(struct ldb_request *req,
328                                   struct ldb_reply *ares)
329 {
330         struct ldb_context *ldb;
331         struct map_context *ac;
332
333         ac = talloc_get_type(req->context, struct map_context);
334         ldb = ldb_module_get_ctx(ac->module);
335
336         if (!ares) {
337                 return ldb_module_done(ac->req, NULL, NULL,
338                                         LDB_ERR_OPERATIONS_ERROR);
339         }
340         if (ares->error != LDB_SUCCESS) {
341                 return ldb_module_done(ac->req, ares->controls,
342                                         ares->response, ares->error);
343         }
344
345         if (ares->type != LDB_REPLY_DONE) {
346                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
347                 return ldb_module_done(ac->req, NULL, NULL,
348                                         LDB_ERR_OPERATIONS_ERROR);
349         }
350
351         return ldb_module_done(ac->req, ares->controls,
352                                         ares->response, ares->error);
353 }
354
355
356 /*****************************************************************************
357  * ADD operations
358 *****************************************************************************/
359
360
361 /* Add a record. */
362 int ldb_map_add(struct ldb_module *module, struct ldb_request *req)
363 {
364         const struct ldb_message *msg = req->op.add.message;
365         struct ldb_context *ldb;
366         struct map_context *ac;
367         struct ldb_message *remote_msg;
368         int ret;
369
370         ldb = ldb_module_get_ctx(module);
371
372         /* Do not manipulate our control entries */
373         if (ldb_dn_is_special(msg->dn)) {
374                 return ldb_next_request(module, req);
375         }
376
377         /* No mapping requested (perhaps no DN mapping specified), skip to next module */
378         if (!ldb_dn_check_local(module, msg->dn)) {
379                 return ldb_next_request(module, req);
380         }
381
382         /* No mapping needed, fail */
383         if (!ldb_msg_check_remote(module, msg)) {
384                 return LDB_ERR_OPERATIONS_ERROR;
385         }
386
387         /* Prepare context and handle */
388         ac = map_init_context(module, req);
389         if (ac == NULL) {
390                 return LDB_ERR_OPERATIONS_ERROR;
391         }
392
393
394         /* Prepare the local message */
395         ac->local_msg = ldb_msg_new(ac);
396         if (ac->local_msg == NULL) {
397                 map_oom(module);
398                 return LDB_ERR_OPERATIONS_ERROR;
399         }
400         ac->local_msg->dn = msg->dn;
401
402         /* Prepare the remote message */
403         remote_msg = ldb_msg_new(ac);
404         if (remote_msg == NULL) {
405                 map_oom(module);
406                 return LDB_ERR_OPERATIONS_ERROR;
407         }
408         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
409
410         /* Split local from remote message */
411         ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
412
413         /* Prepare the remote operation */
414         ret = ldb_build_add_req(&ac->remote_req, ldb,
415                                 ac, remote_msg,
416                                 req->controls,
417                                 ac, map_op_remote_callback,
418                                 req);
419         LDB_REQ_SET_LOCATION(ac->remote_req);
420         if (ret != LDB_SUCCESS) {
421                 return LDB_ERR_OPERATIONS_ERROR;
422         }
423
424         if ((ac->local_msg->num_elements == 0) ||
425             ( ! map_check_local_db(ac->module))) {
426                 /* No local data or db, just run the remote request */
427                 return ldb_next_remote_request(ac->module, ac->remote_req);
428         }
429
430         /* Store remote DN in 'IS_MAPPED' */
431         /* TODO: use GUIDs here instead */
432         ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
433                                         remote_msg->dn);
434         if (ret != LDB_SUCCESS) {
435                 return LDB_ERR_OPERATIONS_ERROR;
436         }
437
438         return map_add_do_local(ac);
439 }
440
441 /* Add the local record. */
442 static int map_add_do_local(struct map_context *ac)
443 {
444         struct ldb_request *local_req;
445         struct ldb_context *ldb;
446         int ret;
447
448         ldb = ldb_module_get_ctx(ac->module);
449
450         /* Prepare the local operation */
451         ret = ldb_build_add_req(&local_req, ldb, ac,
452                                 ac->local_msg,
453                                 ac->req->controls,
454                                 ac,
455                                 map_op_local_callback,
456                                 ac->req);
457         LDB_REQ_SET_LOCATION(local_req);
458         if (ret != LDB_SUCCESS) {
459                 return LDB_ERR_OPERATIONS_ERROR;
460         }
461         return ldb_next_request(ac->module, local_req);
462 }
463
464 /*****************************************************************************
465  * MODIFY operations
466 *****************************************************************************/
467
468 /* Modify a record. */
469 int ldb_map_modify(struct ldb_module *module, struct ldb_request *req)
470 {
471         const struct ldb_message *msg = req->op.mod.message;
472         struct ldb_request *search_req;
473         struct ldb_message *remote_msg;
474         struct ldb_context *ldb;
475         struct map_context *ac;
476         int ret;
477
478         ldb = ldb_module_get_ctx(module);
479
480         /* Do not manipulate our control entries */
481         if (ldb_dn_is_special(msg->dn)) {
482                 return ldb_next_request(module, req);
483         }
484
485         /* No mapping requested (perhaps no DN mapping specified), skip to next module */
486         if (!ldb_dn_check_local(module, msg->dn)) {
487                 return ldb_next_request(module, req);
488         }
489
490         /* No mapping needed, skip to next module */
491         /* TODO: What if the remote part exists, the local doesn't,
492          *       and this request wants to modify local data and thus
493          *       add the local record? */
494         if (!ldb_msg_check_remote(module, msg)) {
495                 return LDB_ERR_OPERATIONS_ERROR;
496         }
497
498         /* Prepare context and handle */
499         ac = map_init_context(module, req);
500         if (ac == NULL) {
501                 return LDB_ERR_OPERATIONS_ERROR;
502         }
503
504         /* Prepare the local message */
505         ac->local_msg = ldb_msg_new(ac);
506         if (ac->local_msg == NULL) {
507                 map_oom(module);
508                 return LDB_ERR_OPERATIONS_ERROR;
509         }
510         ac->local_msg->dn = msg->dn;
511
512         /* Prepare the remote message */
513         remote_msg = ldb_msg_new(ac->remote_req);
514         if (remote_msg == NULL) {
515                 map_oom(module);
516                 return LDB_ERR_OPERATIONS_ERROR;
517         }
518         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
519
520         /* Split local from remote message */
521         ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
522
523         /* Prepare the remote operation */
524         ret = ldb_build_mod_req(&ac->remote_req, ldb,
525                                 ac, remote_msg,
526                                 req->controls,
527                                 ac, map_op_remote_callback,
528                                 req);
529         LDB_REQ_SET_LOCATION(ac->remote_req);
530         if (ret != LDB_SUCCESS) {
531                 return LDB_ERR_OPERATIONS_ERROR;
532         }
533
534         if ((ac->local_msg->num_elements == 0) ||
535             ( ! map_check_local_db(ac->module))) {
536                 /* No local data or db, just run the remote request */
537                 return ldb_next_remote_request(ac->module, ac->remote_req);
538         }
539
540         /* prepare the search operation */
541         ret = map_search_self_req(&search_req, ac, msg->dn);
542         if (ret != LDB_SUCCESS) {
543                 return LDB_ERR_OPERATIONS_ERROR;
544         }
545
546         return ldb_next_request(module, search_req);
547 }
548
549 /* Modify the local record. */
550 static int map_modify_do_local(struct map_context *ac)
551 {
552         struct ldb_request *local_req;
553         struct ldb_context *ldb;
554         int ret;
555
556         ldb = ldb_module_get_ctx(ac->module);
557
558         if (ac->local_dn == NULL) {
559                 /* No local record present, add it instead */
560                 /* Add local 'IS_MAPPED' */
561                 /* TODO: use GUIDs here instead */
562                 if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED,
563                                         LDB_FLAG_MOD_ADD, NULL) != 0) {
564                         return LDB_ERR_OPERATIONS_ERROR;
565                 }
566                 ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
567                                                 ac->remote_req->op.mod.message->dn);
568                 if (ret != 0) {
569                         return LDB_ERR_OPERATIONS_ERROR;
570                 }
571
572                 /* Prepare the local operation */
573                 ret = ldb_build_add_req(&local_req, ldb, ac,
574                                         ac->local_msg,
575                                         ac->req->controls,
576                                         ac,
577                                         map_op_local_callback,
578                                         ac->req);
579                 LDB_REQ_SET_LOCATION(local_req);
580                 if (ret != LDB_SUCCESS) {
581                         return LDB_ERR_OPERATIONS_ERROR;
582                 }
583         } else {
584                 /* Prepare the local operation */
585                 ret = ldb_build_mod_req(&local_req, ldb, ac,
586                                         ac->local_msg,
587                                         ac->req->controls,
588                                         ac,
589                                         map_op_local_callback,
590                                         ac->req);
591                 LDB_REQ_SET_LOCATION(local_req);
592                 if (ret != LDB_SUCCESS) {
593                         return LDB_ERR_OPERATIONS_ERROR;
594                 }
595         }
596
597         return ldb_next_request(ac->module, local_req);
598 }
599
600 /*****************************************************************************
601  * DELETE operations
602 *****************************************************************************/
603
604 /* Delete a record. */
605 int ldb_map_delete(struct ldb_module *module, struct ldb_request *req)
606 {
607         struct ldb_request *search_req;
608         struct ldb_context *ldb;
609         struct map_context *ac;
610         int ret;
611
612         ldb = ldb_module_get_ctx(module);
613
614         /* Do not manipulate our control entries */
615         if (ldb_dn_is_special(req->op.del.dn)) {
616                 return ldb_next_request(module, req);
617         }
618
619         /* No mapping requested (perhaps no DN mapping specified).
620          * Skip to next module */
621         if (!ldb_dn_check_local(module, req->op.del.dn)) {
622                 return ldb_next_request(module, req);
623         }
624
625         /* Prepare context and handle */
626         ac = map_init_context(module, req);
627         if (ac == NULL) {
628                 return LDB_ERR_OPERATIONS_ERROR;
629         }
630
631         /* Prepare the remote operation */
632         ret = ldb_build_del_req(&ac->remote_req, ldb, ac,
633                                    ldb_dn_map_local(module, ac, req->op.del.dn),
634                                    req->controls,
635                                    ac,
636                                    map_op_remote_callback,
637                                    req);
638         LDB_REQ_SET_LOCATION(ac->remote_req);
639         if (ret != LDB_SUCCESS) {
640                 return LDB_ERR_OPERATIONS_ERROR;
641         }
642
643         /* No local db, just run the remote request */
644         if (!map_check_local_db(ac->module)) {
645                 /* Do the remote request. */
646                 return ldb_next_remote_request(ac->module, ac->remote_req);
647         }
648
649         /* Prepare the search operation */
650         ret = map_search_self_req(&search_req, ac, req->op.del.dn);
651         if (ret != LDB_SUCCESS) {
652                 map_oom(module);
653                 return LDB_ERR_OPERATIONS_ERROR;
654         }
655
656         return ldb_next_request(module, search_req);
657 }
658
659 /* Delete the local record. */
660 static int map_delete_do_local(struct map_context *ac)
661 {
662         struct ldb_request *local_req;
663         struct ldb_context *ldb;
664         int ret;
665
666         ldb = ldb_module_get_ctx(ac->module);
667
668         /* No local record, continue remotely */
669         if (ac->local_dn == NULL) {
670                 /* Do the remote request. */
671                 return ldb_next_remote_request(ac->module, ac->remote_req);
672         }
673
674         /* Prepare the local operation */
675         ret = ldb_build_del_req(&local_req, ldb, ac,
676                                    ac->req->op.del.dn,
677                                    ac->req->controls,
678                                    ac,
679                                    map_op_local_callback,
680                                    ac->req);
681         LDB_REQ_SET_LOCATION(local_req);
682         if (ret != LDB_SUCCESS) {
683                 return LDB_ERR_OPERATIONS_ERROR;
684         }
685         return ldb_next_request(ac->module, local_req);
686 }
687
688 /*****************************************************************************
689  * RENAME operations
690 *****************************************************************************/
691
692 /* Rename a record. */
693 int ldb_map_rename(struct ldb_module *module, struct ldb_request *req)
694 {
695         struct ldb_request *search_req;
696         struct ldb_context *ldb;
697         struct map_context *ac;
698         int ret;
699
700         ldb = ldb_module_get_ctx(module);
701
702         /* Do not manipulate our control entries */
703         if (ldb_dn_is_special(req->op.rename.olddn)) {
704                 return ldb_next_request(module, req);
705         }
706
707         /* No mapping requested (perhaps no DN mapping specified).
708          * Skip to next module */
709         if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
710             (!ldb_dn_check_local(module, req->op.rename.newdn))) {
711                 return ldb_next_request(module, req);
712         }
713
714         /* Rename into/out of the mapped partition requested, bail out */
715         if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
716             !ldb_dn_check_local(module, req->op.rename.newdn)) {
717                 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
718         }
719
720         /* Prepare context and handle */
721         ac = map_init_context(module, req);
722         if (ac == NULL) {
723                 return LDB_ERR_OPERATIONS_ERROR;
724         }
725
726         /* Prepare the remote operation */
727         ret = ldb_build_rename_req(&ac->remote_req, ldb, ac,
728                                    ldb_dn_map_local(module, ac, req->op.rename.olddn),
729                                    ldb_dn_map_local(module, ac, req->op.rename.newdn),
730                                    req->controls,
731                                    ac, map_op_remote_callback,
732                                    req);
733         LDB_REQ_SET_LOCATION(ac->remote_req);
734         if (ret != LDB_SUCCESS) {
735                 return LDB_ERR_OPERATIONS_ERROR;
736         }
737
738         /* No local db, just run the remote request */
739         if (!map_check_local_db(ac->module)) {
740                 /* Do the remote request. */
741                 return ldb_next_remote_request(ac->module, ac->remote_req);
742         }
743
744         /* Prepare the search operation */
745         ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
746         if (ret != LDB_SUCCESS) {
747                 map_oom(module);
748                 return LDB_ERR_OPERATIONS_ERROR;
749         }
750
751         return ldb_next_request(module, search_req);
752 }
753
754 /* Rename the local record. */
755 static int map_rename_do_local(struct map_context *ac)
756 {
757         struct ldb_request *local_req;
758         struct ldb_context *ldb;
759         int ret;
760
761         ldb = ldb_module_get_ctx(ac->module);
762
763         /* No local record, continue remotely */
764         if (ac->local_dn == NULL) {
765                 /* Do the remote request. */
766                 return ldb_next_remote_request(ac->module, ac->remote_req);
767         }
768
769         /* Prepare the local operation */
770         ret = ldb_build_rename_req(&local_req, ldb, ac,
771                                    ac->req->op.rename.olddn,
772                                    ac->req->op.rename.newdn,
773                                    ac->req->controls,
774                                    ac,
775                                    map_rename_local_callback,
776                                    ac->req);
777         LDB_REQ_SET_LOCATION(local_req);
778         if (ret != LDB_SUCCESS) {
779                 return LDB_ERR_OPERATIONS_ERROR;
780         }
781
782         return ldb_next_request(ac->module, local_req);
783 }
784
785 static int map_rename_local_callback(struct ldb_request *req,
786                                      struct ldb_reply *ares)
787 {
788         struct ldb_context *ldb;
789         struct map_context *ac;
790         int ret;
791
792         ac = talloc_get_type(req->context, struct map_context);
793         ldb = ldb_module_get_ctx(ac->module);
794
795         if (!ares) {
796                 return ldb_module_done(ac->req, NULL, NULL,
797                                         LDB_ERR_OPERATIONS_ERROR);
798         }
799         if (ares->error != LDB_SUCCESS) {
800                 return ldb_module_done(ac->req, ares->controls,
801                                         ares->response, ares->error);
802         }
803
804         if (ares->type != LDB_REPLY_DONE) {
805                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
806                 return ldb_module_done(ac->req, NULL, NULL,
807                                         LDB_ERR_OPERATIONS_ERROR);
808         }
809
810         /* proceed with next step */
811         ret = map_rename_do_fixup(ac);
812         if (ret != LDB_SUCCESS) {
813                 return ldb_module_done(ac->req, NULL, NULL,
814                                         LDB_ERR_OPERATIONS_ERROR);
815         }
816
817         return LDB_SUCCESS;
818 }
819
820 /* Update the local 'IS_MAPPED' attribute. */
821 static int map_rename_do_fixup(struct map_context *ac)
822 {
823         struct ldb_request *local_req;
824
825         /* Prepare the fixup operation */
826         /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
827         local_req = map_build_fixup_req(ac,
828                                         ac->req->op.rename.newdn,
829                                         ac->remote_req->op.rename.newdn,
830                                         ac,
831                                         map_op_local_callback);
832         if (local_req == NULL) {
833                 return LDB_ERR_OPERATIONS_ERROR;
834         }
835
836         return ldb_next_request(ac->module, local_req);
837 }