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