diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-06-13 07:36:52 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:18:06 -0500 |
commit | 8fd5825a890db4f08966e4b262b03fb7868cc4c2 (patch) | |
tree | 7b0d235d4110bf5b16006f52252744c5568f0e2a /source4 | |
parent | 8f31f8c57e9147a3b073347153f5724e2267b1bc (diff) | |
download | samba-8fd5825a890db4f08966e4b262b03fb7868cc4c2.tar.gz samba-8fd5825a890db4f08966e4b262b03fb7868cc4c2.tar.bz2 samba-8fd5825a890db4f08966e4b262b03fb7868cc4c2.zip |
r7524: make the ldap ASN.1 filter parse code go via a struct
ldb_parse_tree. This also fixes the error handling.
next step will be to pass the parse tree straight into ldb, avoiding
the string encoding completely.
(This used to be commit 235cf625e20767c8d5d30c5955ae45e1fdf88bf2)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/ldap/ldap.c | 184 |
1 files changed, 107 insertions, 77 deletions
diff --git a/source4/libcli/ldap/ldap.c b/source4/libcli/ldap/ldap.c index f383d08074..2718dd7e34 100644 --- a/source4/libcli/ldap/ldap.c +++ b/source4/libcli/ldap/ldap.c @@ -413,122 +413,152 @@ static void ldap_decode_response(TALLOC_CTX *mem_ctx, } } -static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data, - const char **filterp) +static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, + struct asn1_data *data) { uint8_t filter_tag, tag_desc; - char *filter = NULL; - - *filterp = NULL; + struct ldb_parse_tree *ret; - if (!asn1_peek_uint8(data, &filter_tag)) - return False; + if (!asn1_peek_uint8(data, &filter_tag)) { + return NULL; + } tag_desc = filter_tag; filter_tag &= 0x1f; /* strip off the asn1 stuff */ tag_desc &= 0xe0; - switch(filter_tag) { - case 0: { - /* AND of one or more filters */ - if (tag_desc != 0xa0) /* context compount */ - return False; - - asn1_start_tag(data, ASN1_CONTEXT(0)); + ret = talloc(mem_ctx, struct ldb_parse_tree); + if (ret == NULL) return NULL; - filter = talloc_strdup(mem_ctx, "(&"); - if (filter == NULL) - return False; - - while (asn1_tag_remaining(data) > 0) { - const char *subfilter; - if (!ldap_decode_filter(mem_ctx, data, &subfilter)) - return False; - filter = talloc_asprintf_append(filter, "%s", subfilter); - if (filter == NULL) - return False; + switch(filter_tag) { + case 0: + case 1: + /* AND or OR of one or more filters */ + ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR; + ret->u.list.num_elements = 0; + ret->u.list.elements = NULL; + + if (tag_desc != 0xa0) { + /* context compount */ + goto failed; } - asn1_end_tag(data); - - filter = talloc_asprintf_append(filter, ")"); - break; - } - case 1: { - /* OR of one or more filters */ - if (tag_desc != 0xa0) /* context compount */ - return False; - asn1_start_tag(data, ASN1_CONTEXT(1)); - - filter = talloc_strdup(mem_ctx, "(|"); - if (filter == NULL) - return False; + if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) { + goto failed; + } while (asn1_tag_remaining(data) > 0) { - const char *subfilter; - if (!ldap_decode_filter(mem_ctx, data, &subfilter)) - return False; - filter = talloc_asprintf_append(filter, "%s", subfilter); - if (filter == NULL) - return False; + struct ldb_parse_tree *subtree; + subtree = ldap_decode_filter_tree(ret, data); + if (subtree == NULL) { + goto failed; + } + ret->u.list.elements = + talloc_realloc(ret, ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements+1); + if (ret->u.list.elements == NULL) { + goto failed; + } + talloc_steal(ret->u.list.elements, subtree); + ret->u.list.elements[ret->u.list.num_elements] = subtree; + ret->u.list.num_elements++; + } + if (!asn1_end_tag(data)) { + goto failed; } - - asn1_end_tag(data); - - filter = talloc_asprintf_append(filter, ")"); break; - } + case 3: { /* equalityMatch */ const char *attrib; DATA_BLOB value; - struct ldb_val val; - if (tag_desc != 0xa0) /* context compound */ - return False; + ret->operation = LDB_OP_SIMPLE; + + if (tag_desc != 0xa0) { + /* context compound */ + goto failed; + } + asn1_start_tag(data, ASN1_CONTEXT(3)); 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)) - return False; - val.data = value.data; - val.length = value.length; - filter = talloc_asprintf(mem_ctx, "(%s=%s)", - attrib, ldb_binary_encode(mem_ctx, val)); - data_blob_free(&value); + if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) { + goto failed; + } + 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; break; } case 7: { /* Normal presence, "attribute=*" */ int attr_len; - char *attr_name; - if (tag_desc != 0x80) /* context simple */ - return False; - if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7))) - return False; + if (tag_desc != 0x80) { + /* context simple */ + goto failed; + } + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7))) { + goto failed; + } + + ret->operation = LDB_OP_SIMPLE; + attr_len = asn1_tag_remaining(data); - attr_name = malloc(attr_len+1); - if (attr_name == NULL) - return False; - asn1_read(data, attr_name, attr_len); - attr_name[attr_len] = '\0'; - filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name); - SAFE_FREE(attr_name); - asn1_end_tag(data); + + ret->u.simple.attr = talloc_size(ret, attr_len+1); + if (ret->u.simple.attr == NULL) { + goto failed; + } + if (!asn1_read(data, ret->u.simple.attr, attr_len)) { + goto failed; + } + ret->u.simple.attr[attr_len] = 0; + ret->u.simple.value.data = talloc_strdup(ret, "*"); + if (ret->u.simple.value.data == NULL) { + goto failed; + } + ret->u.simple.value.length = 1; + if (!asn1_end_tag(data)) { + goto failed; + } break; } default: - return False; + DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag)); + goto failed; } - if (filter == NULL) - return False; + + return ret; - *filterp = filter; +failed: + talloc_free(ret); + DEBUG(0,("Failed to parse ASN.1 LDAP filter\n")); + return NULL; +} + + +static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data, + const char **filterp) +{ + struct ldb_parse_tree *tree; + tree = ldap_decode_filter_tree(mem_ctx, data); + if (tree == NULL) { + return False; + } + *filterp = ldb_filter_from_tree(mem_ctx, tree); + talloc_free(tree); + if (*filterp == NULL) { + return False; + } return True; } + + static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldap_attribute *attrib) { |