The branch, master has been updated via c5d38fd45abb037ff03dfb196c7fd0e2f59b1f28 (commit) via 93e1e8bec92a828ab343c6a4cc53f3759de557ba (commit) via 7fbd18a9dd0fb07aceffd2494de8fc9710a427ce (commit) via d80058f64edde55a4543d79475bb2a5730c2ab98 (commit) via 46dab92a2ddb4af3706de15894acc54b0b2b8d7b (commit) from c14b2eb8ddba17b6e349038671124e70a66e6723 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c5d38fd45abb037ff03dfb196c7fd0e2f59b1f28 Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 20 06:05:59 2009 +0200 blackbox/test_ldb.sh: test searching using OIDs instead of names for attributes and classes metze commit 93e1e8bec92a828ab343c6a4cc53f3759de557ba Author: Stefan Metzmacher <me...@samba.org> Date: Sat Sep 19 07:54:59 2009 +0200 s4:provision: add the 'resolve_oids' on the top of the module stack metze commit 7fbd18a9dd0fb07aceffd2494de8fc9710a427ce Author: Stefan Metzmacher <me...@samba.org> Date: Sat Sep 19 07:01:26 2009 +0200 dsdb/samdb: add resolve_oids module Windows Servers allow OID strings to be used instead of attribute/class names. For now we only resolve the OIDs in the search expressions, the rest will follow. metze commit d80058f64edde55a4543d79475bb2a5730c2ab98 Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 20 05:42:27 2009 +0200 s4:build: require ldb 0.9.7 metze commit 46dab92a2ddb4af3706de15894acc54b0b2b8d7b Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 20 05:41:42 2009 +0200 s4:ldb: add ldb_parse_tree_copy_shallow() and change version to 0.9.7 metze ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/config.mk | 11 + source4/dsdb/samdb/ldb_modules/resolve_oids.c | 427 +++++++++++++++++++++++++ source4/lib/ldb/common/ldb_parse.c | 58 ++++ source4/lib/ldb/configure.ac | 2 +- source4/lib/ldb/include/ldb.h | 6 + source4/min_versions.m4 | 2 +- source4/scripting/python/samba/provision.py | 3 +- testprogs/blackbox/test_ldb.sh | 16 + 8 files changed, 522 insertions(+), 3 deletions(-) create mode 100644 source4/dsdb/samdb/ldb_modules/resolve_oids.c Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index f868f8a..9384d06 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -346,3 +346,14 @@ SUBSYSTEM = LIBLDB ################################################ ldb_descriptor_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/descriptor.o + +################################################ +# Start MODULE ldb_resolve_oids +[MODULE::ldb_resolve_oids] +SUBSYSTEM = LIBLDB +PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS LIBNDR +INIT_FUNCTION = LDB_MODULE(resolve_oids) +# End MODULE ldb_resolve_oids +################################################ + +ldb_resolve_oids_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/resolve_oids.o diff --git a/source4/dsdb/samdb/ldb_modules/resolve_oids.c b/source4/dsdb/samdb/ldb_modules/resolve_oids.c new file mode 100644 index 0000000..f4d9eba --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/resolve_oids.c @@ -0,0 +1,427 @@ +/* + ldb database library + + Copyright (C) Stefan Metzmacher <me...@samba.org> 2009 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "ldb_module.h" +#include "dsdb/samdb/samdb.h" + +static int resolve_oids_replace_value(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct dsdb_attribute *a, + struct ldb_val *valp) +{ + const struct dsdb_attribute *va = NULL; + const struct dsdb_class *vo = NULL; + const void *p2; + char *str = NULL; + + if (a->syntax->oMSyntax != 6) { + return LDB_SUCCESS; + } + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p2) { + return LDB_SUCCESS; + } + + switch (a->attributeID_id) { + case DRSUAPI_ATTRIBUTE_objectClass: + case DRSUAPI_ATTRIBUTE_subClassOf: + case DRSUAPI_ATTRIBUTE_auxiliaryClass: + case DRSUAPI_ATTRIBUTE_systemPossSuperiors: + case DRSUAPI_ATTRIBUTE_possSuperiors: + str = talloc_strndup(schema, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + vo = dsdb_class_by_governsID_oid(schema, str); + talloc_free(str); + if (!vo) { + return LDB_SUCCESS; + } + *valp = data_blob_string_const(vo->lDAPDisplayName); + return LDB_SUCCESS; + case DRSUAPI_ATTRIBUTE_systemMustContain: + case DRSUAPI_ATTRIBUTE_systemMayContain: + case DRSUAPI_ATTRIBUTE_mustContain: + case DRSUAPI_ATTRIBUTE_mayContain: + str = talloc_strndup(schema, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + va = dsdb_attribute_by_attributeID_oid(schema, str); + talloc_free(str); + if (!va) { + return LDB_SUCCESS; + } + *valp = data_blob_string_const(va->lDAPDisplayName); + return LDB_SUCCESS; + case DRSUAPI_ATTRIBUTE_governsID: + case DRSUAPI_ATTRIBUTE_attributeID: + case DRSUAPI_ATTRIBUTE_attributeSyntax: + return LDB_SUCCESS; + } + + return LDB_SUCCESS; +} + +static int resolve_oids_parse_tree_replace(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_parse_tree *tree) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char **attrp; + const char *p1; + const void *p2; + struct ldb_val *valp = NULL; + + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;i<tree->u.list.num_elements;i++) { + resolve_oids_parse_tree_replace(ldb, schema, + tree->u.list.elements[i]); + } + return LDB_SUCCESS; + case LDB_OP_NOT: + resolve_oids_parse_tree_replace(ldb, schema, + tree->u.isnot.child); + return LDB_SUCCESS; + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + attrp = &tree->u.equality.attr; + valp = &tree->u.equality.value; + break; + case LDB_OP_SUBSTRING: + attrp = &tree->u.substring.attr; + break; + case LDB_OP_PRESENT: + attrp = &tree->u.present.attr; + break; + case LDB_OP_EXTENDED: + attrp = &tree->u.extended.attr; + valp = &tree->u.extended.value; + break; + default: + return LDB_SUCCESS; + } + + p1 = strchr(*attrp, '.'); + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p1 && !p2) { + return LDB_SUCCESS; + } + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, *attrp); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp); + } + if (!a) { + return LDB_SUCCESS; + } + + *attrp = a->lDAPDisplayName; + + if (!p2) { + return LDB_SUCCESS; + } + + if (a->syntax->oMSyntax != 6) { + return LDB_SUCCESS; + } + + return resolve_oids_replace_value(ldb, schema, a, valp); +} + +static int resolve_oids_element_replace(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_message_element *el) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char *p1; + + p1 = strchr(el->name, '.'); + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, el->name); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + } + if (!a) { + return LDB_SUCCESS; + } + + el->name = a->lDAPDisplayName; + + for (i=0; i < el->num_values; i++) { + int ret; + ret = resolve_oids_replace_value(ldb, schema, a, + &el->values[i]); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +static int resolve_oids_message_replace(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_message *msg) +{ + int i; + + for (i=0; i < msg->num_elements; i++) { + int ret; + ret = resolve_oids_element_replace(ldb, schema, + &msg->elements[i]); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +struct resolve_oids_context { + struct ldb_module *module; + struct ldb_request *req; +}; + +static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct resolve_oids_context *ac; + + ac = talloc_get_type_abort(req->context, struct resolve_oids_context); + ldb = ldb_module_get_ctx(ac->module); + + 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); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + return ldb_module_send_entry(ac->req, ares->message, 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, LDB_SUCCESS); + + } + return LDB_SUCCESS; +} + +static int resolve_oids_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct dsdb_schema *schema; + struct ldb_parse_tree *tree; + struct ldb_request *down_req; + struct resolve_oids_context *ac; + int ret; + + ldb = ldb_module_get_ctx(module); + schema = dsdb_get_schema(ldb); + + if (!schema) { + return ldb_next_request(module, req); + } + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.search.base)) { + return ldb_next_request(module, req); + } + + ac = talloc(req, struct resolve_oids_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->module = module; + ac->req = req; + + tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); + if (!tree) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = resolve_oids_parse_tree_replace(ldb, schema, + tree); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_search_req_ex(&down_req, ldb, ac, + req->op.search.base, + req->op.search.scope, + tree, + req->op.search.attrs, + req->controls, + ac, resolve_oids_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* go on with the call chain */ + return ldb_next_request(module, down_req); +} + +static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct dsdb_schema *schema; + int ret; + struct ldb_message *msg; + struct ldb_request *down_req; + struct resolve_oids_context *ac; + + ldb = ldb_module_get_ctx(module); + schema = dsdb_get_schema(ldb); + + if (!schema) { + return ldb_next_request(module, req); + } + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.add.message->dn)) { + return ldb_next_request(module, req); + } + + ac = talloc(req, struct resolve_oids_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->module = module; + ac->req = req; + + msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message); + if (!msg) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = resolve_oids_message_replace(ldb, schema, msg); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_add_req(&down_req, ldb, ac, + msg, + req->controls, + ac, resolve_oids_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* go on with the call chain */ + return ldb_next_request(module, down_req); +} + +static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct dsdb_schema *schema; + int ret; + struct ldb_message *msg; + struct ldb_request *down_req; + struct resolve_oids_context *ac; + + ldb = ldb_module_get_ctx(module); + schema = dsdb_get_schema(ldb); + + if (!schema) { + return ldb_next_request(module, req); + } + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.mod.message->dn)) { + return ldb_next_request(module, req); + } + + ac = talloc(req, struct resolve_oids_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->module = module; + ac->req = req; + + /* we have to copy the message as the caller might have it as a const */ + msg = ldb_msg_copy_shallow(ac, req->op.mod.message); + if (msg == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = resolve_oids_message_replace(ldb, schema, msg); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&down_req, ldb, ac, + msg, + req->controls, + ac, resolve_oids_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* go on with the call chain */ + return ldb_next_request(module, down_req); +} + +_PUBLIC_ const struct ldb_module_ops ldb_resolve_oids_module_ops = { + .name = "resolve_oids", + .search = resolve_oids_search, + .add = resolve_oids_add, + .modify = resolve_oids_modify, +}; + diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 0fab002..7f347c5 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -818,3 +818,61 @@ void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, break; } } + +/* + shallow copy a tree - copying only the elements array so that the caller + can safely add new elements without changing the message +*/ +struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_parse_tree *ot) +{ + int i; + struct ldb_parse_tree *nt; + + nt = talloc(mem_ctx, struct ldb_parse_tree); + if (!nt) { + return NULL; + } + + *nt = *ot; + + switch (ot->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree, + ot->u.list.num_elements); + if (!nt->u.list.elements) { + talloc_free(nt); + return NULL; + } + + for (i=0;i<ot->u.list.num_elements;i++) { + nt->u.list.elements[i] = + ldb_parse_tree_copy_shallow(nt->u.list.elements, + ot->u.list.elements[i]); + if (!nt->u.list.elements[i]) { + talloc_free(nt); + return NULL; + } + } + break; + case LDB_OP_NOT: + nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt, -- Samba Shared Repository