@@ -, +, @@
---
.../univention-directory-listener/debian/rules | 3 +-
.../univention-directory-listener/tests/Makefile | 39 +++++++++
.../test__filter__cache_entry_ldap_filter_match.c | 89 ++++++++++++++++++++
3 files changed, 130 insertions(+), 1 deletions(-)
create mode 100644 branches/ucs-3.0/ucs/management/univention-directory-listener/tests/Makefile
create mode 100644 branches/ucs-3.0/ucs/management/univention-directory-listener/tests/test__filter__cache_entry_ldap_filter_match.c
--- a/branches/ucs-3.0/ucs/management/univention-directory-listener/debian/rules
+++ a/branches/ucs-3.0/ucs/management/univention-directory-listener/debian/rules
@@ -32,6 +32,7 @@
override_dh_auto_clean:
$(MAKE) -C src clean
+ $(MAKE) -C tests clean
dh_auto_clean
override_dh_auto_build:
@@ -56,7 +57,7 @@ override_dh_installinit:
override_dh_auto_test:
ucslint
- dh_auto_test
+ make -C tests
override_dh_strip:
dh_strip --dbg-package=univention-directory-listener-dbg
--- a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/Makefile
+++ a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/Makefile
@@ -0,0 +1,39 @@
+#
+# Univention Directory Listener
+# Makefile for testing the listener
+#
+# Copyright 2004-2012 Univention GmbH
+#
+# http://www.univention.de/
+#
+# All rights reserved.
+#
+# The source code of this program is made available
+# under the terms of the GNU Affero General Public License version 3
+# (GNU AGPL V3) as published by the Free Software Foundation.
+#
+# Binary versions of this program provided by Univention to you as
+# well as other copyrighted, protected or trademarked materials like
+# Logos, graphics, fonts, specific documentations and configurations,
+# cryptographic keys etc. are subject to a license agreement between
+# you and Univention and not subject to the GNU AGPL V3.
+#
+# In the case you use this program under the terms of the GNU AGPL V3,
+# the program is provided 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License with the Debian GNU/Linux or Univention distribution in file
+# /usr/share/common-licenses/AGPL-3; if not, see
+# .
+#
+tests: test__filter__cache_entry_ldap_filter_match
+ set -e ; for t in $^; do ./$$t ; done
+
+test__filter__cache_entry_ldap_filter_match: test__filter__cache_entry_ldap_filter_match.o ../src/filter.o
+
+include ../src/Makefile
+
+CFLAGS := -g -Wall -Werror -D_FILE_OFFSET_BITS=64 $(DB_CFLAGS) -I../src
--- a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/test__filter__cache_entry_ldap_filter_match.c
+++ a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/test__filter__cache_entry_ldap_filter_match.c
@@ -0,0 +1,89 @@
+#include
+#include
+#include
+#include "filter.h"
+
+static struct filter filter = {
+ .base = "dc=bar,dc=baz",
+ .scope = 2, // LDAP.SCOPE_SUBTREE
+ .filter = "objectclass=*",
+};
+static struct filter *filters[2] = {
+ &filter,
+ NULL,
+};
+static CacheEntry entry = {
+ .attributes = NULL,
+ .attribute_count = 0,
+ .modules = NULL,
+ .module_count = 0,
+};
+
+static bool test_match_exact(void) {
+ char dn[] = "dc=bar,dc=baz";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 1;
+}
+
+static bool test_match_one(void) {
+ char dn[] = "dc=foo,dc=bar,dc=baz";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 1;
+}
+
+static bool test_match_other(void) {
+ char dn[] = "dc=foo";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 0;
+}
+
+static bool test_match_sub(void) {
+ char dn[] = "dc=bam,dc=foo,dc=bar,dc=baz";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 1;
+}
+
+static bool test_match_case(void) {
+ char dn[] = "dc=foo,dc=bar,dc=BAZ";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 0;
+}
+
+static bool test_match_short(void) {
+ char dn[] = "dc=baz";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 0;
+}
+
+static bool test_match_infix(void) {
+ char dn[] = "dc=foo,dc=bar,dc=baz,dc=bam";
+ int r = cache_entry_ldap_filter_match(filters, dn, &entry);
+ return r == 0;
+}
+
+#define TEST(n) { .name = "test_" # n, .func = test_##n }
+struct tests {
+ const char *name;
+ bool (*func)(void);
+} tests[] = {
+ TEST(match_exact),
+ TEST(match_one),
+ TEST(match_other),
+ TEST(match_sub),
+ TEST(match_case),
+ TEST(match_short),
+ TEST(match_infix),
+};
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
+int main(int argc, char *argv[]) {
+ int i, failed = 0;
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
+ if (tests[i].func()) {
+ fprintf(stdout, "+%s\n", tests[i].name);
+ } else {
+ fprintf(stdout, "-%s\n", tests[i].name);
+ failed++;
+ }
+ return failed;
+}
--
---
.../univention-directory-listener/src/filter.c | 36 +++++++++++---------
1 files changed, 20 insertions(+), 16 deletions(-)
--- a/branches/ucs-3.0/ucs/management/univention-directory-listener/src/filter.c
+++ a/branches/ucs-3.0/ucs/management/univention-directory-listener/src/filter.c
@@ -169,30 +169,34 @@ static int __cache_entry_ldap_filter_match(char* filter, int first, int last, Ca
int cache_entry_ldap_filter_match(struct filter **filter, char *dn, CacheEntry *entry)
{
struct filter **f;
+ size_t dn_len = strlen(dn);
for (f = filter; f != NULL && *f != NULL; f++) {
- int len = strlen((*f)->filter);
-
/* check if base and scope match */
if ((*f)->base != NULL && (*f)->base[0] != '\0') {
- char *p = strstr(dn, (*f)->base);
-
- /* strstr only finds the first occurance of the needle in the
- * haystack; hence, we keep on looping thru the results while
- * the result isn't at the end of the haystack */
- while (p != NULL && p+strlen(p) != (*f)->base+strlen((*f)->base)) {
- p = strstr(p+1, (*f)->base);
- }
- if (p == NULL) /* base doesn't match at all*/
+ size_t b_len = strlen((*f)->base);
+ /* No match if required base is longer then tested dn */
+ if (b_len > dn_len)
continue;
-
- if ( /* scope doesn't match */
- ((*f)->scope == LDAP_SCOPE_BASE && strchr(dn, ',') <= p) ||
- ((*f)->scope == LDAP_SCOPE_ONELEVEL && strchr(dn, ',')+1 != p))
+ /* No match if testes dn does not end on required base */
+ if (strcmp(dn + dn_len - b_len, (*f)->base))
continue;
+
+ switch ((*f)->scope) {
+ case LDAP_SCOPE_BASE:
+ /* skip if more levels exists. */
+ if (strchr(dn, '.') <= dn + dn_len - b_len)
+ continue;
+ break;
+ case LDAP_SCOPE_ONELEVEL:
+ /* skip if more then one level */
+ if (strchr(dn, '.') + 1 != dn + dn_len - b_len)
+ continue;
+ break;
+ }
}
-
+ int len = strlen((*f)->filter);
if (__cache_entry_ldap_filter_match((*f)->filter, 0, len-1, entry))
return 1;
}
--