From 3725b1817f1e26370015d955622f0705e9121714 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 15 Jan 2006 06:12:29 +0000 Subject: [PATCH] r12941: Add Attribute Scoped Search control want to see what it does ? do aq make test and try: ./bin/ldbsearch -H st/private/sam.ldb --controls=asq:1:member -s base -b 'CN=Administrators,CN=Builtin,DC=samba,DC=example,DC=com' 'objectclass=*' have fun. simo. (This used to be commit 900f4fd3435aacc3351f30afb77d3488d2cb4804) --- source4/lib/ldb/common/ldb_modules.c | 1 + source4/lib/ldb/config.mk | 10 ++ source4/lib/ldb/modules/asq.c | 220 +++++++++++++++++++++++++++ source4/lib/ldb/tools/ldbsearch.c | 4 + source4/setup/provision_init.ldif | 2 +- 5 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 source4/lib/ldb/modules/asq.c diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index f49ccf5413b..ddbdddedcc4 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -123,6 +123,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { "objectclass", objectclass_module_init }, { "paged_results", paged_results_module_init }, { "server_sort", server_sort_module_init }, + { "asq", asq_module_init }, #ifdef _SAMBA_BUILD_ { "objectguid", objectguid_module_init }, { "samldb", samldb_module_init }, diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index cbd91a6de65..fb1970be080 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -1,3 +1,13 @@ +################################################ +# Start MODULE libldb_asq +[MODULE::libldb_asq] +SUBSYSTEM = LIBLDB +OUTPUT_TYPE = MERGEDOBJ +OBJ_FILES = \ + modules/asq.o +# End MODULE libldb_asq +################################################ + ################################################ # Start MODULE libldb_sort [MODULE::libldb_sort] diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c new file mode 100644 index 00000000000..1fbf7521fb6 --- /dev/null +++ b/source4/lib/ldb/modules/asq.c @@ -0,0 +1,220 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** 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. + + This library 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 +*/ + +/* + * Name: ldb + * + * Component: ldb attribute scoped query control module + * + * Description: this module searches all the the objects pointed + * by the DNs contained in the references attribute + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/includes.h" + +#define ASQ_CTRL_SUCCESS 0 +#define ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX 21 +#define ASQ_CTRL_UNWILLING_TO_PERFORM 53 +#define ASQ_CTRL_AFFECTS_MULTIPLE_DSA 71 + +static int build_response(struct ldb_result *res, int result) +{ + struct ldb_asq_control *asq; + int i; + + if (res->controls) { + for (i = 0; res->controls[i]; i++); + res->controls = talloc_realloc(res, res->controls, struct ldb_control *, i + 2); + } else { + i = 0; + res->controls = talloc_array(res, struct ldb_control *, 2); + } + if (res->controls == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + res->controls[i] = talloc(res->controls, struct ldb_control); + if (res->controls[i] == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + res->controls[i]->oid = LDB_CONTROL_ASQ_OID; + res->controls[i]->critical = 0; + + asq = talloc_zero(res->controls[i], struct ldb_asq_control); + if (asq == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + asq->result = result; + + res->controls[i]->data = asq; + + res->controls[i + 1] = NULL; + + return LDB_SUCCESS; +} + +/* search */ +static int asq_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_control *control; + struct ldb_asq_control *asq_ctrl; + struct ldb_request *base_req; + struct ldb_message_element *el; + struct ldb_result *res; + char **base_attrs; + int i, c, ret; + + /* check if there's a paged request control */ + control = get_control_from_list(req->controls, LDB_CONTROL_ASQ_OID); + if (control == NULL) { + /* not found go on */ + return ldb_next_request(module, req); + } + + /* pre-allocate a clean result structure */ + req->op.search.res = res = talloc_zero(req, struct ldb_result); + if (res == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + /* check the search is well formed */ + if (req->op.search.scope != LDB_SCOPE_BASE) { + return build_response(res, ASQ_CTRL_UNWILLING_TO_PERFORM); + } + + asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control); + + /* get the object to retrieve the DNs to search */ + base_req = talloc_zero(req, struct ldb_request); + if (base_req == NULL) + return LDB_ERR_OPERATIONS_ERROR; + base_req->operation = LDB_REQ_SEARCH; + base_req->op.search.base = req->op.search.base; + base_req->op.search.scope = LDB_SCOPE_BASE; + base_req->op.search.tree = req->op.search.tree; + base_attrs = talloc_array(base_req, char *, 2); + if (base_attrs == NULL) + return LDB_ERR_OPERATIONS_ERROR; + base_attrs[0] = talloc_strdup(base_attrs, asq_ctrl->source_attribute); + if (base_attrs[0] == NULL) + return LDB_ERR_OPERATIONS_ERROR; + base_attrs[1] = NULL; + base_req->op.search.attrs = (const char * const *)base_attrs; + base_req->creds = req->creds; + + ret = ldb_request(module->ldb, base_req); + + if (ret != LDB_SUCCESS) + return ret; + + /* look up the DNs */ + el = ldb_msg_find_element(base_req->op.search.res->msgs[0], + asq_ctrl->source_attribute); + /* no values found */ + if (el == NULL) { + return build_response(res, ASQ_CTRL_SUCCESS); + } + + for (i = 0, c = 0; i < el->num_values; i++) { + struct ldb_request *exp_req; + + exp_req = talloc_zero(req, struct ldb_request); + if (exp_req == NULL) + return LDB_ERR_OPERATIONS_ERROR; + exp_req->operation = LDB_REQ_SEARCH; + exp_req->op.search.base = ldb_dn_explode(exp_req, el->values[i].data); + if (exp_req->op.search.base == NULL) { + build_response(res, ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX); + return LDB_ERR_OPERATIONS_ERROR; + } + exp_req->op.search.scope = LDB_SCOPE_BASE; + exp_req->op.search.tree = req->op.search.tree; + exp_req->op.search.attrs = req->op.search.attrs; + exp_req->creds = req->creds; + + ret = ldb_request(module->ldb, exp_req); + + if (ret != LDB_SUCCESS) + return ret; + + if (exp_req->op.search.res && exp_req->op.search.res->count != 0) { + if (res->msgs == NULL) { + res->msgs = talloc_array(res, + struct ldb_message *, 2); + } else { + res->msgs = talloc_realloc(res, res->msgs, + struct ldb_message *, c + 2); + } + if (res->msgs == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + res->msgs[c] = talloc_steal(res->msgs, exp_req->op.search.res->msgs[0]); + c++; + } + + if (res->msgs) { + res->msgs[c] = NULL; + res->count = c; + } + + talloc_free(exp_req); + } + + return build_response(res, ASQ_CTRL_SUCCESS); +} + +static int asq(struct ldb_module *module, struct ldb_request *req) +{ + switch (req->operation) { + + case LDB_REQ_SEARCH: + return asq_search(module, req); + + default: + return ldb_next_request(module, req); + + } +} + +static const struct ldb_module_ops asq_ops = { + .name = "asq", + .request = asq +}; + +struct ldb_module *asq_module_init(struct ldb_context *ldb, const char *options[]) +{ + struct ldb_module *ctx; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &asq_ops; + ctx->private_data = NULL; + + return ctx; +} diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index c81db7eb4da..582861eae28 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -305,6 +305,10 @@ static int do_search(struct ldb_context *ldb, ret = ldb_request(ldb, &req); if (ret != LDB_SUCCESS) { printf("search failed - %s\n", ldb_errstring(ldb)); + if (req.op.search.res && req.op.search.res->controls) { + /* TODO: handle_control */ + ; + } return -1; } diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif index 0d0261cf52d..a54c5632ca9 100644 --- a/source4/setup/provision_init.ldif +++ b/source4/setup/provision_init.ldif @@ -78,5 +78,5 @@ isSynchronized: TRUE #Add modules to the list to activate them by default #beware often order is important dn: @MODULES -@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,samldb,password_hash,operational,objectguid,rdn_name,objectclass +@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,objectclass