summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2005-07-17 14:16:41 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:29:35 -0500
commitf4576157edab9d3e39a88342312fc42ba6e59469 (patch)
treec25f069153161c82595b6336bbe486d762a960f7
parent7bcccfc000a22c1f686341678f171bcfaed19763 (diff)
downloadsamba-f4576157edab9d3e39a88342312fc42ba6e59469.tar.gz
samba-f4576157edab9d3e39a88342312fc42ba6e59469.tar.bz2
samba-f4576157edab9d3e39a88342312fc42ba6e59469.zip
r8530: Now our ldap server is able to fullfill present and substring searches
(This used to be commit a910671bd8c6d2d8d5b6ff30fc07ead244e696f1)
-rw-r--r--source4/libcli/ldap/ldap.c220
1 files changed, 184 insertions, 36 deletions
diff --git a/source4/libcli/ldap/ldap.c b/source4/libcli/ldap/ldap.c
index 5a45e6524e..b5e142ff6c 100644
--- a/source4/libcli/ldap/ldap.c
+++ b/source4/libcli/ldap/ldap.c
@@ -34,17 +34,26 @@ static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
int i;
switch (tree->operation) {
- case LDB_OP_SIMPLE:
- if ((tree->u.simple.value.length == 1) &&
- (((char *)(tree->u.simple.value.data))[0] == '*')) {
- /* Just a presence test */
- asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
- asn1_write(data, tree->u.simple.attr,
- strlen(tree->u.simple.attr));
- asn1_pop_tag(data);
- return !data->has_error;
+ case LDB_OP_AND:
+ case LDB_OP_OR:
+ asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
+ for (i=0; i<tree->u.list.num_elements; i++) {
+ if (!ldap_push_filter(data, tree->u.list.elements[i])) {
+ return False;
+ }
}
+ asn1_pop_tag(data);
+ break;
+ case LDB_OP_NOT:
+ asn1_push_tag(data, ASN1_CONTEXT(2));
+ if (!ldap_push_filter(data, tree->u.isnot.child)) {
+ return False;
+ }
+ asn1_pop_tag(data);
+ break;
+
+ case LDB_OP_SIMPLE:
/* equality test */
asn1_push_tag(data, ASN1_CONTEXT(3));
asn1_write_OctetString(data, tree->u.simple.attr,
@@ -54,6 +63,51 @@ static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
asn1_pop_tag(data);
break;
+ case LDB_OP_SUBSTRING:
+ /*
+ SubstringFilter ::= SEQUENCE {
+ type AttributeDescription,
+ -- at least one must be present
+ substrings SEQUENCE OF CHOICE {
+ initial [0] LDAPString,
+ any [1] LDAPString,
+ final [2] LDAPString } }
+ */
+ asn1_push_tag(data, ASN1_CONTEXT(4));
+ asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
+ asn1_push_tag(data, ASN1_SEQUENCE(0));
+ i = 0;
+ if ( ! tree->u.substring.start_with_wildcard) {
+ asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
+ asn1_write_LDAPString(data, tree->u.substring.chunks[i]->data);
+ asn1_pop_tag(data);
+ i++;
+ }
+ while (tree->u.substring.chunks[i]) {
+ int ctx;
+
+ if (( ! tree->u.substring.chunks[i + 1]) &&
+ (tree->u.substring.end_with_wildcard == 0)) {
+ ctx = 2;
+ } else {
+ ctx = 1;
+ }
+ asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
+ asn1_write_LDAPString(data, tree->u.substring.chunks[i]->data);
+ asn1_pop_tag(data);
+ i++;
+ }
+ asn1_pop_tag(data);
+ asn1_pop_tag(data);
+ break;
+
+ case LDB_OP_PRESENT:
+ /* present test */
+ asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
+ asn1_write_LDAPString(data, tree->u.present.attr);
+ asn1_pop_tag(data);
+ return !data->has_error;
+
case LDB_OP_EXTENDED:
/*
MatchingRuleAssertion ::= SEQUENCE {
@@ -82,26 +136,6 @@ static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
asn1_pop_tag(data);
asn1_pop_tag(data);
break;
-
-
- case LDB_OP_AND:
- case LDB_OP_OR:
- asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
- for (i=0; i<tree->u.list.num_elements; i++) {
- if (!ldap_push_filter(data, tree->u.list.elements[i])) {
- return False;
- }
- }
- asn1_pop_tag(data);
- break;
-
- case LDB_OP_NOT:
- asn1_push_tag(data, ASN1_CONTEXT(2));
- if (!ldap_push_filter(data, tree->u.isnot.child)) {
- return False;
- }
- asn1_pop_tag(data);
- break;
default:
return False;
@@ -440,6 +474,30 @@ static void ldap_decode_response(TALLOC_CTX *mem_ctx,
}
}
+static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
+{
+
+ chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
+ if (chunks == NULL) {
+ return NULL;
+ }
+
+ chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
+ if (chunks[chunk_num] == NULL) {
+ return NULL;
+ }
+
+ chunks[chunk_num]->data = talloc_strdup(mem_ctx, value);
+ if (chunks[chunk_num]->data == NULL) {
+ return NULL;
+ }
+ chunks[chunk_num]->length = strlen(value) + 1;
+
+ chunks[chunk_num + 1] = NULL;
+
+ return chunks;
+}
+
/*
parse the ASN.1 formatted search string into a ldb_parse_tree
@@ -528,6 +586,100 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
ret->u.simple.value.length = value.length;
break;
}
+ case 4: {
+ /* substrings */
+ DATA_BLOB attr;
+ uint8_t subs_tag;
+ char *value;
+ int chunk_num = 0;
+
+ if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
+ goto failed;
+ }
+ if (!asn1_read_OctetString(data, &attr)) {
+ goto failed;
+ }
+
+ ret->operation = LDB_OP_SUBSTRING;
+ ret->u.substring.attr = talloc_memdup(ret, attr.data, attr.length + 1);
+ ret->u.substring.attr[attr.length] = '\0';
+ ret->u.substring.chunks = NULL;
+ ret->u.substring.start_with_wildcard = 1;
+ ret->u.substring.end_with_wildcard = 1;
+
+ if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+ goto failed;
+ }
+
+ while (asn1_tag_remaining(data)) {
+ asn1_peek_uint8(data, &subs_tag);
+ subs_tag &= 0x1f; /* strip off the asn1 stuff */
+ if (subs_tag > 2) goto failed;
+
+ asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
+ asn1_read_LDAPString(data, &value);
+ asn1_end_tag(data);
+
+ switch (subs_tag) {
+ case 0:
+ if (ret->u.substring.chunks != NULL) {
+ /* initial value found in the middle */
+ goto failed;
+ }
+
+ ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
+ if (ret->u.substring.chunks == NULL) {
+ goto failed;
+ }
+
+ ret->u.substring.start_with_wildcard = 0;
+ chunk_num = 1;
+ break;
+
+ case 1:
+ if (ret->u.substring.end_with_wildcard == 0) {
+ /* "any" value found after a "final" value */
+ goto failed;
+ }
+
+ ret->u.substring.chunks = ldap_decode_substring(ret,
+ ret->u.substring.chunks,
+ chunk_num,
+ value);
+ if (ret->u.substring.chunks == NULL) {
+ goto failed;
+ }
+
+ chunk_num++;
+ break;
+
+ case 2:
+ ret->u.substring.chunks = ldap_decode_substring(ret,
+ ret->u.substring.chunks,
+ chunk_num,
+ value);
+ if (ret->u.substring.chunks == NULL) {
+ goto failed;
+ }
+
+ ret->u.substring.end_with_wildcard = 0;
+ break;
+
+ default:
+ goto failed;
+ }
+
+ }
+
+ if (!asn1_end_tag(data)) { /* SEQUENCE */
+ goto failed;
+ }
+
+ if (!asn1_end_tag(data)) {
+ goto failed;
+ }
+ break;
+ }
case 7: {
/* Normal presence, "attribute=*" */
char *attr;
@@ -539,13 +691,9 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
goto failed;
}
- ret->operation = LDB_OP_SIMPLE;
- 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;
- }
- ret->u.simple.value.length = 1;
+ ret->operation = LDB_OP_PRESENT;
+ ret->u.present.attr = talloc_steal(ret, attr);
+
if (!asn1_end_tag(data)) {
goto failed;
}