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:
parent
f7eaa03d6f
commit
bc58792b71
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user