From 4fec6356ea190d202783fe19013387462a22c441 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 01:35:44 +0000 Subject: r7558: added support in ldb for extended ldap search requests. These are using to perform such things as bitop tests on integers. So far I have only added support for the 1.2.840.113556.1.4.803 and 1.2.840.113556.1.4.804 rules, which are for bitwise and/or (This used to be commit 5f773b065f1db959e59c02de68bcf30cef1a6c2c) --- source4/lib/ldb/common/ldb_parse.c | 71 +++++++++++++++++++ source4/lib/ldb/include/ldb.h | 9 ++- source4/lib/ldb/include/ldb_private.h | 4 ++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 4 ++ source4/lib/ldb/ldb_tdb/ldb_index.c | 5 ++ source4/lib/ldb/ldb_tdb/ldb_match.c | 114 ++++++++++++++++++++++++++---- 6 files changed, 193 insertions(+), 14 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index afcda60e8e..c9a35cc255 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -196,6 +196,61 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val) static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s); + +/* + parse an extended match + + possible forms: + (attr:oid:=value) + (attr:dn:oid:=value) + (attr:dn:=value) + (:dn:oid:=value) + + the ':dn' part sets the dnAttributes boolean if present + the oid sets the rule_id string + +*/ +static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, + char *attr, char *value) +{ + char *p1, *p2, *p3; + ret->operation = LDB_OP_EXTENDED; + ret->u.extended.value = ldb_binary_decode(ret, value); + p1 = strchr(attr, ':'); + if (p1 == NULL) goto failed; + p2 = strchr(p1+1, ':'); + if (p2 == NULL) goto failed; + p3 = strchr(p2+1, ':'); + + *p1 = 0; + *p2 = 0; + if (p3) *p3 = 0; + + ret->u.extended.attr = talloc_strdup(ret, attr); + if (ret->u.extended.attr == NULL) goto failed; + if (strcmp(p1+1, "dn") == 0) { + ret->u.extended.dnAttributes = 1; + if (p3) { + ret->u.extended.rule_id = talloc_strdup(ret, p2+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } else { + ret->u.extended.rule_id = NULL; + } + } else { + ret->u.extended.dnAttributes = 0; + ret->u.extended.rule_id = talloc_strdup(ret, p1+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } + ret->u.extended.value = ldb_binary_decode(ret, value); + + return ret; + +failed: + talloc_free(ret); + return NULL; +} + + /* ::= */ @@ -233,6 +288,11 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) talloc_free(ret); return NULL; } + + if (l[strlen(l)-1] == ':') { + /* its an extended match */ + return ldb_parse_extended(ret, l, val); + } ret->operation = LDB_OP_SIMPLE; ret->u.simple.attr = l; @@ -420,6 +480,17 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) tree->u.simple.attr, s); talloc_free(s); return ret; + case LDB_OP_EXTENDED: + s = ldb_binary_encode(mem_ctx, tree->u.extended.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s%s%s%s=%s)", + tree->u.extended.attr?tree->u.extended.attr:"", + tree->u.extended.dnAttributes?":dn":"", + tree->u.extended.rule_id?":":"", + tree->u.extended.rule_id?tree->u.extended.rule_id:"", + s); + talloc_free(s); + return ret; case LDB_OP_AND: case LDB_OP_OR: ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 02df0ae810..5773e39fa9 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -146,7 +146,8 @@ struct ldb_debug_ops { /* structues for ldb_parse_tree handling code */ -enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; +enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_EXTENDED=2, + LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; struct ldb_parse_tree { enum ldb_parse_op operation; @@ -155,6 +156,12 @@ struct ldb_parse_tree { char *attr; struct ldb_val value; } simple; + struct { + char *attr; + int dnAttributes; + char *rule_id; + struct ldb_val value; + } extended; struct { unsigned int num_elements; struct ldb_parse_tree **elements; diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 414d8c14a1..e022d68ec7 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -82,6 +82,10 @@ struct ldb_context { /* the modules init function */ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + /* The following definitions come from lib/ldb/common/ldb_modules.c */ int ldb_load_modules(struct ldb_context *ldb, const char *options[]); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 747938116a..4089f0bdb5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1117,6 +1117,10 @@ parsetree_to_sql(struct ldb_module *module, case LDB_OP_SIMPLE: break; + case LDB_OP_EXTENDED: +#warning "derrell, you'll need to work out how to handle bitops" + return NULL; + case LDB_OP_AND: ret = parsetree_to_sql(module, hTalloc, diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index b6ba413ba5..00b124a9cf 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -550,6 +550,11 @@ static int ltdb_index_dn(struct ldb_module *module, ret = ltdb_index_dn_leaf(module, tree, index_list, list); break; + case LDB_OP_EXTENDED: + /* we can't index with fancy bitops yet */ + ret = -1; + break; + case LDB_OP_AND: ret = ltdb_index_dn_and(module, tree, index_list, list); break; diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index abaa5e98c6..5bc59383a5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -262,7 +262,8 @@ static int match_leaf(struct ldb_module *module, const char *base, enum ldb_scope scope) { - unsigned int i, j; + unsigned int i; + struct ldb_message_element *el; if (!scope_match(msg->dn, base, scope)) { return 0; @@ -275,20 +276,104 @@ static int match_leaf(struct ldb_module *module, return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; } - for (i=0;inum_elements;i++) { - if (ldb_attr_cmp(msg->elements[i].name, tree->u.simple.attr) == 0) { - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; - } - for (j=0;jelements[i].num_values;j++) { - if (ltdb_val_equal(module, msg->elements[i].name, - &msg->elements[i].values[j], - &tree->u.simple.value)) { - return 1; - } - } + el = ldb_msg_find_element(msg, tree->u.simple.attr); + if (el == NULL) { + return 0; + } + + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + + for (i=0;inum_values;i++) { + if (ltdb_val_equal(module, el->name, &el->values[i], + &tree->u.simple.value)) { + return 1; + } + } + + return 0; +} + + +/* + bitwise-and comparator +*/ +static int comparator_and(struct ldb_val *v1, struct ldb_val *v2) +{ + unsigned i1, i2; + i1 = strtoul(v1->data, NULL, 0); + i2 = strtoul(v2->data, NULL, 0); + return ((i1 & i2) == i2); +} + +/* + bitwise-or comparator +*/ +static int comparator_or(struct ldb_val *v1, struct ldb_val *v2) +{ + unsigned i1, i2; + i1 = strtoul(v1->data, NULL, 0); + i2 = strtoul(v2->data, NULL, 0); + return ((i1 & i2) != 0); +} + + +/* + extended match, handles things like bitops +*/ +static int ltdb_extended_match(struct ldb_module *module, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + int i; + const struct { + const char *oid; + int (*comparator)(struct ldb_val *, struct ldb_val *); + } rules[] = { + { "1.2.840.113556.1.4.803", comparator_and}, + { "1.2.840.113556.1.4.804", comparator_or} + }; + int (*comp)(struct ldb_val *, struct ldb_val *) = NULL; + struct ldb_message_element *el; + + if (tree->u.extended.dnAttributes) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet"); + return -1; + } + if (tree->u.extended.rule_id == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); + return -1; + } + if (tree->u.extended.attr == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); + return -1; + } + + for (i=0;iu.extended.rule_id) == 0) { + comp = rules[i].comparator; + break; } } + if (comp == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n", + tree->u.extended.rule_id); + return -1; + } + + /* find the message element */ + el = ldb_msg_find_element(msg, tree->u.extended.attr); + if (el == NULL) { + return 0; + } + + for (i=0;inum_values;i++) { + int ret = comp(&el->values[i], &tree->u.extended.value); + if (ret == -1 || ret == 1) return ret; + } return 0; } @@ -314,6 +399,9 @@ int ltdb_message_match(struct ldb_module *module, case LDB_OP_SIMPLE: break; + case LDB_OP_EXTENDED: + return ltdb_extended_match(module, msg, tree, base, scope); + case LDB_OP_NOT: return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope); -- cgit