r19731: Modify the ldb_map infrustructure to always map from requested
authorAndrew Bartlett <abartlet@samba.org>
Thu, 16 Nov 2006 09:16:17 +0000 (09:16 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:28:15 +0000 (14:28 -0500)
attributes to backend (remote) attributes.

We can't do a reverse mapping safely where the remote attribute may be
a source for multiple local attributes.  (We end up with the wrong
attributes returned).

In doing this, I've modified the samba3sam.js test to be more
realistic, and fixed some failures in the handling of primaryGroupID.

I've added a new (private) helper function ldb_msg_remove_element() to
avoid a double lookup of the element name.

I've also re-formatted many of the function headers, to fit into
standard editor widths.

Andrew Bartlett
(This used to be commit 186766e3095e71ba716c69e681592e217a3bc420)

source4/dsdb/samdb/ldb_modules/samba3sam.c
source4/lib/ldb/common/ldb_msg.c
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/modules/ldb_map.c
source4/lib/ldb/modules/ldb_map_outbound.c
source4/lib/ldb/modules/ldb_map_private.h
testprogs/ejs/samba3sam.js

index 341fad4bd97af707dae2e705e49ee3984d4220af..6c7c3c70662a7ceb966df01a447f24f2c4d58936 100644 (file)
 /* In Samba4 but not in Samba3:
 */
 
-static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote)
+/* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
+static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *local_attr, const struct ldb_message *remote)
 {
        struct ldb_message_element *el;
-       const char *sid = ldb_msg_find_attr_as_string(remote, attr, NULL);
-
+       const char *sid = ldb_msg_find_attr_as_string(remote, "sambaPrimaryGroupSID", NULL);
+       const char *p;
+       
        if (!sid)
                return NULL;
 
-       if (strchr(sid, '-') == NULL)
+       p = strrchr(sid, '-');
+       if (!p)
                return NULL;
 
        el = talloc_zero(ctx, struct ldb_message_element);
        el->name = talloc_strdup(ctx, "primaryGroupID");
        el->num_values = 1;
        el->values = talloc_array(ctx, struct ldb_val, 1);
-       el->values[0].data = (uint8_t *)talloc_strdup(el->values, strchr(sid, '-')+1);
+       el->values[0].data = (uint8_t *)talloc_strdup(el->values, strrchr(sid, '-')+1);
        el->values[0].length = strlen((char *)el->values[0].data);
 
        return el;
@@ -80,6 +83,7 @@ static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char
        struct dom_sid *sid;
        NTSTATUS status;
 
+       /* We need the domain, so we get it from the objectSid that we hope is here... */
        sidval = ldb_msg_find_ldb_val(local, "objectSid");
 
        if (!sidval) 
index 9cb4cf5ed04edf6a47d6e90f248db425c6c7a9b3..65d1ecacb7a98ee502a5e94ccd99587371af9bfd 100644 (file)
@@ -654,7 +654,7 @@ const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
 
 /*
   copy an attribute list. This only copies the array, not the elements
-  (ie. the elements are left as the same pointers)
+  (ie. the elements are left as the same pointers).  The new attribute is added to the list.
 */
 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
 {
@@ -737,6 +737,18 @@ void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
        }
 }
 
+/*
+  remove the specified element in a search result
+*/
+void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
+{
+       int n = (el - msg->elements);
+       if (n != msg->num_elements-1) {
+               memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
+       }
+       msg->num_elements--;
+}
+
 /*
   return a LDAP formatted time string
 */
index 3902bb2fc28f275669c9c01def3e05efe43a1372..f4049188ad3bbb5a9be8b201478a1023f7e8bb32 100644 (file)
@@ -211,6 +211,8 @@ int check_critical_controls(struct ldb_control **controls);
 /* The following definitions come from lib/ldb/common/ldb_utf8.c */
 char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
 
+void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
+
 /**
   Obtain current/next database sequence number
 */
index 32e64f3eb2cf1fd8c15f95cc2905acaf1ac2fda4..bbd7b9603dececbb7a37ae2d4888135066dcad7d 100644 (file)
@@ -390,13 +390,14 @@ const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *m
 
 
 /* Merge two lists of attributes into a single one. */
