summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_tdb/ldb_match.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-07-01 06:21:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:19:01 -0500
commita06d66a3a669c3a0a0f816438e2b3e91e208f398 (patch)
tree0a80e63dad3f00cd584263e56df6f751b46de58e /source4/lib/ldb/ldb_tdb/ldb_match.c
parent8ab3f59a10d00357cb129a2051fd0f694b5c8081 (diff)
downloadsamba-a06d66a3a669c3a0a0f816438e2b3e91e208f398.tar.gz
samba-a06d66a3a669c3a0a0f816438e2b3e91e208f398.tar.bz2
samba-a06d66a3a669c3a0a0f816438e2b3e91e208f398.zip
r8037: a fairly major update to the internals of ldb. Changes are:
- moved the knowledge of attribute types out of ldb_tdb and into the generic ldb code. This allows the ldb_match() message match logic to be generic, so it can be used by other backend - added the generic ability to load attribute handlers, for canonicalisation, compare, ldif read and ldif write. In the future this will be used by the schema module to allow us to correctly obey the attributetype schema elements - added attribute handlers for some of the core ldap attribute types, Integer, DirectoryString, DN, ObjectClass etc - added automatic registration of attribute handlers for well-known attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass' - converted the objectSid special handlers for Samba to the new system - added more correct handling of indexing in tdb backend based on the attribute canonicalisation function - added generic support for subclasses, moving it out of the tdb backend. This will be used in future by the schema module - fixed several bugs in the dn_explode code. It still needs more work, but doesn't corrupt ldb dbs any more. (This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9)
Diffstat (limited to 'source4/lib/ldb/ldb_tdb/ldb_match.c')
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_match.c426
1 files changed, 0 insertions, 426 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c
deleted file mode 100644
index b5b023bc09..0000000000
--- a/source4/lib/ldb/ldb_tdb/ldb_match.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb expression matching
- *
- * Description: ldb expression matching for tdb backend
- *
- * Author: Andrew Tridgell
- */
-
-#include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_private.h"
-#include "ldb/ldb_tdb/ldb_tdb.h"
-#include <fnmatch.h>
-
-/*
- see if two ldb_val structures contain the same data as integers
- return 1 for a match, 0 for a mis-match
-*/
-static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2)
-{
- uint64_t i1, i2;
-
- i1 = strtoull(v1->data, NULL, 0);
- i2 = strtoull(v2->data, NULL, 0);
-
- return i1 == i2;
-}
-
-/*
- see if two ldb_val structures contain the same data as case insensitive strings
- return 1 for a match, 0 for a mis-match
-*/
-static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1,
- const struct ldb_val *v2)
-{
- if (v1->length != v2->length) {
- return 0;
- }
- if (strncasecmp(v1->data, v2->data, v1->length) == 0) {
- return 1;
- }
- return 0;
-}
-
-/*
- see if two ldb_val structures contain the same data with wildcards
- and case insensitive
- return 1 for a match, 0 for a mis-match
-*/
-static int ltdb_val_equal_wildcard_ci(struct ldb_module *module,
- const struct ldb_val *v1,
- const struct ldb_val *v2)
-{
- struct ldb_context *ldb = module->ldb;
- char *s1, *s2;
- int ret;
-
- if (!v1->data || !v2->data) {
- return v1->data == v2->data;
- }
-
- s1 = ldb_casefold(ldb, v1->data);
- if (!s1) {
- return -1;
- }
-
- s2 = ldb_casefold(ldb, v2->data);
- if (!s2) {
- talloc_free(s1);
- return -1;
- }
-
- ret = fnmatch(s2, s1, 0);
-
- talloc_free(s1);
- talloc_free(s2);
-
- if (ret == 0) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- see if two ldb_val structures contain the same data with wildcards
- return 1 for a match, 0 for a mis-match
-*/
-static int ltdb_val_equal_wildcard(struct ldb_module *module,
- const struct ldb_val *v1,
- const struct ldb_val *v2,
- int flags)
-{
- if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
- return ltdb_val_equal_wildcard_ci(module, v1, v2);
- }
- if (!v1->data || !v2->data) {
- return v1->data == v2->data;
- }
- if (fnmatch(v2->data, v1->data, 0) == 0) {
- return 1;
- }
- return 0;
-}
-
-
-/*
- see if two objectclasses are considered equal. This handles
- the subclass attributes
-
- v1 contains the in-database value, v2 contains the value
- that the user gave
-
- return 1 for a match, 0 for a mis-match
-*/
-static int ltdb_val_equal_objectclass(struct ldb_module *module,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- struct ltdb_private *ltdb = module->private_data;
- unsigned int i;
-
- if (ltdb_val_equal_case_insensitive(v1, v2) == 1) {
- return 1;
- }
-
- for (i=0;i<ltdb->cache->subclasses->num_elements;i++) {
- struct ldb_message_element *el = &ltdb->cache->subclasses->elements[i];
- if (ldb_attr_cmp(el->name, v2->data) == 0) {
- unsigned int j;
- for (j=0;j<el->num_values;j++) {
- if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) {
- return 1;
- }
- }
- }
- }
-
- return 0;
-}
-
-
-/*
- see if two ldb_val structures contain the same data
-
- v1 contains the in-database value, v2 contains the value
- that the user gave
-
- return 1 for a match, 0 for a mis-match
-*/
-int ltdb_val_equal(struct ldb_module *module,
- const char *attr_name,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- int flags = ltdb_attribute_flags(module, attr_name);
-
- if (flags & LTDB_FLAG_OBJECTCLASS) {
- return ltdb_val_equal_objectclass(module, v1, v2);
- }
-
- if (flags & LTDB_FLAG_INTEGER) {
- return ltdb_val_equal_integer(v1, v2);
- }
-
- if (flags & LTDB_FLAG_WILDCARD) {
- return ltdb_val_equal_wildcard(module, v1, v2, flags);
- }
-
- if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
- return ltdb_val_equal_case_insensitive(v1, v2);
- }
-
- if (v1->length != v2->length) return 0;
-
- if (v1->length == 0) return 1;
-
- if (memcmp(v1->data, v2->data, v1->length) == 0) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- check if the scope matches in a search result
-*/
-static int scope_match(const char *dn, const char *base, enum ldb_scope scope)
-{
- size_t dn_len, base_len;
-
- if (base == NULL) {
- return 1;
- }
-
- base_len = strlen(base);
- dn_len = strlen(dn);
-
- if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) {
- return 1;
- }
-
- if (base_len+1 >= dn_len) {
- return 0;
- }
-
- switch (scope) {
- case LDB_SCOPE_BASE:
- break;
-
- case LDB_SCOPE_ONELEVEL:
- if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
- dn[dn_len - base_len - 1] == ',' &&
- strchr(dn, ',') == &dn[dn_len - base_len - 1]) {
- return 1;
- }
- break;
-
- case LDB_SCOPE_SUBTREE:
- default:
- if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
- dn[dn_len - base_len - 1] == ',') {
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-
-/*
- match a leaf node
-*/
-static int match_leaf(struct ldb_module *module,
- struct ldb_message *msg,
- struct ldb_parse_tree *tree,
- const char *base,
- enum ldb_scope scope)
-{
- unsigned int i;
- struct ldb_message_element *el;
-
- if (!scope_match(msg->dn, base, scope)) {
- return 0;
- }
-
- if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
- if (strcmp(tree->u.simple.value.data, "*") == 0) {
- return 1;
- }
- return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 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 (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)
-{
- uint64_t i1, i2;
- i1 = strtoull(v1->data, NULL, 0);
- i2 = strtoull(v2->data, NULL, 0);
- return ((i1 & i2) == i2);
-}
-
-/*
- bitwise-or comparator
-*/
-static int comparator_or(struct ldb_val *v1, struct ldb_val *v2)
-{
- uint64_t i1, i2;
- i1 = strtoull(v1->data, NULL, 0);
- i2 = strtoull(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[] = {
- { LDB_OID_COMPARATOR_AND, comparator_and},
- { LDB_OID_COMPARATOR_OR, 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;
-}
-
-/*
- return 0 if the given parse tree matches the given message. Assumes
- the message is in sorted order
-
- return 1 if it matches, and 0 if it doesn't match
-
- this is a recursive function, and does short-circuit evaluation
- */
-int ltdb_message_match(struct ldb_module *module,
- struct ldb_message *msg,
- struct ldb_parse_tree *tree,
- const char *base,
- enum ldb_scope scope)
-{
- unsigned int i;
- int v;
-
- switch (tree->operation) {
- 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);
-
- case LDB_OP_AND:
- for (i=0;i<tree->u.list.num_elements;i++) {
- v = ltdb_message_match(module, msg, tree->u.list.elements[i],
- base, scope);
- if (!v) return 0;
- }
- return 1;
-
- case LDB_OP_OR:
- for (i=0;i<tree->u.list.num_elements;i++) {
- v = ltdb_message_match(module, msg, tree->u.list.elements[i],
- base, scope);
- if (v) return 1;
- }
- return 0;
- }
-
- return match_leaf(module, msg, tree, base, scope);
-}