@@ -, +, @@ --- .../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; } --