-int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attrs, const char * const *more_attrs)
+int map_attrs_merge(struct ldb_module *module, void *mem_ctx, 
+                   const char ***attrs, const char * const *more_attrs)
 {
        int i, j, k;
 
        for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ;
        for (j = 0; more_attrs && more_attrs[j]; j++) /* noop */ ;
-
+       
        *attrs = talloc_realloc(mem_ctx, *attrs, const char *, i+j+1);
        if (*attrs == NULL) {
                map_oom(module);
@@ -404,7 +405,7 @@ int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attr
        }
 
        for (k = 0; k < j; k++) {
-               (*attrs)[i+k] = more_attrs[k];
+               (*attrs)[i + k] = more_attrs[k];
        }
 
        (*attrs)[i+k] = NULL;
@@ -416,7 +417,8 @@ int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attr
  * ================== */
 
 /* Map an ldb value into the remote partition. */
-struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val)
+struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, 
+                                const struct ldb_map_attribute *map, const struct ldb_val *val)
 {
        if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_local)) {
                return map->u.convert.convert_local(module, mem_ctx, val);
@@ -426,7 +428,8 @@ struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const
 }
 
 /* Map an ldb value back into the local partition. */
-struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val)
+struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, 
+                                 const struct ldb_map_attribute *map, const struct ldb_val *val)
 {
        if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_remote)) {
                return map->u.convert.convert_remote(module, mem_ctx, val);
@@ -679,7 +682,7 @@ static void map_objectclass_generate_remote(struct ldb_module *module, const cha
        int i;
 
        /* Find old local objectClass */
-       oc = ldb_msg_find_element(old, local_attr);
+       oc = ldb_msg_find_element(old, "objectClass");
        if (oc == NULL) {
                return;
        }
@@ -743,14 +746,14 @@ static struct ldb_val map_objectclass_convert_remote(struct ldb_module *module,
 }
 
 /* Generate a local message with a mapped objectClass. */
-static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *remote_attr, const struct ldb_message *remote)
+static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *local_attr, const struct ldb_message *remote)
 {
        struct ldb_message_element *el, *oc;
        struct ldb_val val;
        int i;
 
        /* Find old remote objectClass */
-       oc = ldb_msg_find_element(remote, remote_attr);
+       oc = ldb_msg_find_element(remote, "objectClass");
        if (oc == NULL) {
                return NULL;
        }
@@ -772,7 +775,7 @@ static struct ldb_message_element *map_objectclass_generate_local(struct ldb_mod
        }
 
        /* Copy remote element name "objectClass" */
-       el->name = talloc_strdup(el, remote_attr);
+       el->name = talloc_strdup(el, local_attr);
 
        /* Convert all remote objectClasses */
        for (i = 0; i < el->num_values; i++) {
index dc213f36d183953bc8e222ab9eece98f85d92dbc..505df795337340780aabc11f57a6536ea1f80282 100644 (file)
@@ -75,7 +75,8 @@ failed:
 }
 
 /* Collect attributes that are mapped into the remote partition. */
-static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
+static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, 
+                                            const char * const *attrs)
 {
        const struct ldb_map_context *data = map_get_context(module);
        const char **result;
@@ -172,10 +173,10 @@ failed:
 
 /* Split attributes that stay in the local partition from those that
  * are mapped into the remote partition. */
-static int map_attrs_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
+static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
 {
-       *local_attrs = map_attrs_select_local(module, local_ctx, attrs);
-       *remote_attrs = map_attrs_collect_remote(module, remote_ctx, attrs);
+       *local_attrs = map_attrs_select_local(module, mem_ctx, attrs);
+       *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs);
 
        return 0;
 }
@@ -213,7 +214,11 @@ static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_ele
 }
 
 /* Map a message element back into the local partition. */
-static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
+static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, 
+                                                        void *mem_ctx, 
+                                                        const struct ldb_map_attribute *map, 
+                                                        const char *attr_name,
+                                                        const struct ldb_message_element *old)
 {
        struct ldb_message_element *el;
        int i;
@@ -232,7 +237,12 @@ static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *modu
                return NULL;
        }
 
