X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=lib%2Fldb%2Fcommon%2Fldb_match.c;h=a493daec49f866edfa4f7896ac5797e0e9efb715;hb=faa4be0535fd41bf282b1afc749a05412f4ee96c;hp=7918aec65f166378a232e9da4513f1dd19928ff5;hpb=172aa0ee3885720464e8eacd728eb1a1342fc9b4;p=obnox%2Fsamba%2Fsamba-obnox.git diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index 7918aec65f1..a493daec49f 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -33,6 +33,7 @@ */ #include "ldb_private.h" +#include "dlinklist.h" /* check if the scope matches in a search result @@ -342,7 +343,7 @@ static int ldb_match_substring(struct ldb_context *ldb, /* - bitwise-and comparator + bitwise and/or comparator depending on oid */ static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2, bool *matched) @@ -385,10 +386,48 @@ static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, con return LDB_SUCCESS; } +static int ldb_match_bitmask(struct ldb_context *ldb, + const char *oid, + const struct ldb_message *msg, + const char *attribute_to_match, + const struct ldb_val *value_to_match, + bool *matched) +{ + unsigned int i; + struct ldb_message_element *el; + + /* find the message element */ + el = ldb_msg_find_element(msg, attribute_to_match); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + for (i=0;inum_values;i++) { + int ret; + struct ldb_val *v = &el->values[i]; + + ret = ldb_comparator_bitmask(oid, v, value_to_match, matched); + if (ret != LDB_SUCCESS) { + return ret; + } + if (*matched) { + return LDB_SUCCESS; + } + } + + *matched = false; + return LDB_SUCCESS; +} + /* always return false */ -static int ldb_comparator_false(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2, +static int ldb_comparator_false(struct ldb_context *ldb, + const char *oid, + const struct ldb_message *msg, + const char *attribute_to_match, + const struct ldb_val *value_to_match, bool *matched) { *matched = false; @@ -396,6 +435,23 @@ static int ldb_comparator_false(const char *oid, const struct ldb_val *v1, const } +static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb, + const char *oid) +{ + struct ldb_extended_match_entry *extended_match_rule; + + for (extended_match_rule = ldb->extended_match_rules; + extended_match_rule; + extended_match_rule = extended_match_rule->next) { + if (strcmp(extended_match_rule->rule->oid, oid) == 0) { + return extended_match_rule->rule; + } + } + + return NULL; +} + + /* extended match, handles things like bitops */ @@ -404,17 +460,7 @@ static int ldb_match_extended(struct ldb_context *ldb, const struct ldb_parse_tree *tree, enum ldb_scope scope, bool *matched) { - unsigned int i; - const struct { - const char *oid; - int (*comparator)(const char *, const struct ldb_val *, const struct ldb_val *, bool *); - } rules[] = { - { LDB_OID_COMPARATOR_AND, ldb_comparator_bitmask}, - { LDB_OID_COMPARATOR_OR, ldb_comparator_bitmask}, - { SAMBA_LDAP_MATCH_ALWAYS_FALSE, ldb_comparator_false} - }; - int (*comp)(const char *,const struct ldb_val *, const struct ldb_val *, bool *) = NULL; - struct ldb_message_element *el; + const struct ldb_extended_match_rule *rule; if (tree->u.extended.dnAttributes) { /* FIXME: We really need to find out what this ":dn" part in @@ -432,33 +478,16 @@ static int ldb_match_extended(struct ldb_context *ldb, return LDB_ERR_INAPPROPRIATE_MATCHING; } - for (i=0;iu.extended.rule_id) == 0) { - comp = rules[i].comparator; - break; - } - } - if (comp == NULL) { + rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id); + if (rule == NULL) { ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s", tree->u.extended.rule_id); return LDB_ERR_INAPPROPRIATE_MATCHING; } - /* find the message element */ - el = ldb_msg_find_element(msg, tree->u.extended.attr); - if (el == NULL) { - *matched = false; - return LDB_SUCCESS; - } - - for (i=0;inum_values;i++) { - int ret = comp(tree->u.extended.rule_id, &el->values[i], &tree->u.extended.value, matched); - if (ret != LDB_SUCCESS) return ret; - if (*matched) return LDB_SUCCESS; - } - - *matched = false; - return LDB_SUCCESS; + return rule->callback(ldb, rule->oid, msg, + tree->u.extended.attr, + &tree->u.extended.value, matched); } /* @@ -587,5 +616,81 @@ int ldb_match_msg_objectclass(const struct ldb_message *msg, return 0; } +_PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb) +{ + struct ldb_extended_match_rule *bitmask_and; + struct ldb_extended_match_rule *bitmask_or; + struct ldb_extended_match_rule *always_false; + int ret; + + /* Register bitmask-and match */ + bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule); + if (bitmask_and == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + bitmask_and->oid = LDB_OID_COMPARATOR_AND; + bitmask_and->callback = ldb_match_bitmask; + + ret = ldb_register_extended_match_rule(ldb, bitmask_and); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* Register bitmask-or match */ + bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule); + if (bitmask_or == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + bitmask_or->oid = LDB_OID_COMPARATOR_OR; + bitmask_or->callback = ldb_match_bitmask; + + ret = ldb_register_extended_match_rule(ldb, bitmask_or); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* Register always-false match */ + always_false = talloc_zero(ldb, struct ldb_extended_match_rule); + if (always_false == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE; + always_false->callback = ldb_comparator_false; + + ret = ldb_register_extended_match_rule(ldb, always_false); + if (ret != LDB_SUCCESS) { + return ret; + } + + return LDB_SUCCESS; +} + +/* + register a new ldb backend + + if override is true, then override any existing backend for this prefix +*/ +int ldb_register_extended_match_rule(struct ldb_context *ldb, + const struct ldb_extended_match_rule *rule) +{ + const struct ldb_extended_match_rule *lookup_rule; + struct ldb_extended_match_entry *entry; + + lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid); + if (lookup_rule) { + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } + + entry = talloc_zero(ldb, struct ldb_extended_match_entry); + if (!entry) { + return LDB_ERR_OPERATIONS_ERROR; + } + entry->rule = rule; + DLIST_ADD_END(ldb->extended_match_rules, entry, struct ldb_extended_match_entry); + + return LDB_SUCCESS; +} -