[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