r7567: added wire parsing of NOT and extended ldap search requests. This
authorAndrew Tridgell <tridge@samba.org>
Tue, 14 Jun 2005 03:53:35 +0000 (03:53 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:10 +0000 (13:18 -0500)
allows us to parse and handle the complex queries we are getting from
w2k, such as

(|(|(&(!(groupType:1.2.840.113556.1.4.803=1))(groupType:1.2.840.113556.1.4.803=2147483648)(groupType:1.2.840.113556.1.4.804=6))(samAccountType=805306368))(samAccountType=805306369))
(This used to be commit 041bce591306a0fb26bd31fe371e30021ea5c0c1)

source4/libcli/ldap/ldap.c

index 0d310b4eed1d8fe566cba2e7fc75821ec63b6508..048a60317a05725767ea8739f9d81d955af2c6d3 100644 (file)
 
 static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
 {
+       int i;
+
        switch (tree->operation) {
-       case LDB_OP_SIMPLE: {
+       case LDB_OP_SIMPLE:
                if ((tree->u.simple.value.length == 1) &&
                    (((char *)(tree->u.simple.value.data))[0] == '*')) {
                        /* Just a presence test */
@@ -43,7 +45,7 @@ static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
                        return !data->has_error;
                }
 
-               /* Equality is all we currently do... */
+               /* equality test */
                asn1_push_tag(data, 0xa3);
                asn1_write_OctetString(data, tree->u.simple.attr,
                                      strlen(tree->u.simple.attr));
@@ -51,29 +53,51 @@ static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
                                      tree->u.simple.value.length);
                asn1_pop_tag(data);
                break;
-       }
-
-       case LDB_OP_AND: {
-               int i;
 
-               asn1_push_tag(data, 0xa0);
-               for (i=0; i<tree->u.list.num_elements; i++) {
-                       ldap_push_filter(data, tree->u.list.elements[i]);
+       case LDB_OP_EXTENDED:
+               /*
+                 MatchingRuleAssertion ::= SEQUENCE {
+                 matchingRule    [1] MatchingRuleID OPTIONAL,
+                 type            [2] AttributeDescription OPTIONAL,
+                 matchValue      [3] AssertionValue,
+                 dnAttributes    [4] BOOLEAN DEFAULT FALSE
+                 }
+               */
+               asn1_push_tag(data, 0xa9);
+               if (tree->u.extended.rule_id) {
+                       asn1_push_tag(data, 1);
+                       asn1_write_OctetString(data, tree->u.extended.rule_id,
+                                              strlen(tree->u.extended.rule_id));
+                       asn1_pop_tag(data);
+               }
+               if (tree->u.extended.attr) {
+                       asn1_push_tag(data, 2);
+                       asn1_write_OctetString(data, tree->u.extended.attr,
+                                              strlen(tree->u.extended.attr));
+                       asn1_pop_tag(data);
+               }
+               asn1_push_tag(data, 3);
+               asn1_write_OctetString(data, tree->u.extended.value.data,
+                                     tree->u.extended.value.length);
+               asn1_pop_tag(data);
+               if (tree->u.extended.dnAttributes) {
+                       asn1_push_tag(data, 4);
+                       asn1_write_BOOLEAN(data, True);
+                       asn1_pop_tag(data);
                }
                asn1_pop_tag(data);
                break;
-       }
-
-       case LDB_OP_OR: {
-               int i;
+               
 
-               asn1_push_tag(data, 0xa1);
+       case LDB_OP_AND:
+       case LDB_OP_OR:
+               asn1_push_tag(data, 0xa0 | (tree->operation==LDB_OP_AND?0:1));
                for (i=0; i<tree->u.list.num_elements; i++) {
                        ldap_push_filter(data, tree->u.list.elements[i]);
                }
                asn1_pop_tag(data);
                break;
-       }
+
        default:
                return False;
        }
@@ -464,25 +488,34 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
                }
                break;
 
-       case 3: {
-               /* equalityMatch */
-               const char *attrib;
-               DATA_BLOB value;
+       case 2:
+               /* 'not' operation */
+               if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
+                       goto failed;
+               }
 
-               ret->operation = LDB_OP_SIMPLE;
+               ret->operation = LDB_OP_NOT;
+               ret->u.not.child = ldap_decode_filter_tree(ret, data);
 
-               if (tag_desc != 0xa0) {
-                       /* context compound */
+               if (!asn1_end_tag(data)) {
                        goto failed;
                }
+               break;
 
-               asn1_start_tag(data, ASN1_CONTEXT(3));
+       case 3: {
+               /* equalityMatch */
+               const char *attrib;
+               DATA_BLOB value;
+
+               asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
                asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
                asn1_read_OctetString(data, &value);
                asn1_end_tag(data);
                if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
                        goto failed;
                }
+
+               ret->operation = LDB_OP_SIMPLE;
                ret->u.simple.attr = talloc_steal(ret, attrib);
                ret->u.simple.value.data = talloc_steal(ret, value.data);
                ret->u.simple.value.length = value.length;
@@ -490,37 +523,64 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
        }
        case 7: {
                /* Normal presence, "attribute=*" */
-               int attr_len;
-               if (tag_desc != 0x80) {
-                       /* context simple */
+               char *attr;
+
+               if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
                        goto failed;
                }
-               if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
+               if (!asn1_read_LDAPString(data, &attr)) {
                        goto failed;
                }
 
                ret->operation = LDB_OP_SIMPLE;
-
-               attr_len = asn1_tag_remaining(data);
-
-               ret->u.simple.attr = talloc_size(ret, attr_len+1);
-               if (ret->u.simple.attr == NULL) {
+               ret->u.simple.attr = talloc_steal(ret, attr);
+               ret->u.simple.value.data = talloc_strdup(ret, "*");
+               if (ret->u.simple.value.data == NULL) {
                        goto failed;
                }
-               if (!asn1_read(data, ret->u.simple.attr, attr_len)) {
+               ret->u.simple.value.length = 1;
+               if (!asn1_end_tag(data)) {
                        goto failed;
                }
-               ret->u.simple.attr[attr_len] = 0;
-               ret->u.simple.value.data = talloc_strdup(ret, "*");
-               if (ret->u.simple.value.data == NULL) {
+               break;
+       }
+       case 9: {
+               char *oid, *attr, *value;
+               uint8_t dnAttributes;
+               /* an extended search */
+               if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
                        goto failed;
                }
-               ret->u.simple.value.length = 1;
+
+               asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
+               asn1_read_LDAPString(data, &oid);
+               asn1_end_tag(data);
+               asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
+               asn1_read_LDAPString(data, &attr);
+               asn1_end_tag(data);
+               asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
+               asn1_read_LDAPString(data, &value);
+               asn1_end_tag(data);
+               asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
+               asn1_read_uint8(data, &dnAttributes);
+               asn1_end_tag(data);
+               if ((data->has_error) || (oid == NULL) || (value == NULL)) {
+                       goto failed;
+               }
+
+               ret->operation               = LDB_OP_EXTENDED;
+               ret->u.extended.attr         = talloc_steal(ret, attr);
+               ret->u.extended.rule_id      = talloc_steal(ret, oid);
+               ret->u.extended.value.data   = talloc_steal(ret, value);
+               ret->u.extended.value.length = strlen(value);
+               ret->u.extended.dnAttributes = dnAttributes;
+
                if (!asn1_end_tag(data)) {
                        goto failed;
                }
                break;
        }
+
        default:
                DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
                goto failed;