From 1e4f5a096cb75f0db0219fc55a6f654c485b0427 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 14 Sep 2006 03:15:30 +0000 Subject: r18495: More work on the LDAP backend (which now passes a lot of our tests!) This adds a list of attributes that are in our wildcard seaches, but the remote server requires to be explicitly listed. This also cleans up the handling of wildcards in ldb_map to be more consistant. Also fix the partitions module to rebase the search, if on the GC port, we do a subtree search. (Otherwise backends can rightly complain that the search is not in their scope). Andrew Bartlett (This used to be commit bc58792b7102f086b19353635d5d5ef9d40a0aae) --- source4/dsdb/samdb/ldb_modules/entryUUID.c | 14 ++++++- source4/dsdb/samdb/ldb_modules/partition.c | 53 +++++++++++++++++-------- source4/dsdb/samdb/ldb_modules/samba3sam.c | 2 +- source4/lib/ldb/modules/ldb_map.c | 38 ++++++++++++++++-- source4/lib/ldb/modules/ldb_map.h | 51 +++++++++++++----------- source4/lib/ldb/modules/ldb_map_outbound.c | 64 +++++++++++++++--------------- source4/lib/ldb/modules/ldb_map_private.h | 1 + 7 files changed, 145 insertions(+), 78 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/entryUUID.c b/source4/dsdb/samdb/ldb_modules/entryUUID.c index 109e9be2f9..f7701b7652 100644 --- a/source4/dsdb/samdb/ldb_modules/entryUUID.c +++ b/source4/dsdb/samdb/ldb_modules/entryUUID.c @@ -303,6 +303,15 @@ const struct ldb_map_attribute entryUUID_attributes[] = } }; +/* These things do not show up in wildcard searches in OpenLDAP, but + * we need them to show up in the AD-like view */ +const char * const wildcard_attributes[] = { + "objectGUID", + "whenCreated", + "whenChanged", + NULL +}; + static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx) { const char *rootdse_attrs[] = {"schemaNamingContext", NULL}; @@ -372,7 +381,7 @@ static int entryUUID_init(struct ldb_module *module) struct entryUUID_private *entryUUID_private; struct ldb_dn *schema_dn; - ret = ldb_map_init(module, entryUUID_attributes, NULL, NULL); + ret = ldb_map_init(module, entryUUID_attributes, NULL, wildcard_attributes, NULL); if (ret != LDB_SUCCESS) return ret; @@ -387,7 +396,8 @@ static int entryUUID_init(struct ldb_module *module) return LDB_SUCCESS; } - ret = fetch_objectclass_schema(module->ldb, schema_dn, entryUUID_private, &entryUUID_private->objectclass_res); + ret = fetch_objectclass_schema(module->ldb, schema_dn, entryUUID_private, + &entryUUID_private->objectclass_res); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(module->ldb, "Failed to fetch objectClass schema elements: %s\n", ldb_errstring(module->ldb)); return ret; diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 889c0bfeb0..bb085e0b11 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -186,35 +186,43 @@ error: } -static int partition_send_request(struct partition_context *ac, struct ldb_module *partition) +static int partition_send_request(struct partition_context *ac, struct ldb_module *partition, + struct ldb_dn *partition_base_dn) { int ret; struct ldb_module *next = make_module_for_next_request(ac->module, ac->module->ldb, partition); - + struct ldb_request *req; ac->down_req = talloc_realloc(ac, ac->down_req, struct ldb_request *, ac->num_requests + 1); if (!ac->down_req) { ldb_set_errstring(ac->module->ldb, "Out of Memory"); return LDB_ERR_OPERATIONS_ERROR; } - ac->down_req[ac->num_requests] = talloc(ac, struct ldb_request); - if (ac->down_req[ac->num_requests] == NULL) { + req = ac->down_req[ac->num_requests] = talloc(ac, struct ldb_request); + if (req == NULL) { ldb_set_errstring(ac->module->ldb, "Out of Memory"); return LDB_ERR_OPERATIONS_ERROR; } *ac->down_req[ac->num_requests] = *ac->orig_req; /* copy the request */ - - if (ac->down_req[ac->num_requests]->operation == LDB_SEARCH) { - ac->down_req[ac->num_requests]->callback = partition_search_callback; - ac->down_req[ac->num_requests]->context = ac; + + if (req->operation == LDB_SEARCH) { + /* If the search is for 'more' than this partition, + * then change the basedn, so a remote LDAP server + * doesn't object */ + if (ldb_dn_compare_base(ac->module->ldb, + partition_base_dn, req->op.search.base) != 0) { + req->op.search.base = partition_base_dn; + } + req->callback = partition_search_callback; + req->context = ac; } else { - ac->down_req[ac->num_requests]->callback = partition_other_callback; - ac->down_req[ac->num_requests]->context = ac; + req->callback = partition_other_callback; + req->context = ac; } /* Spray off search requests to all backends */ - ret = ldb_next_request(next, ac->down_req[ac->num_requests]); + ret = ldb_next_request(next, req); if (ret != LDB_SUCCESS) { return ret; } @@ -230,12 +238,12 @@ static int partition_send_all(struct ldb_module *module, int i; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); - int ret = partition_send_request(ac, module->next); + int ret = partition_send_request(ac, module->next, NULL); if (ret != LDB_SUCCESS) { return ret; } for (i=0; data && data->partitions && data->partitions[i]; i++) { - ret = partition_send_request(ac, data->partitions[i]->module); + ret = partition_send_request(ac, data->partitions[i]->module, data->partitions[i]->dn); if (ret != LDB_SUCCESS) { return ret; } @@ -307,21 +315,26 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) ac = talloc_get_type(h->private_data, struct partition_context); + /* Search from the base DN */ + if (!req->op.search.base || req->op.search.base->comp_num == 0) { + return partition_send_all(module, ac, req); + } for (i=0; data && data->partitions && data->partitions[i]; i++) { /* Find all partitions under the search base */ if (ldb_dn_compare_base(module->ldb, req->op.search.base, data->partitions[i]->dn) == 0) { - ret = partition_send_request(ac, data->partitions[i]->module); + ret = partition_send_request(ac, data->partitions[i]->module, data->partitions[i]->dn); if (ret != LDB_SUCCESS) { return ret; } } } - /* Perhaps we didn't match any partitions. Try the main partition, then all partitions */ + /* Perhaps we didn't match any partitions. Try the main partition, only */ if (ac->num_requests == 0) { - return partition_send_all(module, ac, req); + talloc_free(h); + return ldb_next_request(module, req); } return LDB_SUCCESS; @@ -701,11 +714,19 @@ static int partition_init(struct ldb_module *module) ret = ldb_load_modules_list(module->ldb, modules, partition->module, &partition->module); if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "partition_init: " + "loading backend for %s failed: %s", + base, ldb_errstring(module->ldb)); talloc_free(mem_ctx); return ret; } ret = ldb_init_module_chain(module->ldb, partition->module); if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "partition_init: " + "initialising backend for %s failed: %s", + base, ldb_errstring(module->ldb)); talloc_free(mem_ctx); return ret; } diff --git a/source4/dsdb/samdb/ldb_modules/samba3sam.c b/source4/dsdb/samdb/ldb_modules/samba3sam.c index 670d9ef0d8..fcbcf0f421 100644 --- a/source4/dsdb/samdb/ldb_modules/samba3sam.c +++ b/source4/dsdb/samdb/ldb_modules/samba3sam.c @@ -866,7 +866,7 @@ static int samba3sam_init(struct ldb_module *module) { int ret; - ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, "samba3sam"); + ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, "samba3sam"); if (ret != LDB_SUCCESS) return ret; diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 2bc3416a93..0c58687ddb 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -432,6 +432,30 @@ const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *m return talloc_strdup(mem_ctx, map->local_name); } + +/* 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 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); + return -1; + } + + for (k = 0; k < j; k++) { + (*attrs)[i+k] = more_attrs[k]; + } + + (*attrs)[i+k] = NULL; + + return 0; +} + /* Mapping ldb values * ================== */ @@ -1226,7 +1250,10 @@ static int map_init_dns(struct ldb_module *module, struct ldb_map_context *data, } /* Store attribute maps and objectClass maps in private data. */ -static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls) +static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data, + const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes) { int i, j, last; last = 0; @@ -1261,6 +1288,8 @@ static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data /* Store list of objectClass maps */ data->objectclass_maps = ocls; + data->wildcard_attributes = wildcard_attributes; + return LDB_SUCCESS; } @@ -1271,7 +1300,10 @@ struct ldb_module_ops ldb_map_get_ops(void) } /* Initialize global private data. */ -int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name) +int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes, + const char *name) { struct map_private *data; int ret; @@ -1299,7 +1331,7 @@ int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attr } /* Store list of attribute and objectClass maps */ - ret = map_init_maps(module, data->context, attrs, ocls); + ret = map_init_maps(module, data->context, attrs, ocls, wildcard_attributes); if (ret != LDB_SUCCESS) { talloc_free(data); return ret; diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index e743970564..c5c455bcb2 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -1,27 +1,26 @@ -/* - ldb database library - map backend +/* + ldb database mapping module Copyright (C) Jelmer Vernooij 2005 Copyright (C) Martin Kuehl 2006 - Development sponsored by the Google Summer of Code program - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + * NOTICE: this module is NOT released under the GNU LGPL license as + * other ldb code. This module is release under the GNU GPL v2 or + * later license. - This library is distributed in the hope that it will be useful, + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __LDB_MAP_H__ @@ -130,6 +129,11 @@ struct ldb_map_context { struct ldb_map_attribute *attribute_maps; /* NOTE: Always declare base classes first here */ const struct ldb_map_objectclass *objectclass_maps; + + /* Remote (often operational) attributes that should be added + * to any wildcard search */ + const char * const *wildcard_attributes; + /* struct ldb_context *mapped_ldb; */ const struct ldb_dn *local_base_dn; const struct ldb_dn *remote_base_dn; @@ -141,12 +145,11 @@ struct map_private { struct ldb_map_context *context; }; -/* initialization function */ -int -ldb_map_init(struct ldb_module *module, - const struct ldb_map_attribute *attrs, - const struct ldb_map_objectclass *ocls, - const char *name); +/* Initialize global private data. */ +int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes, + const char *name); /* get copy of map_ops */ struct ldb_module_ops diff --git a/source4/lib/ldb/modules/ldb_map_outbound.c b/source4/lib/ldb/modules/ldb_map_outbound.c index bd30d8ca27..c034a86375 100644 --- a/source4/lib/ldb/modules/ldb_map_outbound.c +++ b/source4/lib/ldb/modules/ldb_map_outbound.c @@ -3,6 +3,7 @@ Copyright (C) Jelmer Vernooij 2005 Copyright (C) Martin Kuehl 2006 + Copyright (C) Andrew Bartlett 2006 * NOTICE: this module is NOT released under the GNU LGPL license as * other ldb code. This module is release under the GNU GPL v2 or @@ -81,9 +82,7 @@ static const char **map_attrs_collect_remote(struct ldb_module *module, void *me const struct ldb_map_attribute *map; const char *name=NULL; int i, j, last; - - if (attrs == NULL) - return NULL; + int ret; last = 0; result = talloc_array(mem_ctx, const char *, 1); @@ -95,6 +94,25 @@ static const char **map_attrs_collect_remote(struct ldb_module *module, void *me for (i = 0; attrs[i]; i++) { /* Wildcards are kept remotely, too */ if (ldb_attr_cmp(attrs[i], "*") == 0) { + const char **new_attrs = NULL; + ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs); + if (ret != LDB_SUCCESS) { + goto failed; + } + ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes); + if (ret != LDB_SUCCESS) { + goto failed; + } + + attrs = new_attrs; + break; + } + } + + for (i = 0; attrs[i]; i++) { + /* Wildcards are kept remotely, too */ + if (ldb_attr_cmp(attrs[i], "*") == 0) { + /* Add all 'include in wildcard' attributes */ name = attrs[i]; goto named; } @@ -162,29 +180,6 @@ static int map_attrs_partition(struct ldb_module *module, void *local_ctx, void return 0; } -/* Merge two lists of attributes into a single one. */ -static 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)[i]; i++) /* noop */ ; - for (j = 0; more_attrs[j]; j++) /* noop */ ; - - *attrs = talloc_realloc(mem_ctx, *attrs, const char *, i+j+1); - if (*attrs == NULL) { - map_oom(module); - return -1; - } - - for (k = 0; k < j; k++) { - (*attrs)[i+k] = more_attrs[k]; - } - - (*attrs)[i+k] = NULL; - - return 0; -} - /* Mapping ldb values * ================== */ @@ -815,11 +810,6 @@ static int map_attrs_collect_and_partition(struct ldb_module *module, void *loca *local_attrs = NULL; *remote_attrs = NULL; - /* There are no searched attributes, just stick to that */ - if (search_attrs == NULL) { - return 0; - } - /* 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); @@ -1028,6 +1018,9 @@ int map_search(struct ldb_module *module, struct ldb_request *req) const char **local_attrs, **remote_attrs; int ret; + const char *wildcard[] = { "*", NULL }; + const char * const *attrs; + /* Do not manipulate our control entries */ if (ldb_dn_is_special(req->op.search.base)) return ldb_next_request(module, req); @@ -1068,8 +1061,15 @@ int map_search(struct ldb_module *module, struct ldb_request *req) ac->search_reqs[0]->context = ac; ac->search_reqs[0]->callback = map_remote_search_callback; + /* It is easier to deal with the two different ways of + * expressing the wildcard in the same codepath */ + attrs = req->op.search.attrs; + if (attrs == NULL) { + attrs = wildcard; + } + /* Split local from remote attrs */ - ret = map_attrs_collect_and_partition(module, ac, ac->search_reqs[0], &local_attrs, &remote_attrs, req->op.search.attrs, req->op.search.tree); + ret = map_attrs_collect_and_partition(module, ac, ac->search_reqs[0], &local_attrs, &remote_attrs, attrs, req->op.search.tree); if (ret) { goto failed; } diff --git a/source4/lib/ldb/modules/ldb_map_private.h b/source4/lib/ldb/modules/ldb_map_private.h index 4fff5614af..7fb2745179 100644 --- a/source4/lib/ldb/modules/ldb_map_private.h +++ b/source4/lib/ldb/modules/ldb_map_private.h @@ -75,6 +75,7 @@ const struct ldb_map_attribute *map_attr_find_remote(const struct ldb_map_contex const char *map_attr_map_local(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr); const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr); +int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attrs, const char * const *more_attrs); struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val); struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val); -- cgit