-       el->name = map_attr_map_remote(el, map, old->name);
+       el->name = talloc_strdup(el, attr_name);
+       if (el->name == NULL) {
+               talloc_free(el);
+               map_oom(module);
+               return NULL;
+       }
 
        for (i = 0; i < el->num_values; i++) {
                el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
@@ -242,37 +252,64 @@ static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *modu
 }
 
 /* Merge a remote message element into a local message. */
-static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const char *attr_name, const struct ldb_message_element *old)
+static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, 
+                           struct ldb_message *remote, const char *attr_name)
 {
        const struct ldb_map_context *data = map_get_context(module);
-       const struct ldb_map_attribute *map = map_attr_find_remote(data, attr_name);
-       struct ldb_message_element *el=NULL;
+       const struct ldb_map_attribute *map;
+       struct ldb_message_element *old, *el=NULL;
+       const char *remote_name = NULL;
+
+       /* We handle wildcards in ldb_msg_el_merge_wildcard */
+       if (ldb_attr_cmp(attr_name, "*") == 0) {
+               return 0;
+       }
+
+       map = map_attr_find_local(data, attr_name);
 
        /* Unknown attribute in remote message:
         * skip, attribute was probably auto-generated */
        if (map == NULL) {
-               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
-                         "Skipping attribute '%s': no mapping found\n",
-                         old->name);
                return 0;
        }
 
        switch (map->type) {
        case MAP_IGNORE:
-               return -1;
+               break;
+       case MAP_CONVERT:
+               remote_name = map->u.convert.remote_name;
+               break;
+       case MAP_KEEP:
+               remote_name = attr_name;
+               break;
+       case MAP_RENAME:
+               remote_name = map->u.rename.remote_name;
+               break;
+       case MAP_GENERATE:
+               break;
+       }
+
+       switch (map->type) {
+       case MAP_IGNORE:
+               return 0;
 
        case MAP_CONVERT:
                if (map->u.convert.convert_remote == NULL) {
                        ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                  "Skipping attribute '%s': "
                                  "'convert_remote' not set\n",
-                                 old->name);
+                                 attr_name);
                        return 0;
                }
                /* fall through */
        case MAP_KEEP:
        case MAP_RENAME:
-               el = ldb_msg_el_map_remote(module, local, map, old);
+               old = ldb_msg_find_element(remote, remote_name);
+               if (old) {
+                       el = ldb_msg_el_map_remote(module, local, map, attr_name, old);
+               } else {
+                       return LDB_ERR_NO_SUCH_ATTRIBUTE;
+               }
                break;
 
        case MAP_GENERATE:
@@ -280,21 +317,72 @@ static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local
                        ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                  "Skipping attribute '%s': "
                                  "'generate_local' not set\n",
-                                 old->name);
+                                 attr_name);
                        return 0;
                }
 
-               el = map->u.generate.generate_local(module, local, old->name, remote);
+               el = map->u.generate.generate_local(module, local, attr_name, remote);
+               if (!el) {
+                       /* Generation failure is probably due to lack of source attributes */
+                       return LDB_ERR_NO_SUCH_ATTRIBUTE;
+               }
                break;
        }
 
        if (el == NULL) {
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
        return ldb_msg_replace(local, el);
 }
 
+/* Handle wildcard parts of merging a remote message element into a local message. */
+static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local, 
+                                    struct ldb_message *remote)
+{
+       const struct ldb_map_context *data = map_get_context(module);
+       const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
+       struct ldb_message_element *el=NULL;
+       int i, ret;
+
+       /* Perhaps we have a mapping for "*" */
+       if (map && map->type == MAP_KEEP) {
+               /* We copy everything over, and hope that anything with a 
+                  more specific rule is overwritten, or caught by the test below */
+               for (i = 0; i < remote->num_elements; i++) {
+                       if (map_attr_find_local(data, remote->elements[i].name)) {
+                               /* The name this would have been copied to has a more specific mapping */
+                               continue;
+                       }
+                       el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name,
+                                                  &remote->elements[i]);
+                       if (el == NULL) {
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+                       
+                       ret = ldb_msg_replace(local, el);
+                       if (ret) {
+                               return ret;
+                       }
+               }
+       }
+       
+       /* Now walk the list of possible mappings, and apply each */
+       for (i = 0; data->attribute_maps[i].local_name; i++) {
+               ret = ldb_msg_el_merge(module, local, remote, 
+                                      data->attribute_maps[i].local_name);
+               if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+                       continue;
+               } else if (ret) {
+                       return ret;
+               } else {
+                       continue;
+               }
+       }
+
+       return 0;
+}
+
 /* Mapping messages
  * ================ */
 
