1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

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 commit is contained in:
Andrew Bartlett 2006-09-14 03:15:30 +00:00 committed by Gerald (Jerry) Carter
parent f7eaa03d6f
commit bc58792b71
7 changed files with 145 additions and 78 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -1,27 +1,26 @@
/*
ldb database library - map backend
/*
ldb database mapping module
Copyright (C) Jelmer Vernooij 2005
Copyright (C) Martin Kuehl <mkhl@samba.org> 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
* 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 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 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.
This library is distributed in the hope that it will be useful,
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

View File

@ -3,6 +3,7 @@
Copyright (C) Jelmer Vernooij 2005
Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
Copyright (C) Andrew Bartlett <abartlet@samba.org> 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;
}

View File

@ -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);