root/source3/lib/ldb/modules/ldb_map_outbound.c

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

DEFINITIONS

This source file includes following definitions.
  1. map_attrs_select_local
  2. map_attrs_collect_remote
  3. map_attrs_partition
  4. ldb_msg_replace
  5. ldb_msg_el_map_remote
  6. ldb_msg_el_merge
  7. ldb_msg_el_merge_wildcard
  8. ldb_msg_merge_local
  9. ldb_msg_merge_remote
  10. map_reply_remote
  11. ldb_parse_tree_check_splittable
  12. ldb_parse_tree_collect_attrs
  13. map_subtree_select_local_not
  14. map_subtree_select_local_list
  15. map_subtree_select_local_simple
  16. map_subtree_select_local
  17. map_subtree_collect_remote_not
  18. map_subtree_collect_remote_list
  19. map_subtree_collect_remote_simple
  20. map_subtree_collect_remote
  21. ldb_parse_tree_partition
  22. map_attrs_collect_and_partition
  23. map_up_callback
  24. map_local_merge_callback
  25. map_remote_search_callback
  26. map_search

   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) Andrew Bartlett <abartlet@samba.org> 2006
   7 
   8    * NOTICE: this module is NOT released under the GNU LGPL license as
   9    * other ldb code. This module is release under the GNU GPL v2 or
  10    * later license.
  11 
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 3 of the License, or
  15    (at your option) any later version.
  16    
  17    This program 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
  20    GNU General Public License for more details.
  21    
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24 */
  25 
  26 #include "includes.h"
  27 #include "ldb/include/includes.h"
  28 
  29 #include "ldb/modules/ldb_map.h"
  30 #include "ldb/modules/ldb_map_private.h"
  31 
  32 
  33 /* Mapping attributes
  34  * ================== */
  35 
  36 /* Select attributes that stay in the local partition. */
  37 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
     /* [<][>][^][v][top][bottom][index][help] */
  38 {
  39         const struct ldb_map_context *data = map_get_context(module);
  40         const char **result;
  41         int i, last;
  42 
  43         if (attrs == NULL)
  44                 return NULL;
  45 
  46         last = 0;
  47         result = talloc_array(mem_ctx, const char *, 1);
  48         if (result == NULL) {
  49                 goto failed;
  50         }
  51         result[0] = NULL;
  52 
  53         for (i = 0; attrs[i]; i++) {
  54                 /* Wildcards and ignored attributes are kept locally */
  55                 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
  56                     (!map_attr_check_remote(data, attrs[i]))) {
  57                         result = talloc_realloc(mem_ctx, result, const char *, last+2);
  58                         if (result == NULL) {
  59                                 goto failed;
  60                         }
  61 
  62                         result[last] = talloc_strdup(result, attrs[i]);
  63                         result[last+1] = NULL;
  64                         last++;
  65                 }
  66         }
  67 
  68         return result;
  69 
  70 failed:
  71         talloc_free(result);
  72         map_oom(module);
  73         return NULL;
  74 }
  75 
  76 /* Collect attributes that are mapped into the remote partition. */
  77 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  78                                              const char * const *attrs)
  79 {
  80         const struct ldb_map_context *data = map_get_context(module);
  81         const char **result;
  82         const struct ldb_map_attribute *map;
  83         const char *name=NULL;
  84         int i, j, last;
  85         int ret;
  86 
  87         last = 0;
  88         result = talloc_array(mem_ctx, const char *, 1);
  89         if (result == NULL) {
  90                 goto failed;
  91         }
  92         result[0] = NULL;
  93 
  94         for (i = 0; attrs[i]; i++) {
  95                 /* Wildcards are kept remotely, too */
  96                 if (ldb_attr_cmp(attrs[i], "*") == 0) {
  97                         const char **new_attrs = NULL;
  98                         ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
  99                         if (ret != LDB_SUCCESS) {
 100                                 goto failed;
 101                         }
 102                         ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
 103                         if (ret != LDB_SUCCESS) {
 104                                 goto failed;
 105                         }
 106 
 107                         attrs = new_attrs;
 108                         break;
 109                 }
 110         }
 111 
 112         for (i = 0; attrs[i]; i++) {
 113                 /* Wildcards are kept remotely, too */
 114                 if (ldb_attr_cmp(attrs[i], "*") == 0) {
 115                         /* Add all 'include in wildcard' attributes */
 116                         name = attrs[i];
 117                         goto named;
 118                 }
 119 
 120                 /* Add remote names of mapped attrs */
 121                 map = map_attr_find_local(data, attrs[i]);
 122                 if (map == NULL) {
 123                         continue;
 124                 }
 125 
 126                 switch (map->type) {
 127                 case MAP_IGNORE:
 128                         continue;
 129 
 130                 case MAP_KEEP:
 131                         name = attrs[i];
 132                         goto named;
 133 
 134                 case MAP_RENAME:
 135                 case MAP_CONVERT:
 136                         name = map->u.rename.remote_name;
 137                         goto named;
 138 
 139                 case MAP_GENERATE:
 140                         /* Add all remote names of "generate" attrs */
 141                         for (j = 0; map->u.generate.remote_names[j]; j++) {
 142                                 result = talloc_realloc(mem_ctx, result, const char *, last+2);
 143                                 if (result == NULL) {
 144                                         goto failed;
 145                                 }
 146 
 147                                 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
 148                                 result[last+1] = NULL;
 149                                 last++;
 150                         }
 151                         continue;
 152                 }
 153 
 154         named:  /* We found a single remote name, add that */
 155                 result = talloc_realloc(mem_ctx, result, const char *, last+2);
 156                 if (result == NULL) {
 157                         goto failed;
 158                 }
 159 
 160                 result[last] = talloc_strdup(result, name);
 161                 result[last+1] = NULL;
 162                 last++;
 163         }
 164 
 165         return result;
 166 
 167 failed:
 168         talloc_free(result);
 169         map_oom(module);
 170         return NULL;
 171 }
 172 
 173 /* Split attributes that stay in the local partition from those that
 174  * are mapped into the remote partition. */
 175 static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
     /* [<][>][^][v][top][bottom][index][help] */
 176 {
 177         *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
 178         *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
 179 
 180         return 0;
 181 }
 182 
 183 /* Mapping message elements
 184  * ======================== */
 185 
 186 /* Add an element to a message, overwriting any old identically named elements. */
 187 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
     /* [<][>][^][v][top][bottom][index][help] */
 188 {
 189         struct ldb_message_element *old;
 190 
 191         old = ldb_msg_find_element(msg, el->name);
 192 
 193         /* no local result, add as new element */
 194         if (old == NULL) {
 195                 if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
 196                         return -1;
 197                 }
 198                 talloc_free(old->name);
 199         }
 200 
 201         /* copy new element */
 202         *old = *el;
 203 
 204         /* and make sure we reference the contents */
 205         if (!talloc_reference(msg->elements, el->name)) {
 206                 return -1;
 207         }
 208         if (!talloc_reference(msg->elements, el->values)) {
 209                 return -1;
 210         }
 211 
 212         return 0;
 213 }
 214 
 215 /* Map a message element back into the local partition. */
 216 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, 
     /* [<][>][^][v][top][bottom][index][help] */
 217                                                          void *mem_ctx, 
 218                                                          const struct ldb_map_attribute *map, 
 219                                                          const char *attr_name,
 220                                                          const struct ldb_message_element *old)
 221 {
 222         struct ldb_message_element *el;
 223         int i;
 224 
 225         el = talloc_zero(mem_ctx, struct ldb_message_element);
 226         if (el == NULL) {
 227                 map_oom(module);
 228                 return NULL;
 229         }
 230 
 231         el->num_values = old->num_values;
 232         el->values = talloc_array(el, struct ldb_val, el->num_values);
 233         if (el->values == NULL) {
 234                 talloc_free(el);
 235                 map_oom(module);
 236                 return NULL;
 237         }
 238 
 239         el->name = talloc_strdup(el, attr_name);
 240         if (el->name == NULL) {
 241                 talloc_free(el);
 242                 map_oom(module);
 243                 return NULL;
 244         }
 245 
 246         for (i = 0; i < el->num_values; i++) {
 247                 el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
 248         }
 249 
 250         return el;
 251 }
 252 
 253 /* Merge a remote message element into a local message. */
 254 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, 
     /* [<][>][^][v][top][bottom][index][help] */
 255                             struct ldb_message *remote, const char *attr_name)
 256 {
 257         const struct ldb_map_context *data = map_get_context(module);
 258         const struct ldb_map_attribute *map;
 259         struct ldb_message_element *old, *el=NULL;
 260         const char *remote_name = NULL;
 261 
 262         /* We handle wildcards in ldb_msg_el_merge_wildcard */
 263         if (ldb_attr_cmp(attr_name, "*") == 0) {
 264                 return 0;
 265         }
 266 
 267         map = map_attr_find_local(data, attr_name);
 268 
 269         /* Unknown attribute in remote message:
 270          * skip, attribute was probably auto-generated */
 271         if (map == NULL) {
 272                 return 0;
 273         }
 274 
 275         switch (map->type) {
 276         case MAP_IGNORE:
 277                 break;
 278         case MAP_CONVERT:
 279                 remote_name = map->u.convert.remote_name;
 280                 break;
 281         case MAP_KEEP:
 282                 remote_name = attr_name;
 283                 break;
 284         case MAP_RENAME:
 285                 remote_name = map->u.rename.remote_name;
 286                 break;
 287         case MAP_GENERATE:
 288                 break;
 289         }
 290 
 291         switch (map->type) {
 292         case MAP_IGNORE:
 293                 return 0;
 294 
 295         case MAP_CONVERT:
 296                 if (map->u.convert.convert_remote == NULL) {
 297                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
 298                                   "Skipping attribute '%s': "
 299                                   "'convert_remote' not set\n",
 300                                   attr_name);
 301                         return 0;
 302                 }
 303                 /* fall through */
 304         case MAP_KEEP:
 305         case MAP_RENAME:
 306                 old = ldb_msg_find_element(remote, remote_name);
 307                 if (old) {
 308                         el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
 309                 } else {
 310                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
 311                 }
 312                 break;
 313 
 314         case MAP_GENERATE:
 315                 if (map->u.generate.generate_local == NULL) {
 316                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
 317                                   "Skipping attribute '%s': "
 318                                   "'generate_local' not set\n",
 319                                   attr_name);
 320                         return 0;
 321                 }
 322 
 323                 el = map->u.generate.generate_local(module, local, attr_name, remote);
 324                 if (!el) {
 325                         /* Generation failure is probably due to lack of source attributes */
 326                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
 327                 }
 328                 break;
 329         }
 330 
 331         if (el == NULL) {
 332                 return LDB_ERR_OPERATIONS_ERROR;
 333         }
 334 
 335         return ldb_msg_replace(local, el);
 336 }
 337 
 338 /* Handle wildcard parts of merging a remote message element into a local message. */
 339 static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local, 
     /* [<][>][^][v][top][bottom][index][help] */
 340                                      struct ldb_message *remote)
 341 {
 342         const struct ldb_map_context *data = map_get_context(module);
 343         const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
 344         struct ldb_message_element *el=NULL;
 345         int i, ret;
 346 
 347         /* Perhaps we have a mapping for "*" */
 348         if (map && map->type == MAP_KEEP) {
 349                 /* We copy everything over, and hope that anything with a 
 350                    more specific rule is overwritten */
 351                 for (i = 0; i < remote->num_elements; i++) {
 352                         el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
 353                                                    &remote->elements[i]);
 354                         if (el == NULL) {
 355                                 return LDB_ERR_OPERATIONS_ERROR;
 356                         }
 357                         
 358                         ret = ldb_msg_replace(local, el);
 359                         if (ret) {
 360                                 return ret;
 361                         }
 362                 }
 363         }
 364         
 365         /* Now walk the list of possible mappings, and apply each */
 366         for (i = 0; data->attribute_maps[i].local_name; i++) {
 367                 ret = ldb_msg_el_merge(module, local, remote, 
 368                                        data->attribute_maps[i].local_name);
 369                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
 370                         continue;
 371                 } else if (ret) {
 372                         return ret;
 373                 } else {
 374                         continue;
 375                 }
 376         }
 377 
 378         return 0;
 379 }
 380 
 381 /* Mapping messages
 382  * ================ */
 383 
 384 /* Merge two local messages into a single one. */
 385 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
     /* [<][>][^][v][top][bottom][index][help] */
 386 {
 387         int i, ret;
 388 
 389         for (i = 0; i < msg2->num_elements; i++) {
 390                 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
 391                 if (ret) {
 392                         return ret;
 393                 }
 394         }
 395 
 396         return 0;
 397 }
 398 
 399 /* Merge a local and a remote message into a single local one. */
 400 static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local, 
     /* [<][>][^][v][top][bottom][index][help] */
 401                                 struct ldb_message *remote)
 402 {
 403         int i, ret;
 404         const char * const *attrs = ac->all_attrs;
 405         if (!attrs) {
 406                 ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
 407                 if (ret) {
 408                         return ret;
 409                 }
 410         }
 411 
 412         for (i = 0; attrs && attrs[i]; i++) {
 413                 if (ldb_attr_cmp(attrs[i], "*") == 0) {
 414                         ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
 415                         if (ret) {
 416                                 return ret;
 417                         }
 418                         break;
 419                 }
 420         }
 421 
 422         /* Try to map each attribute back;
 423          * Add to local message is possible,
 424          * Overwrite old local attribute if necessary */
 425         for (i = 0; attrs && attrs[i]; i++) {
 426                 ret = ldb_msg_el_merge(ac->module, local, remote, 
 427                                        attrs[i]);
 428                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
 429                 } else if (ret) {
 430                         return ret;
 431                 }
 432         }
 433 
 434         return 0;
 435 }
 436 
 437 /* Mapping search results
 438  * ====================== */
 439 
 440 /* Map a search result back into the local partition. */
 441 static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
 442 {
 443         struct ldb_message *msg;
 444         struct ldb_dn *dn;
 445         int ret;
 446 
 447         /* There is no result message, skip */
 448         if (ares->type != LDB_REPLY_ENTRY) {
 449                 return 0;
 450         }
 451 
 452         /* Create a new result message */
 453         msg = ldb_msg_new(ares);
 454         if (msg == NULL) {
 455                 map_oom(ac->module);
 456                 return -1;
 457         }
 458 
 459         /* Merge remote message into new message */
 460         ret = ldb_msg_merge_remote(ac, msg, ares->message);
 461         if (ret) {
 462                 talloc_free(msg);
 463                 return ret;
 464         }
 465 
 466         /* Create corresponding local DN */
 467         dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
 468         if (dn == NULL) {
 469                 talloc_free(msg);
 470                 return -1;
 471         }
 472         msg->dn = dn;
 473 
 474         /* Store new message with new DN as the result */
 475         talloc_free(ares->message);
 476         ares->message = msg;
 477 
 478         return 0;
 479 }
 480 
 481 /* Mapping parse trees
 482  * =================== */
 483 
 484 /* Check whether a parse tree can safely be split in two. */
 485 static BOOL ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 486 {
 487         const struct ldb_parse_tree *subtree = tree;
 488         BOOL negate = False;
 489 
 490         while (subtree) {
 491                 switch (subtree->operation) {
 492                 case LDB_OP_NOT:
 493                         negate = !negate;
 494                         subtree = subtree->u.isnot.child;
 495                         continue;
 496 
 497                 case LDB_OP_AND:
 498                         return !negate; /* if negate: False */
 499 
 500                 case LDB_OP_OR:
 501                         return negate;  /* if negate: True */
 502 
 503                 default:
 504                         return True;    /* simple parse tree */
 505                 }
 506         }
 507 
 508         return True;                    /* no parse tree */
 509 }
 510 
 511 /* Collect a list of attributes required to match a given parse tree. */
 512 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 513 {
 514         const char **new_attrs;
 515         int i, ret;
 516 
 517         if (tree == NULL) {
 518                 return 0;
 519         }
 520 
 521         switch (tree->operation) {
 522         case LDB_OP_OR:
 523         case LDB_OP_AND:                /* attributes stored in list of subtrees */
 524                 for (i = 0; i < tree->u.list.num_elements; i++) {
 525                         ret = ldb_parse_tree_collect_attrs(module, mem_ctx, 
 526                                                            attrs, tree->u.list.elements[i]);
 527                         if (ret) {
 528                                 return ret;
 529                         }
 530                 }
 531                 return 0;
 532 
 533         case LDB_OP_NOT:                /* attributes stored in single subtree */
 534                 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
 535 
 536         default:                        /* single attribute in tree */
 537                 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
 538                 talloc_free(*attrs);
 539                 *attrs = new_attrs;
 540                 return 0;
 541         }
 542 
 543         return -1;
 544 }
 545 
 546 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
 547 
 548 /* Select a negated subtree that queries attributes in the local partition */
 549 static int map_subtree_select_local_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 550 {
 551         struct ldb_parse_tree *child;
 552         int ret;
 553 
 554         /* Prepare new tree */
 555         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
 556         if (*new == NULL) {
 557                 map_oom(module);
 558                 return -1;
 559         }
 560 
 561         /* Generate new subtree */
 562         ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
 563         if (ret) {
 564                 talloc_free(*new);
 565                 return ret;
 566         }
 567 
 568         /* Prune tree without subtree */
 569         if (child == NULL) {
 570                 talloc_free(*new);
 571                 *new = NULL;
 572                 return 0;
 573         }
 574 
 575         (*new)->u.isnot.child = child;
 576 
 577         return ret;
 578 }
 579 
 580 /* Select a list of subtrees that query attributes in the local partition */
 581 static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 582 {
 583         int i, j, ret=0;
 584 
 585         /* Prepare new tree */
 586         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
 587         if (*new == NULL) {
 588                 map_oom(module);
 589                 return -1;
 590         }
 591 
 592         /* Prepare list of subtrees */
 593         (*new)->u.list.num_elements = 0;
 594         (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
 595         if ((*new)->u.list.elements == NULL) {
 596                 map_oom(module);
 597                 talloc_free(*new);
 598                 return -1;
 599         }
 600 
 601         /* Generate new list of subtrees */
 602         j = 0;
 603         for (i = 0; i < tree->u.list.num_elements; i++) {
 604                 struct ldb_parse_tree *child;
 605                 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
 606                 if (ret) {
 607                         talloc_free(*new);
 608                         return ret;
 609                 }
 610 
 611                 if (child) {
 612                         (*new)->u.list.elements[j] = child;
 613                         j++;
 614                 }
 615         }
 616 
 617         /* Prune tree without subtrees */
 618         if (j == 0) {
 619                 talloc_free(*new);
 620                 *new = NULL;
 621                 return 0;
 622         }
 623 
 624         /* Fix subtree list size */
 625         (*new)->u.list.num_elements = j;
 626         (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
 627 
 628         return ret;
 629 }
 630 
 631 /* Select a simple subtree that queries attributes in the local partition */
 632 static int map_subtree_select_local_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 633 {
 634         /* Prepare new tree */
 635         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
 636         if (*new == NULL) {
 637                 map_oom(module);
 638                 return -1;
 639         }
 640 
 641         return 0;
 642 }
 643 
 644 /* Select subtrees that query attributes in the local partition */
 645 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 646 {
 647         const struct ldb_map_context *data = map_get_context(module);
 648 
 649         if (tree == NULL) {
 650                 return 0;
 651         }
 652 
 653         if (tree->operation == LDB_OP_NOT) {
 654                 return map_subtree_select_local_not(module, mem_ctx, new, tree);
 655         }
 656 
 657         if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
 658                 return map_subtree_select_local_list(module, mem_ctx, new, tree);
 659         }
 660 
 661         if (map_attr_check_remote(data, tree->u.equality.attr)) {
 662                 *new = NULL;
 663                 return 0;
 664         }
 665 
 666         return map_subtree_select_local_simple(module, mem_ctx, new, tree);
 667 }
 668 
 669 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
 670 
 671 /* Collect a negated subtree that queries attributes in the remote partition */
 672 static int map_subtree_collect_remote_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 673 {
 674         struct ldb_parse_tree *child;
 675         int ret;
 676 
 677         /* Prepare new tree */
 678         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
 679         if (*new == NULL) {
 680                 map_oom(module);
 681                 return -1;
 682         }
 683 
 684         /* Generate new subtree */
 685         ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
 686         if (ret) {
 687                 talloc_free(*new);
 688                 return ret;
 689         }
 690 
 691         /* Prune tree without subtree */
 692         if (child == NULL) {
 693                 talloc_free(*new);
 694                 *new = NULL;
 695                 return 0;
 696         }
 697 
 698         (*new)->u.isnot.child = child;
 699 
 700         return ret;
 701 }
 702 
 703 /* Collect a list of subtrees that query attributes in the remote partition */
 704 static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 705 {
 706         int i, j, ret=0;
 707 
 708         /* Prepare new tree */
 709         *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
 710         if (*new == NULL) {
 711                 map_oom(module);
 712                 return -1;
 713         }
 714 
 715         /* Prepare list of subtrees */
 716         (*new)->u.list.num_elements = 0;
 717         (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
 718         if ((*new)->u.list.elements == NULL) {
 719                 map_oom(module);
 720                 talloc_free(*new);
 721                 return -1;
 722         }
 723 
 724         /* Generate new list of subtrees */
 725         j = 0;
 726         for (i = 0; i < tree->u.list.num_elements; i++) {
 727                 struct ldb_parse_tree *child;
 728                 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
 729                 if (ret) {
 730                         talloc_free(*new);
 731                         return ret;
 732                 }
 733 
 734                 if (child) {
 735                         (*new)->u.list.elements[j] = child;
 736                         j++;
 737                 }
 738         }
 739 
 740         /* Prune tree without subtrees */
 741         if (j == 0) {
 742                 talloc_free(*new);
 743                 *new = NULL;
 744                 return 0;
 745         }
 746 
 747         /* Fix subtree list size */
 748         (*new)->u.list.num_elements = j;
 749         (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
 750 
 751         return ret;
 752 }
 753 
 754 /* Collect a simple subtree that queries attributes in the remote partition */
 755 int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree, const struct ldb_map_attribute *map)
     /* [<][>][^][v][top][bottom][index][help] */
 756 {
 757         const char *attr;
 758 
 759         /* Prepare new tree */
 760         *new = talloc(mem_ctx, struct ldb_parse_tree);
 761         if (*new == NULL) {
 762                 map_oom(module);
 763                 return -1;
 764         }
 765         **new = *tree;
 766         
 767         if (map->type == MAP_KEEP) {
 768                 /* Nothing to do here */
 769                 return 0;
 770         }
 771 
 772         /* Store attribute and value in new tree */
 773         switch (tree->operation) {
 774         case LDB_OP_PRESENT:
 775                 attr = map_attr_map_local(*new, map, tree->u.present.attr);
 776                 (*new)->u.present.attr = attr;
 777                 break;
 778         case LDB_OP_SUBSTRING:
 779         {
 780                 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
 781                 (*new)->u.substring.attr = attr;
 782                 break;
 783         }
 784         case LDB_OP_EQUALITY:
 785                 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
 786                 (*new)->u.equality.attr = attr;
 787                 break;
 788         case LDB_OP_LESS:
 789         case LDB_OP_GREATER:
 790         case LDB_OP_APPROX:
 791                 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
 792                 (*new)->u.comparison.attr = attr;
 793                 break;
 794         case LDB_OP_EXTENDED:
 795                 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
 796                 (*new)->u.extended.attr = attr;
 797                 break;
 798         default:                        /* unknown kind of simple subtree */
 799                 talloc_free(*new);
 800                 return -1;
 801         }
 802 
 803         if (attr == NULL) {
 804                 talloc_free(*new);
 805                 *new = NULL;
 806                 return 0;
 807         }
 808 
 809         if (map->type == MAP_RENAME) {
 810                 /* Nothing more to do here, the attribute has been renamed */
 811                 return 0;
 812         }
 813 
 814         /* Store attribute and value in new tree */
 815         switch (tree->operation) {
 816         case LDB_OP_PRESENT:
 817                 break;
 818         case LDB_OP_SUBSTRING:
 819         {
 820                 int i;
 821                 /* Map value */
 822                 (*new)->u.substring.chunks = NULL;
 823                 for (i=0; tree->u.substring.chunks[i]; i++) {
 824                         (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
 825                         if (!(*new)->u.substring.chunks) {
 826                                 talloc_free(*new);
 827                                 *new = NULL;
 828                                 return 0;
 829                         }
 830                         (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
 831                         if (!(*new)->u.substring.chunks[i]) {
 832                                 talloc_free(*new);
 833                                 *new = NULL;
 834                                 return 0;
 835                         }
 836                         *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
 837                         (*new)->u.substring.chunks[i+1] = NULL;
 838                 }
 839                 break;
 840         }
 841         case LDB_OP_EQUALITY:
 842                 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
 843                 break;
 844         case LDB_OP_LESS:
 845         case LDB_OP_GREATER:
 846         case LDB_OP_APPROX:
 847                 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
 848                 break;
 849         case LDB_OP_EXTENDED:
 850                 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
 851                 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
 852                 break;
 853         default:                        /* unknown kind of simple subtree */
 854                 talloc_free(*new);
 855                 return -1;
 856         }
 857 
 858         return 0;
 859 }
 860 
 861 /* Collect subtrees that query attributes in the remote partition */
 862 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 863 {
 864         const struct ldb_map_context *data = map_get_context(module);
 865         const struct ldb_map_attribute *map;
 866 
 867         if (tree == NULL) {
 868                 return 0;
 869         }
 870 
 871         if (tree->operation == LDB_OP_NOT) {
 872                 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
 873         }
 874 
 875         if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
 876                 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
 877         }
 878 
 879         if (!map_attr_check_remote(data, tree->u.equality.attr)) {
 880                 *new = NULL;
 881                 return 0;
 882         }
 883 
 884         map = map_attr_find_local(data, tree->u.equality.attr);
 885         if (map->convert_operator) {
 886                 return map->convert_operator(module, mem_ctx, new, tree);
 887         }
 888 
 889         if (map->type == MAP_GENERATE) {
 890                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
 891                           "Skipping attribute '%s': "
 892                           "'convert_operator' not set\n",
 893                           tree->u.equality.attr);
 894                 *new = NULL;
 895                 return 0;
 896         }
 897 
 898         return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
 899 }
 900 
 901 /* Split subtrees that query attributes in the local partition from
 902  * those that query the remote partition. */
 903 static int ldb_parse_tree_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, struct ldb_parse_tree **local_tree, struct ldb_parse_tree **remote_tree, const struct ldb_parse_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 904 {
 905         int ret;
 906 
 907         *local_tree = NULL;
 908         *remote_tree = NULL;
 909 
 910         /* No original tree */
 911         if (tree == NULL) {
 912                 return 0;
 913         }
 914 
 915         /* Generate local tree */
 916         ret = map_subtree_select_local(module, local_ctx, local_tree, tree);
 917         if (ret) {
 918                 return ret;
 919         }
 920 
 921         /* Generate remote tree */
 922         ret = map_subtree_collect_remote(module, remote_ctx, remote_tree, tree);
 923         if (ret) {
 924                 talloc_free(*local_tree);
 925                 return ret;
 926         }
 927 
 928         return 0;
 929 }
 930 
 931 /* Collect a list of attributes required either explicitly from a
 932  * given list or implicitly  from a given parse tree; split the
 933  * collected list into local and remote parts. */
 934 static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
     /* [<][>][^][v][top][bottom][index][help] */
 935                                            const char * const *search_attrs, 
 936                                            const struct ldb_parse_tree *tree)
 937 {
 938         void *tmp_ctx;
 939         const char **tree_attrs;
 940         const char **remote_attrs;
 941         const char **local_attrs;
 942         int ret;
 943 
 944         /* Clear initial lists of partitioned attributes */
 945 
 946         /* Clear initial lists of partitioned attributes */
 947 
 948         /* There is no tree, just partition the searched attributes */
 949         if (tree == NULL) {
 950                 ret = map_attrs_partition(module, ac, 
 951                                           &local_attrs, &remote_attrs, search_attrs);
 952                 if (ret == 0) {
 953                         ac->local_attrs = local_attrs;
 954                         ac->remote_attrs = remote_attrs;
 955                         ac->all_attrs = search_attrs;
 956                 }
 957                 return ret; 
 958         }
 959 
 960         /* Create context for temporary memory */
 961         tmp_ctx = talloc_new(ac);
 962         if (tmp_ctx == NULL) {
 963                 goto oom;
 964         }
 965 
 966         /* Prepare list of attributes from tree */
 967         tree_attrs = talloc_array(tmp_ctx, const char *, 1);
 968         if (tree_attrs == NULL) {
 969                 talloc_free(tmp_ctx);
 970                 goto oom;
 971         }
 972         tree_attrs[0] = NULL;
 973 
 974         /* Collect attributes from tree */
 975         ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
 976         if (ret) {
 977                 goto done;
 978         }
 979 
 980         /* Merge attributes from search operation */
 981         ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
 982         if (ret) {
 983                 goto done;
 984         }
 985 
 986         /* Split local from remote attributes */
 987         ret = map_attrs_partition(module, ac, &local_attrs, 
 988                                   &remote_attrs, tree_attrs);
 989         
 990         if (ret == 0) {
 991                 ac->local_attrs = local_attrs;
 992                 ac->remote_attrs = remote_attrs;
 993                 talloc_steal(ac, tree_attrs);
 994                 ac->all_attrs = tree_attrs;
 995         }
 996 done:
 997         /* Free temporary memory */
 998         talloc_free(tmp_ctx);
 999         return ret;
1000 
1001 oom:
1002         map_oom(module);
1003         return -1;
1004 }
1005 
1006 
1007 /* Outbound requests: search
1008  * ========================= */
1009 
1010 /* Pass a merged search result up the callback chain. */
1011 int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
1012 {
1013         int i;
1014 
1015         /* No callback registered, stop */
1016         if (req->callback == NULL) {
1017                 return LDB_SUCCESS;
1018         }
1019 
1020         /* Only records need special treatment */
1021         if (ares->type != LDB_REPLY_ENTRY) {
1022                 return req->callback(ldb, req->context, ares);
1023         }
1024 
1025         /* Merged result doesn't match original query, skip */
1026         if (!ldb_match_msg(ldb, ares->message, req->op.search.tree, req->op.search.base, req->op.search.scope)) {
1027                 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
1028                           "Skipping record '%s': "
1029                           "doesn't match original search\n",
1030                           ldb_dn_linearize(ldb, ares->message->dn));
1031                 return LDB_SUCCESS;
1032         }
1033 
1034         /* Limit result to requested attrs */
1035         if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) {
1036                 for (i = 0; i < ares->message->num_elements; ) {
1037                         struct ldb_message_element *el = &ares->message->elements[i];
1038                         if (!ldb_attr_in_list(req->op.search.attrs, el->name)) {
1039                                 ldb_msg_remove_element(ares->message, el);
1040                         } else {
1041                                 i++;
1042                         }
1043                 }
1044         }
1045 
1046         return req->callback(ldb, req->context, ares);
1047 }
1048 
1049 /* Merge the remote and local parts of a search result. */
1050 int map_local_merge_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
1051 {
1052         struct map_search_context *sc;
1053         int ret;
1054 
1055         if (context == NULL || ares == NULL) {
1056                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1057                                                        "NULL Context or Result in `map_local_merge_callback`"));
1058                 return LDB_ERR_OPERATIONS_ERROR;
1059         }
1060 
1061         sc = talloc_get_type(context, struct map_search_context);
1062 
1063         switch (ares->type) {
1064         case LDB_REPLY_ENTRY:
1065                 /* We have already found a local record */
1066                 if (sc->local_res) {
1067                         ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1068                                                                "Too many results to base search for local entry"));
1069                         talloc_free(ares);
1070                         return LDB_ERR_OPERATIONS_ERROR;
1071                 }
1072 
1073                 /* Store local result */
1074                 sc->local_res = ares;
1075 
1076                 /* Merge remote into local message */
1077                 ret = ldb_msg_merge_local(sc->ac->module, ares->message, sc->remote_res->message);
1078                 if (ret) {
1079                         talloc_free(ares);
1080                         return LDB_ERR_OPERATIONS_ERROR;
1081                 }
1082 
1083                 return map_up_callback(ldb, sc->ac->orig_req, ares);
1084 
1085         case LDB_REPLY_DONE:
1086                 /* No local record found, continue with remote record */
1087                 if (sc->local_res == NULL) {
1088                         return map_up_callback(ldb, sc->ac->orig_req, sc->remote_res);
1089                 }
1090                 return LDB_SUCCESS;
1091 
1092         default:
1093                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1094                                                        "Unexpected result type in base search for local entry"));
1095                 talloc_free(ares);
1096                 return LDB_ERR_OPERATIONS_ERROR;
1097         }
1098 }
1099 
1100 /* Search the local part of a remote search result. */
1101 int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
1102 {
1103         struct map_context *ac;
1104         struct map_search_context *sc;
1105         struct ldb_request *req;
1106         int ret;
1107 
1108         if (context == NULL || ares == NULL) {
1109                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
1110                                                        "NULL Context or Result in `map_remote_search_callback`"));
1111                 return LDB_ERR_OPERATIONS_ERROR;
1112         }
1113 
1114         ac = talloc_get_type(context, struct map_context);
1115 
1116         /* It's not a record, stop searching */
1117         if (ares->type != LDB_REPLY_ENTRY) {
1118                 return map_up_callback(ldb, ac->orig_req, ares);
1119         }
1120 
1121         /* Map result record into a local message */
1122         ret = map_reply_remote(ac, ares);
1123         if (ret) {
1124                 talloc_free(ares);
1125                 return LDB_ERR_OPERATIONS_ERROR;
1126         }
1127 
1128         /* There is no local db, stop searching */
1129         if (!map_check_local_db(ac->module)) {
1130                 return map_up_callback(ldb, ac->orig_req, ares);
1131         }
1132 
1133         /* Prepare local search context */
1134         sc = map_init_search_context(ac, ares);
1135         if (sc == NULL) {
1136                 talloc_free(ares);
1137                 return LDB_ERR_OPERATIONS_ERROR;
1138         }
1139 
1140         /* Prepare local search request */
1141         /* TODO: use GUIDs here instead? */
1142 
1143         ac->search_reqs = talloc_realloc(ac, ac->search_reqs, struct ldb_request *, ac->num_searches + 2);
1144         if (ac->search_reqs == NULL) {
1145                 talloc_free(ares);
1146                 return LDB_ERR_OPERATIONS_ERROR;
1147         }
1148 
1149         ac->search_reqs[ac->num_searches]
1150                 = req = map_search_base_req(ac, ares->message->dn, 
1151                                             NULL, NULL, sc, map_local_merge_callback);
1152         if (req == NULL) {
1153                 talloc_free(sc);
1154                 talloc_free(ares);
1155                 return LDB_ERR_OPERATIONS_ERROR;
1156         }
1157         ac->num_searches++;
1158         ac->search_reqs[ac->num_searches] = NULL;
1159 
1160         return ldb_next_request(ac->module, req);
1161 }
1162 
1163 /* Search a record. */
1164 int map_search(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1165 {
1166         struct ldb_handle *h;
1167         struct map_context *ac;
1168         struct ldb_parse_tree *local_tree, *remote_tree;
1169         int ret;
1170 
1171         const char *wildcard[] = { "*", NULL };
1172         const char * const *attrs;
1173 
1174         /* Do not manipulate our control entries */
1175         if (ldb_dn_is_special(req->op.search.base))
1176                 return ldb_next_request(module, req);
1177 
1178         /* No mapping requested, skip to next module */
1179         if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1180                 return ldb_next_request(module, req);
1181         }
1182 
1183         /* TODO: How can we be sure about which partition we are
1184          *       targetting when there is no search base? */
1185 
1186         /* Prepare context and handle */
1187         h = map_init_handle(req, module);
1188         if (h == NULL) {
1189                 return LDB_ERR_OPERATIONS_ERROR;
1190         }
1191         ac = talloc_get_type(h->private_data, struct map_context);
1192 
1193         ac->search_reqs = talloc_array(ac, struct ldb_request *, 2);
1194         if (ac->search_reqs == NULL) {
1195                 talloc_free(h);
1196                 return LDB_ERR_OPERATIONS_ERROR;
1197         }
1198         ac->num_searches = 1;
1199         ac->search_reqs[1] = NULL;
1200 
1201         /* Prepare the remote operation */
1202         ac->search_reqs[0] = talloc(ac, struct ldb_request);
1203         if (ac->search_reqs[0] == NULL) {
1204                 goto oom;
1205         }
1206 
1207         *(ac->search_reqs[0]) = *req;   /* copy the request */
1208 
1209         ac->search_reqs[0]->handle = h; /* return our own handle to deal with this call */
1210 
1211         ac->search_reqs[0]->context = ac;
1212         ac->search_reqs[0]->callback = map_remote_search_callback;
1213 
1214         /* It is easier to deal with the two different ways of
1215          * expressing the wildcard in the same codepath */
1216         attrs = req->op.search.attrs;
1217         if (attrs == NULL) {
1218                 attrs = wildcard;
1219         }
1220 
1221         /* Split local from remote attrs */
1222         ret = map_attrs_collect_and_partition(module, ac, 
1223                                               attrs, req->op.search.tree);
1224         if (ret) {
1225                 goto failed;
1226         }
1227 
1228         ac->search_reqs[0]->op.search.attrs = ac->remote_attrs;
1229 
1230         /* Split local from remote tree */
1231         ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], 
1232                                        &local_tree, &remote_tree, 
1233                                        req->op.search.tree);
1234         if (ret) {
1235                 goto failed;
1236         }
1237 
1238         if (((local_tree != NULL) && (remote_tree != NULL)) &&
1239             (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1240                 /* The query can't safely be split, enumerate the remote partition */
1241                 local_tree = NULL;
1242                 remote_tree = NULL;
1243         }
1244 
1245         if (local_tree == NULL) {
1246                 /* Construct default local parse tree */
1247                 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1248                 if (local_tree == NULL) {
1249                         map_oom(ac->module);
1250                         goto failed;
1251                 }
1252 
1253                 local_tree->operation = LDB_OP_PRESENT;
1254                 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1255         }
1256         if (remote_tree == NULL) {
1257                 /* Construct default remote parse tree */
1258                 remote_tree = ldb_parse_tree(ac->search_reqs[0], NULL);
1259                 if (remote_tree == NULL) {
1260                         goto failed;
1261                 }
1262         }
1263 
1264         ac->local_tree = local_tree;
1265         ac->search_reqs[0]->op.search.tree = remote_tree;
1266 
1267         ldb_set_timeout_from_prev_req(module->ldb, req, ac->search_reqs[0]);
1268 
1269         h->state = LDB_ASYNC_INIT;
1270         h->status = LDB_SUCCESS;
1271 
1272         ac->step = MAP_SEARCH_REMOTE;
1273 
1274         ret = ldb_next_remote_request(module, ac->search_reqs[0]);
1275         if (ret == LDB_SUCCESS) {
1276                 req->handle = h;
1277         }
1278         return ret;
1279 
1280 oom:
1281         map_oom(module);
1282 failed:
1283         talloc_free(h);
1284         return LDB_ERR_OPERATIONS_ERROR;
1285 }

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