@@ -314,16 +402,36 @@ static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *ms
 }
 
 /* Merge a local and a remote message into a single local one. */
-static int ldb_msg_merge_remote(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote)
+static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local, 
+                               struct ldb_message *remote)
 {
        int i, ret;
+       const char * const *attrs = ac->all_attrs;
+       if (!attrs) {
+               ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
+               if (ret) {
+                       return ret;
+               }
+       }
+
+       for (i = 0; attrs && attrs[i]; i++) {
+               if (ldb_attr_cmp(attrs[i], "*") == 0) {
+                       ret = ldb_msg_el_merge_wildcard(ac->module, local, remote);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+       }
 
        /* Try to map each attribute back;
         * Add to local message is possible,
         * Overwrite old local attribute if necessary */
-       for (i = 0; i < remote->num_elements; i++) {
-               ret = ldb_msg_el_merge(module, local, remote, remote->elements[i].name, &remote->elements[i]);
-               if (ret) {
+       for (i = 0; attrs && attrs[i]; i++) {
+               ret = ldb_msg_el_merge(ac->module, local, remote, 
+                                      attrs[i]);
+               if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+               } else if (ret) {
                        return ret;
                }
        }
@@ -335,7 +443,7 @@ static int ldb_msg_merge_remote(struct ldb_module *module, struct ldb_message *l
  * ====================== */
 
 /* Map a search result back into the local partition. */
-static int map_reply_remote(struct ldb_module *module, struct ldb_reply *ares)
+static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares)
 {
        struct ldb_message *msg;
        struct ldb_dn *dn;
@@ -349,19 +457,19 @@ static int map_reply_remote(struct ldb_module *module, struct ldb_reply *ares)
        /* Create a new result message */
        msg = ldb_msg_new(ares);
        if (msg == NULL) {
-               map_oom(module);
+               map_oom(ac->module);
                return -1;
        }
 
        /* Merge remote message into new message */
-       ret = ldb_msg_merge_remote(module, msg, ares->message);
+       ret = ldb_msg_merge_remote(ac, msg, ares->message);
        if (ret) {
                talloc_free(msg);
                return ret;
        }
 
        /* Create corresponding local DN */
-       dn = ldb_dn_map_rebase_remote(module, msg, ares->message->dn);
+       dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn);
        if (dn == NULL) {
                talloc_free(msg);
                return -1;
@@ -419,7 +527,8 @@ static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx
        case LDB_OP_OR:
        case LDB_OP_AND:                /* attributes stored in list of subtrees */
                for (i = 0; i < tree->u.list.num_elements; i++) {
-                       ret = ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.list.elements[i]);
+                       ret = ldb_parse_tree_collect_attrs(module, mem_ctx, 
+                                                          attrs, tree->u.list.elements[i]);
                        if (ret) {
                                return ret;
                        }
@@ -827,23 +936,34 @@ static int ldb_parse_tree_partition(struct ldb_module *module, void *local_ctx,
 /* Collect a list of attributes required either explicitly from a
  * given list or implicitly  from a given parse tree; split the
  * collected list into local and remote parts. */
-static int map_attrs_collect_and_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *search_attrs, const struct ldb_parse_tree *tree)
+static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac,
+                                          const char * const *search_attrs, 
+                                          const struct ldb_parse_tree *tree)
 {
        void *tmp_ctx;
        const char **tree_attrs;
+       const char **remote_attrs;
+       const char **local_attrs;
        int ret;
 
        /* Clear initial lists of partitioned attributes */
-       *local_attrs = NULL;
-       *remote_attrs = NULL;
+
+       /* Clear initial lists of partitioned attributes */
 
        /* There is no tree, just partition the searched attributes */
        if (tree == NULL) {
-               return map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, search_attrs);
+               ret = map_attrs_partition(module, ac, 
+                                         &local_attrs, &remote_attrs, search_attrs);
+               if (ret == 0) {
+                       ac->local_attrs = local_attrs;
+                       ac->remote_attrs = remote_attrs;
+                       ac->all_attrs = search_attrs;
+               }
+               return ret; 
        }
 
        /* Create context for temporary memory */
-       tmp_ctx = talloc_new(local_ctx);
+       tmp_ctx = talloc_new(ac);
        if (tmp_ctx == NULL) {
                goto oom;
        }
@@ -869,8 +989,15 @@ static int map_attrs_collect_and_partition(struct ldb_module *module, void *loca
        }
 
        /* Split local from remote attributes */
-       ret = map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, tree_attrs);
-
+       ret = map_attrs_partition(module, ac, &local_attrs, 
+                                 &remote_attrs, tree_attrs);
+       
+       if (ret == 0) {
+               ac->local_attrs = local_attrs;
+               ac->remote_attrs = remote_attrs;
+               talloc_steal(ac, tree_attrs);
+               ac->all_attrs = tree_attrs;
+       }
 done:
        /* Free temporary memory */
        talloc_free(tmp_ctx);
@@ -911,10 +1038,12 @@ int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, stru
 
        /* Limit result to requested attrs */
        if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) {
-               for (i = 0; i < ares->message->num_elements; i++) {
+               for (i = 0; i < ares->message->num_elements; ) {
                        const struct ldb_message_element *el = &ares->message->elements[i];
                        if (!ldb_attr_in_list(req->op.search.attrs, el->name)) {
-                               ldb_msg_remove_attr(ares->message, el->name);
+                               ldb_msg_remove_element(ares->message, el);
+                       } else {
+                               i++;
                        }
                }
        }
@@ -995,7 +1124,7 @@ int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ld
        }
 
        /* Map result record into a local message */
-       ret = map_reply_remote(ac->module, ares);
+       ret = map_reply_remote(ac, ares);
        if (ret) {
                talloc_free(ares);
                return LDB_ERR_OPERATIONS_ERROR;
@@ -1042,7 +1171,6 @@ int map_search(struct ldb_module *module, struct ldb_request *req)
        struct ldb_handle *h;
        struct map_context *ac;
        struct ldb_parse_tree *local_tree, *remote_tree;
-       const char **local_attrs, **remote_attrs;
        int ret;
 
        const char *wildcard[] = { "*", NULL };
@@ -1096,16 +1224,18 @@ int map_search(struct ldb_module *module, struct ldb_request *req)
        }
 
        /* Split local from remote attrs */
-       ret = map_attrs_collect_and_partition(module, ac, ac->search_reqs[0], &local_attrs, &remote_attrs, attrs, req->op.search.tree);
+       ret = map_attrs_collect_and_partition(module, ac, 
+                                             attrs, req->op.search.tree);
        if (ret) {
                goto failed;
        }
 
-       ac->local_attrs = local_attrs;
-       ac->search_reqs[0]->op.search.attrs = remote_attrs;
+       ac->search_reqs[0]->op.search.attrs = ac->remote_attrs;
 
        /* Split local from remote tree */
-       ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], &local_tree, &remote_tree, req->op.search.tree);
+       ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], 
+                                      &local_tree, &remote_tree, 
+                                      req->op.search.tree);
        if (ret) {
                goto failed;
        }
