summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-06-14 01:35:44 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:18:08 -0500
commit4fec6356ea190d202783fe19013387462a22c441 (patch)
tree7c36a84ebd98b7d48d4613619218c5c557392f54 /source4/lib/ldb
parentf29b9278bb782b48c4f31dd7d42dc530ce598969 (diff)
downloadsamba-4fec6356ea190d202783fe19013387462a22c441.tar.gz
samba-4fec6356ea190d202783fe19013387462a22c441.tar.bz2
samba-4fec6356ea190d202783fe19013387462a22c441.zip
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)
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/common/ldb_parse.c71
-rw-r--r--source4/lib/ldb/include/ldb.h9
-rw-r--r--source4/lib/ldb/include/ldb_private.h4
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c4
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c5
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_match.c114
6 files changed, 193 insertions, 14 deletions
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;
+}
+
+
/*
<simple> ::= <attributetype> <filtertype> <attributevalue>
*/
@@ -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;
@@ -156,6 +157,12 @@ struct ldb_parse_tree {
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;
} list;
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;i<msg->num_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;j<msg->elements[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;i<el->num_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;i<ARRAY_SIZE(rules);i++) {
+ if (strcmp(rules[i].oid, tree->u.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;i<el->num_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);