From 651cd7b1dfd66cc247a6b474ecd38bc38f5935d4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 12 Dec 2008 14:45:03 +1100 Subject: [PATCH] Merge the 'normalise' ldb module with extended_dn_out This allows extended_dn_out to use the cheaper binary comparisons when looping over the dereference control avoids a second module doing a loop over all attributes and the matching schema lookup. Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/config.mk | 12 -- .../dsdb/samdb/ldb_modules/extended_dn_out.c | 71 ++++++- source4/dsdb/samdb/ldb_modules/normalise.c | 198 ------------------ source4/scripting/python/samba/provision.py | 2 +- 4 files changed, 66 insertions(+), 217 deletions(-) delete mode 100644 source4/dsdb/samdb/ldb_modules/normalise.c diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 19375bb923f..1c50923eba3 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -311,18 +311,6 @@ SUBSYSTEM = LIBLDB ldb_anr_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/anr.o -################################################ -# Start MODULE ldb_normalise -[MODULE::ldb_normalise] -INIT_FUNCTION = LDB_MODULE(normalise) -CFLAGS = -Ilib/ldb/include -PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBSAMBA-UTIL SAMDB -SUBSYSTEM = LIBLDB -# End MODULE ldb_normalise -################################################ - -ldb_normalise_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/normalise.o - ################################################ # Start MODULE ldb_instancetype [MODULE::ldb_instancetype] diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c index f284c719daf..d91d9460e2a 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c @@ -24,7 +24,7 @@ * Component: ldb extended dn control module * * Description: this module builds a special dn for returned search - * results + * results, and fixes some other aspects of the result (returned case issues) * values. * * Authors: Simo Sorce @@ -41,6 +41,7 @@ struct extended_dn_out_private { bool dereference; + bool normalise; struct dsdb_openldap_dereference_control *dereference_control; }; @@ -98,6 +99,39 @@ static bool add_attrs(void *mem_ctx, char ***attrs, const char *attr) return true; } +/* Fix the DN so that the relative attribute names are in upper case so that the DN: + cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes + CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com +*/ + + +static int fix_dn(struct ldb_dn *dn) +{ + int i, ret; + char *upper_rdn_attr; + + for (i=0; i < ldb_dn_get_comp_num(dn); i++) { + /* We need the attribute name in upper case */ + upper_rdn_attr = strupper_talloc(dn, + ldb_dn_get_component_name(dn, i)); + if (!upper_rdn_attr) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* And replace it with CN=foo (we need the attribute in upper case */ + ret = ldb_dn_set_component(dn, i, upper_rdn_attr, + *ldb_dn_get_component_val(dn, i)); + talloc_free(upper_rdn_attr); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} + +/* Inject the extended DN components, so the DN cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes + ;;cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com */ + static int inject_extended_dn_out(struct ldb_reply *ares, struct ldb_context *ldb, int type, @@ -161,10 +195,9 @@ static int handle_dereference(struct ldb_dn *dn, /* Look for this attribute in the returned control */ for (j = 0; dereference_attrs && dereference_attrs[j]; j++) { - DATA_BLOB source_dn = data_blob_string_const(dereference_attrs[j]->dereferenced_dn); - if (ldb_attr_cmp(dereference_attrs[j]->source_attribute, attr) + struct ldb_val source_dn = data_blob_string_const(dereference_attrs[j]->dereferenced_dn); + if (ldb_attr_cmp(dereference_attrs[j]->source_attribute, attr) == 0 && data_blob_cmp(&source_dn, val) == 0) { - fake_msg.num_elements = dereference_attrs[j]->num_attributes; fake_msg.elements = dereference_attrs[j]->attributes; break; @@ -279,6 +312,18 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares) if (!attribute) { continue; } + + if (private->normalise) { + /* If we are also in 'normalise' mode, then + * fix the attribute names to be in the + * correct case */ + msg->elements[i].name = talloc_strdup(msg->elements, attribute->lDAPDisplayName); + if (!msg->elements[i].name) { + ldb_oom(ac->module->ldb); + return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); + } + } + /* Look to see if this attributeSyntax is a DN */ if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0) { continue; @@ -291,6 +336,13 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares) return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX); } + if (private->normalise) { + ret = fix_dn(dn); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + } + /* If we are running in dereference mode (such * as against OpenLDAP) then the DN in the msg * above does not contain the extended values, @@ -305,11 +357,10 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares) msg->elements[i].name, &msg->elements[i].values[j]); if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); } } - + if (!ac->inject) { dn_str = talloc_steal(msg->elements[i].values, ldb_dn_get_linearized(dn)); @@ -318,6 +369,10 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares) ldb_dn_get_extended_linearized(msg->elements[i].values, dn, ac->extended_type)); } + if (!dn_str) { + ldb_oom(ac->module->ldb); + return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); + } msg->elements[i].values[j] = data_blob_string_const(dn_str); talloc_free(dn); } @@ -508,6 +563,10 @@ static int extended_dn_out_dereference_init(struct ldb_module *module) private->dereference = true; + /* At the moment, servers that need dereference also need the + * DN and attribute names to be normalised */ + private->normalise = true; + ret = ldb_mod_register_control(module, LDB_CONTROL_EXTENDED_DN_OID); if (ret != LDB_SUCCESS) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, diff --git a/source4/dsdb/samdb/ldb_modules/normalise.c b/source4/dsdb/samdb/ldb_modules/normalise.c deleted file mode 100644 index f938672f965..00000000000 --- a/source4/dsdb/samdb/ldb_modules/normalise.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - ldb database library - - Copyright (C) Amdrew Bartlett 2007-2008 - - 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 3 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - * Name: ldb - * - * Component: ldb normalisation module - * - * Description: module to ensure all DNs and attribute names are normalised - * - * Author: Andrew Bartlett - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_errors.h" -#include "ldb/include/ldb_private.h" -#include "dsdb/samdb/samdb.h" - -/* Fix up the DN to be in the standard form, taking particular care to match the parent DN - - This should mean that if the parent is: - CN=Users,DC=samba,DC=example,DC=com - and a proposed child is - cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM - - The resulting DN should be: - - CN=Admins,CN=Users,DC=samba,DC=example,DC=com - - */ - -struct norm_context { - struct ldb_module *module; - struct ldb_request *req; - - const struct dsdb_schema *schema; -}; - -static int fix_dn(struct ldb_dn *dn) -{ - int i, ret; - char *upper_rdn_attr; - - for (i=0; i < ldb_dn_get_comp_num(dn); i++) { - /* We need the attribute name in upper case */ - upper_rdn_attr = strupper_talloc(dn, - ldb_dn_get_component_name(dn, i)); - if (!upper_rdn_attr) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* And replace it with CN=foo (we need the attribute in upper case */ - ret = ldb_dn_set_component(dn, i, upper_rdn_attr, - *ldb_dn_get_component_val(dn, i)); - talloc_free(upper_rdn_attr); - if (ret != LDB_SUCCESS) { - return ret; - } - } - return LDB_SUCCESS; -} - -static int normalize_search_callback(struct ldb_request *req, struct ldb_reply *ares) -{ - struct ldb_message *msg; - struct norm_context *ac; - int i, j, ret; - - ac = talloc_get_type(req->context, struct norm_context); - - if (!ares) { - return ldb_module_done(ac->req, NULL, NULL, - LDB_ERR_OPERATIONS_ERROR); - } - if (ares->error != LDB_SUCCESS) { - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - - /* Only entries are interesting, and we handle the case of the parent seperatly */ - - switch (ares->type) { - case LDB_REPLY_ENTRY: - - /* OK, we have one of *many* search results passing by here, - * but we should get them one at a time */ - msg = ares->message; - - ret = fix_dn(msg->dn); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - - for (i = 0; i < msg->num_elements; i++) { - const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name); - if (!attribute) { - continue; - } - msg->elements[i].name = talloc_strdup(msg->elements, attribute->lDAPDisplayName); - if (!msg->elements[i].name) { - return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); - } - - /* Look to see if this attributeSyntax is a DN */ - if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0) { - continue; - } - for (j = 0; j < msg->elements[i].num_values; j++) { - const char *dn_str; - struct ldb_dn *dn = ldb_dn_from_ldb_val(ac, ac->module->ldb, &msg->elements[i].values[j]); - if (!dn) { - return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX); - } - ret = fix_dn(dn); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - dn_str = talloc_steal(msg->elements[i].values, ldb_dn_get_linearized(dn)); - msg->elements[i].values[j] = data_blob_string_const(dn_str); - talloc_free(dn); - } - } - - return ldb_module_send_entry(ac->req, msg, ares->controls); - - case LDB_REPLY_REFERRAL: - - return ldb_module_send_referral(ac->req, ares->referral); - - case LDB_REPLY_DONE: - - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - - return LDB_SUCCESS; -} - -/* search */ -static int normalise_search(struct ldb_module *module, struct ldb_request *req) -{ - struct ldb_request *down_req; - struct norm_context *ac; - int ret; - - ac = talloc(req, struct norm_context); - if (ac == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - - ac->module = module; - ac->req = req; - - /* if schema not yet present just skip over */ - ac->schema = dsdb_get_schema(ac->module->ldb); - if (ac->schema == NULL) { - talloc_free(ac); - return ldb_next_request(module, req); - } - - ret = ldb_build_search_req_ex(&down_req, module->ldb, ac, - req->op.search.base, - req->op.search.scope, - req->op.search.tree, - req->op.search.attrs, - req->controls, - ac, normalize_search_callback, - req); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - - return ldb_next_request(module, down_req); -} - - - -_PUBLIC_ const struct ldb_module_ops ldb_normalise_module_ops = { - .name = "normalise", - .search = normalise_search, -}; diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 963410e03d9..b661e5ffb27 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -492,7 +492,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, # We can handle linked attributes here, as we don't have directory-side subtree operations tdb_modules_list = ["linked_attributes", "extended_dn_out_dereference"] elif ldap_backend_type == "openldap": - backend_modules = ["normalise", "entryuuid", "paged_searches"] + backend_modules = ["entryuuid", "paged_searches"] # OpenLDAP handles subtree renames, so we don't want to do any of these things tdb_modules_list = ["extended_dn_out_dereference"] elif ldap_backend is not None: -- 2.34.1