[PATCH][SAMBA4] Ambiguous Name Resolution module
simo
idra at samba.org
Wed Dec 12 14:28:51 GMT 2007
On Wed, 2007-12-12 at 23:17 +1100, Andrew Bartlett wrote:
> Attached is a patch to partially implement ambigious name resolution.
> Apparenelty this is a big feature used by outlook, and inherited from
> exchange into AD, but it is also used by the 'find' feature in the
> Active Directory users and computers plugin.
>
> comments?
So this is not subject to a control ? Interesting (and depressing)
> +/**
> + * Given the match for an 'ambigious name resolution' query, create a
> + * parse tree with an 'or' of all the anr attributes in the schema.
> + */
> +
> +typedef struct ldb_parse_tree *(*ldb_parse_tree_callback_t)(struct
> ldb_parse_tree *tree,
> + const
> struct ldb_val *match,
> + void
> *context);
Why do you call this a callback when it is not ?
As far as I can see it is always called before the requested is passed
down.
> +struct ldb_parse_tree *anr_replace_callback(struct ldb_parse_tree
> *tree,
> + const struct ldb_val
> *match,
> + void *context)
> +{
> + struct anr_context *anr_context = talloc_get_type(context,
> struct anr_context);
> + struct ldb_module *module = anr_context->module;
> + struct ldb_parse_tree *tmp_tree, *prefix_match;
> + enum ldb_parse_op op;
> + struct dsdb_attribute *cur;
> + const struct dsdb_schema *schema =
> dsdb_get_schema(module->ldb);
> + if (!schema) {
> + ldb_asprintf_errstring(module->ldb, "no schema with
> which to construct anr filter");
> + return NULL;
> + }
> +
> + anr_context->found_anr = true;
> +
> + if (match->length > 1 && match->data[0] == '=') {
> + DATA_BLOB *match2 = talloc(tree, DATA_BLOB);
> + *match2 = data_blob_const(match->data+1, match->length
> - 1);
> + if (match2 == NULL){
> + ldb_oom(module->ldb);
> + return NULL;
> + }
> + match = match2;
> + op = LDB_OP_EQUALITY;
> + } else {
> + op = LDB_OP_SUBSTRING;
> + }
> + for (cur = schema->attributes; cur; cur = cur->next) {
> + if (!(cur->searchFlags & 0x4)) continue;
How many attributes do have this search flag ?
> + /* Start with a simple prefix match */
> + prefix_match = talloc(tree, struct ldb_parse_tree);
> +
> + prefix_match->operation = op;
> + switch (op) {
> + case LDB_OP_SUBSTRING:
> + prefix_match->u.substring.attr =
> cur->lDAPDisplayName;
> +
> + prefix_match->u.substring.start_with_wildcard
> = 0;
> + prefix_match->u.substring.end_with_wildcard =
> 1;
> + prefix_match->u.substring.chunks =
> talloc_array(prefix_match, struct ldb_val *, 2);
> +
> + if (prefix_match->u.substring.chunks == NULL){
> + ldb_oom(module->ldb);
> + return NULL;
> + }
> + prefix_match->u.substring.chunks[0] = match;
> + prefix_match->u.substring.chunks[1] = NULL;
> + break;
> + case LDB_OP_EQUALITY:
> + prefix_match->u.equality.attr =
> cur->lDAPDisplayName;
> + prefix_match->u.equality.value = *match;
> + break;
> + }
> +
> + if (tree) {
> + /* Inject an 'or' with the current tree */
> + tmp_tree = talloc(tree, struct
> ldb_parse_tree);
> + if (tmp_tree == NULL){
> + ldb_oom(module->ldb);
> + return NULL;
> + }
> + tmp_tree->operation = LDB_OP_OR;
> +
> + tmp_tree->u.list.num_elements = 2;
> + tmp_tree->u.list.elements =
> talloc_array(tmp_tree, struct ldb_parse_tree *, 2);
> + if (!tmp_tree->u.list.elements) {
> + ldb_oom(module->ldb);
> + return NULL;
> + }
> + tmp_tree->u.list.elements[0] =
> talloc_steal(tmp_tree, tree);
> + tmp_tree->u.list.elements[1] =
> talloc_steal(tmp_tree, prefix_match);
> + tree = tmp_tree;
> + } else {
> + tree = prefix_match;
> + }
> + }
> + return tree;
> +}
> +
> +/*
> + replace any occurances of an attribute with a new, generated
occurrences ---- ^^^^^^^^^^
> attribute tree
> +*/
> +struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree
> *tree,
> + const char *attr,
> + ldb_parse_tree_callback_t
> callback,
> + void *context)
> +{
> + int i;
> + switch (tree->operation) {
> + case LDB_OP_AND:
> + case LDB_OP_OR:
> + for (i=0;i<tree->u.list.num_elements;i++) {
> + tree->u.list.elements[i] =
> anr_replace_subtrees(tree->u.list.elements[i],
> + attr, callback, context);
> + if (!tree->u.list.elements[i]) {
> + return NULL;
> + }
> + }
> + break;
> + case LDB_OP_NOT:
> + tree->u.isnot.child =
> anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
> + if (!tree->u.isnot.child) {
> + return NULL;
> + }
> + break;
> + case LDB_OP_EQUALITY:
> + if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
> + tree = callback(tree,
> &tree->u.equality.value,
> + context);
> + if (!tree) {
> + return NULL;
> + }
> + }
> + break;
> + case LDB_OP_SUBSTRING:
> + if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
> + if (tree->u.substring.start_with_wildcard == 0
> &&
> + tree->u.substring.end_with_wildcard == 1
> &&
> + tree->u.substring.chunks[0] != NULL &&
> + tree->u.substring.chunks[1] == NULL) {
> + tree = callback(tree,
> tree->u.substring.chunks[0], context);
> + if (!tree) {
> + return NULL;
> + }
> + }
> + }
> + break;
> + }
> + return tree;
> +}
> +
> +/* search */
> +static int anr_search(struct ldb_module *module, struct ldb_request
> *req)
> +{
> + struct ldb_parse_tree *anr_tree;
> + struct anr_context *context = talloc(req, struct anr_context);
> + if (!context) {
> + ldb_oom(module->ldb);
> + return LDB_ERR_OPERATIONS_ERROR;
> + }
> +
> + context->module = module;
> + context->found_anr = false;
> +
> + /* Yes, this is a problem with req->op.search.tree being
> const... */
> + anr_tree = anr_replace_subtrees(req->op.search.tree, "anr",
> anr_replace_callback, context);
> + if (!anr_tree) {
> + return LDB_ERR_OPERATIONS_ERROR;
> + }
> +
> + if (context->found_anr) {
> + /* The above function modifies the tree if it finds
> "anr", so no
> + * point just setting this on the down_req */
> + req->op.search.tree = anr_tree;
> + }
> +
> + /* TODO: Add a callback, and ensure we retry the search with
> surname and given name if we fail to match */
Can you explain this?
Actually can you ex-plain or point to documentation that explain how ANR
is supposed to work ?
Simo.
--
Simo Sorce
Samba Team GPL Compliance Officer <simo at samba.org>
Senior Software Engineer at Red Hat Inc. <ssorce at redhat.com>
More information about the samba-technical
mailing list