1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-28 07:21:54 +03:00

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 commit is contained in:
Andrew Tridgell 2005-06-13 07:36:52 +00:00 committed by Gerald (Jerry) Carter
parent 9dab036fbe
commit 235cf625e2

View File

@ -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, static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
const char **filterp) struct asn1_data *data)
{ {
uint8_t filter_tag, tag_desc; uint8_t filter_tag, tag_desc;
char *filter = NULL; struct ldb_parse_tree *ret;
*filterp = NULL; if (!asn1_peek_uint8(data, &filter_tag)) {
return NULL;
if (!asn1_peek_uint8(data, &filter_tag)) }
return False;
tag_desc = filter_tag; tag_desc = filter_tag;
filter_tag &= 0x1f; /* strip off the asn1 stuff */ filter_tag &= 0x1f; /* strip off the asn1 stuff */
tag_desc &= 0xe0; tag_desc &= 0xe0;
ret = talloc(mem_ctx, struct ldb_parse_tree);
if (ret == NULL) return NULL;
switch(filter_tag) { switch(filter_tag) {
case 0: { case 0:
/* AND of one or more filters */ case 1:
if (tag_desc != 0xa0) /* context compount */ /* AND or OR of one or more filters */
return False; ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
ret->u.list.num_elements = 0;
ret->u.list.elements = NULL;
asn1_start_tag(data, ASN1_CONTEXT(0)); if (tag_desc != 0xa0) {
/* context compount */
filter = talloc_strdup(mem_ctx, "(&"); goto failed;
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;
}
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;
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;
} }
asn1_end_tag(data); if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
goto failed;
}
filter = talloc_asprintf_append(filter, ")"); while (asn1_tag_remaining(data) > 0) {
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;
}
break; break;
}
case 3: { case 3: {
/* equalityMatch */ /* equalityMatch */
const char *attrib; const char *attrib;
DATA_BLOB value; DATA_BLOB value;
struct ldb_val val;
if (tag_desc != 0xa0) /* context compound */ ret->operation = LDB_OP_SIMPLE;
return False;
if (tag_desc != 0xa0) {
/* context compound */
goto failed;
}
asn1_start_tag(data, ASN1_CONTEXT(3)); asn1_start_tag(data, ASN1_CONTEXT(3));
asn1_read_OctetString_talloc(mem_ctx, data, &attrib); asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
asn1_read_OctetString(data, &value); asn1_read_OctetString(data, &value);
asn1_end_tag(data); asn1_end_tag(data);
if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
return False; goto failed;
val.data = value.data; }
val.length = value.length; ret->u.simple.attr = talloc_steal(ret, attrib);
filter = talloc_asprintf(mem_ctx, "(%s=%s)", ret->u.simple.value.data = talloc_steal(ret, value.data);
attrib, ldb_binary_encode(mem_ctx, val)); ret->u.simple.value.length = value.length;
data_blob_free(&value);
break; break;
} }
case 7: { case 7: {
/* Normal presence, "attribute=*" */ /* Normal presence, "attribute=*" */
int attr_len; int attr_len;
char *attr_name; if (tag_desc != 0x80) {
if (tag_desc != 0x80) /* context simple */ /* context simple */
return False; goto failed;
if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7))) }
return False; if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
goto failed;
}
ret->operation = LDB_OP_SIMPLE;
attr_len = asn1_tag_remaining(data); attr_len = asn1_tag_remaining(data);
attr_name = malloc(attr_len+1);
if (attr_name == NULL) ret->u.simple.attr = talloc_size(ret, attr_len+1);
return False; if (ret->u.simple.attr == NULL) {
asn1_read(data, attr_name, attr_len); goto failed;
attr_name[attr_len] = '\0'; }
filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name); if (!asn1_read(data, ret->u.simple.attr, attr_len)) {
SAFE_FREE(attr_name); goto failed;
asn1_end_tag(data); }
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; break;
} }
default: default:
DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
goto failed;
}
return ret;
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; return False;
} }
if (filter == NULL) *filterp = ldb_filter_from_tree(mem_ctx, tree);
talloc_free(tree);
if (*filterp == NULL) {
return False; return False;
}
*filterp = filter;
return True; return True;
} }
static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data, static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
struct ldap_attribute *attrib) struct ldap_attribute *attrib)
{ {