mirror of
https://github.com/samba-team/samba.git
synced 2025-11-27 08:23:49 +03:00
r7558: added support in ldb for extended ldap search requests. These are
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
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
71e281ae2f
commit
5f773b065f
@@ -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>
|
||||
*/
|
||||
@@ -234,6 +289,11 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s)
|
||||
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;
|
||||
ret->u.simple.value = ldb_binary_decode(ret, val);
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[]);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,19 +276,103 @@ 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) {
|
||||
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 (j=0;j<msg->elements[i].num_values;j++) {
|
||||
if (ltdb_val_equal(module, msg->elements[i].name,
|
||||
&msg->elements[i].values[j],
|
||||
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user