root/source4/lib/ldb/ldb_map/ldb_map_inbound.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ldb_msg_el_map_local
  2. ldb_msg_el_partition
  3. ldb_msg_check_remote
  4. ldb_msg_partition
  5. map_search_self_callback
  6. map_search_self_req
  7. map_op_local_callback
  8. map_op_remote_callback
  9. map_add
  10. map_add_do_local
  11. map_modify
  12. map_modify_do_local
  13. map_delete
  14. map_delete_do_local
  15. map_rename
  16. map_rename_do_local
  17. map_rename_local_callback
  18. map_rename_do_fixup

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

/* [<][>][^][v][top][bottom][index][help] */