index ae53ebbdd48e8bc5dbf4cbe67f683f0e223b6d5c..8a08d0a5b6ff64d00be3db138ea91c1c7500b988 100644 (file)
@@ -36,6 +36,8 @@ struct map_context {
        const struct ldb_dn *local_dn;
        const struct ldb_parse_tree *local_tree;
        const char * const *local_attrs;
+       const char * const *remote_attrs;
+       const char * const *all_attrs;
 
        struct ldb_request *orig_req;
        struct ldb_request *local_req;
index 446b39facf92be8b20e92f8c1430736b1109ea40..076d4343603cd2c03ba29cee2e43be657cf07810 100755 (executable)
@@ -43,7 +43,7 @@ function setup_modules(ldb, s3, s4, ldif)
        var ldif = "
 dn: @MAP=samba3sam
 @FROM: " + s4.BASEDN + "
-@TO: " + s3.BASEDN + "
+@TO: sambaDomainName=TESTS," + s3.BASEDN + "
 
 dn: @MODULES
 @LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,objectclass,password_hash,operational,objectguid,rdn_name,samba3sam,partition
@@ -79,7 +79,7 @@ function test_s3sam_search(ldb)
        var msg = ldb.search("(cn=Replicator)");
        assert(msg.length == 1);
        println(msg[0].dn);
-       assert(msg[0].dn == "cn=Replicator,ou=Groups,sambaDomainName=TESTS,dc=vernstok,dc=nl");
+       assert(msg[0].dn == "cn=Replicator,ou=Groups,dc=vernstok,dc=nl");
        assert(msg[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
 
        println("Checking mapping of objectClass");
@@ -94,30 +94,36 @@ function test_s3sam_search(ldb)
        assert(msg != undefined);
        assert(msg.length == 2);
        for (var i = 0; i < msg.length; i++) {
-               assert((msg[i].dn == "unixName=Administrator,ou=Users,sambaDomainName=TESTS,dc=vernstok,dc=nl") ||
-                      (msg[i].dn == "unixName=nobody,ou=Users,sambaDomainName=TESTS,dc=vernstok,dc=nl"));
+               assert((msg[i].dn == "unixName=Administrator,ou=Users,dc=vernstok,dc=nl") ||
+                      (msg[i].dn == "unixName=nobody,ou=Users,dc=vernstok,dc=nl"));
        }
 }
 
 function test_s3sam_modify(ldb, s3)
 {
+       var msg, ok;
        println("Adding a record that will be fallbacked");
        ok = ldb.add("
-dn: cn=Foo,dc=idealx,dc=org
+dn: cn=Foo
 foo: bar
 blah: Blie
 cn: Foo
 showInAdvancedViewOnly: TRUE
 ");
+       if (!ok) {
+               println(ldb.errstring());
+               assert(ok);
+       }
        assert(ok);
 
        println("Checking for existence of record (local)");
        /* TODO: This record must be searched in the local database, which is currently only supported for base searches
         * msg = ldb.search("(cn=Foo)", new Array('foo','blah','cn','showInAdvancedViewOnly'));
         * TODO: Actually, this version should work as well but doesn't...
-        * msg = ldb.search("(cn=Foo)", "dc=idealx,dc=org", ldb.LDB_SCOPE_SUBTREE new Array('foo','blah','cn','showInAdvancedViewOnly'));
+        * 
         */
-       msg = ldb.search("", "cn=Foo,dc=idealx,dc=org", ldb.LDB_SCOPE_BASE new Array('foo','blah','cn','showInAdvancedViewOnly'));
+       var attrs =  new Array('foo','blah','cn','showInAdvancedViewOnly');
+       msg = ldb.search("(cn=Foo)", "cn=Foo", ldb.LDB_SCOPE_BASE, attrs);
        assert(msg.length == 1);
        assert(msg[0].showInAdvancedViewOnly == "TRUE");
        assert(msg[0].foo == "bar");
@@ -125,12 +131,16 @@ showInAdvancedViewOnly: TRUE
 
        println("Adding record that will be mapped");
        ok = ldb.add("
-dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
+dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
 objectClass: user
 unixName: bin
 unicodePwd: geheim
 cn: Niemand
 ");
+       if (!ok) {
+               println(ldb.errstring());
+               assert(ok);
+       }
        assert(ok);
 
        println("Checking for existence of record (remote)");
@@ -148,6 +158,7 @@ cn: Niemand
 
        println("Checking for existence of record (local || remote)");
        msg = ldb.search("(|(unixName=bin)(unicodePwd=geheim))", new Array('unixName','cn','dn', 'unicodePwd'));
+       println("got " + msg.length + " replies");
        assert(msg.length == 1);                // TODO: should check with more records
        assert(msg[0].cn == "Niemand");
        assert(msg[0].unixName == "bin" || msg[0].unicodePwd == "geheim");
@@ -160,11 +171,15 @@ cn: Niemand
 
        println("Adding attribute...");
        ok = ldb.modify("
-dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
+dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
 changetype: modify
 add: description
 description: Blah
 ");
+       if (!ok) {
+               println(ldb.errstring());
+               assert(ok);
+       }
        assert(ok);
 
        println("Checking whether changes are still there...");
@@ -175,11 +190,15 @@ description: Blah
 
        println("Modifying attribute...");
        ok = ldb.modify("
-dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
+dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
 changetype: modify
 replace: description
 description: Blie
 ");
+               if (!ok) {
+                       println(ldb.errstring());
+                       assert(ok);
+               }
        assert(ok);
 
        println("Checking whether changes are still there...");
@@ -189,10 +208,14 @@ description: Blie
 
        println("Deleting attribute...");
        ok = ldb.modify("
-dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
+dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
 changetype: modify
 delete: description
 ");
+       if (!ok) {
+               println(ldb.errstring());
+               assert(ok);
+       }
        assert(ok);
 
        println("Checking whether changes are no longer there...");
@@ -201,19 +224,23 @@ delete: description
        assert(msg[0].description == undefined);
 
        println("Renaming record...");
-       ok = ldb.rename("cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl", "cn=Niemand,dc=vernstok,dc=nl");
+       ok = ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
+       assert(ok);
 
        println("Checking whether DN has changed...");
-       msg = ldb.search("(cn=Niemand)");
+       msg = ldb.search("(cn=Niemand2)");
        assert(msg.length == 1);
-       assert(msg[0].dn == "cn=Niemand,dc=vernstok,dc=nl");
+       assert(msg[0].dn == "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
 
        println("Deleting record...");
-       ok = ldb.del("cn=Niemand,dc=vernstok,dc=nl");
-       assert(ok);
+       ok = ldb.del("cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
+       if (!ok) {
+               println(ldb.errstring());
+               assert(ok);
+       }
 
        println("Checking whether record is gone...");
-       msg = ldb.search("(cn=Niemand)");
+       msg = ldb.search("(cn=Niemand2)");
        assert(msg.length == 0);
 }
 
@@ -401,13 +428,13 @@ description: y
        /* In most cases, this even works when the mapping is missing
         * a `convert_operator' by enumerating the remote db. */
        attrs = new Array("objectCategory", "lastLogon", "primaryGroupID");
-       res = ldb.search("(primaryGroupID=1-5-21-4231626423-2410014848-2360679739-512)", NULL, ldb. SCOPE_DEFAULT, attrs);
+       res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs);
        assert(res != undefined);
        assert(res.length == 1);
        assert(res[0].dn == s4.dn("cn=A"));
        assert(res[0].objectCategory == undefined);
        assert(res[0].lastLogon == "x");
-       assert(res[0].primaryGroupID == "1-5-21-4231626423-2410014848-2360679739-512");
+       assert(res[0].primaryGroupID == "512");
 
        /* TODO: There should actually be two results, A and X.  The
         * primaryGroupID of X seems to get corrupted somewhere, and the
@@ -1107,6 +1134,11 @@ function make_dn(rdn)
        return rdn + ",sambaDomainName=TESTS," + this.BASEDN;
 }
 
+function make_s4dn(rdn)
+{
+       return rdn + "," + this.BASEDN;
+}
+
 var ldb = ldb_init();
 
 sys = sys_init();
@@ -1118,12 +1150,12 @@ samba4.file = prefix + "/" + "samba4.ldb";
 samba4.url = "tdb://" + samba4.file;
 samba4.BASEDN = "dc=vernstok,dc=nl";
 samba4.db = ldb_init();
-samba4.dn = make_dn;
+samba4.dn = make_s4dn;
 
 var samba3 = new Object("samba3 partition info");
 samba3.file = prefix + "/" + "samba3.ldb";
 samba3.url = "tdb://" + samba3.file;
-samba3.BASEDN = "cn=Samba3Sam," + samba4.BASEDN;
+samba3.BASEDN = "cn=Samba3Sam";
 samba3.db = ldb_init();
 samba3.dn = make_dn;