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