r7558: added support in ldb for extended ldap search requests. These are
authorAndrew Tridgell <tridge@samba.org>
Tue, 14 Jun 2005 01:35:44 +0000 (01:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:08 +0000 (13:18 -0500)
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

source/lib/ldb/common/ldb_parse.c
source/lib/ldb/include/ldb.h
source/lib/ldb/include/ldb_private.h
source/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source/lib/ldb/ldb_tdb/ldb_index.c
source/lib/ldb/ldb_tdb/ldb_match.c

index afcda60e8e7c2d55f8185fa99a6564f44630101a..c9a35cc25574bbd4d7a99b0c060d674193cde68a 100644 (file)
@@ -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);
index 02df0ae8103087a467f769b5e2fb5fcd46548ea9..5773e39fa9ee329e42372e381ab8501e23e7b757 100644 (file)
@@ -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;
index 414d8c14a11004a490252d341470a363b152bf23..e022d68ec76d56592b2c138b439cec33495cb1e0 100644 (file)
@@ -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[]);
index 747938116a8752476919ee332d165a18b1ab31b7..4089f0bdb5884ef16f97d77476f08d5e84f249ae 100644 (file)
@@ -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,
index b6ba413ba5bbff8ddd64ab031939f13753a2a927..00b124a9cfc9339b46765a763f550e72c4731107 100644 (file)
@@ -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;
index abaa5e98c640d2ebbc999e9a219e6065800ea538..5bc59383a5fa68b9673c7c074728d3a49af9dda2 100644 (file)
@@ -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);