From 61f080fd3c017bc99ae38fb4580b6adf673e2973 Mon Sep 17 00:00:00 2001 Message-Id: <61f080fd3c017bc99ae38fb4580b6adf673e2973.1338362352.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 30 May 2012 08:56:32 +0200 Subject: [PATCH 1/2] Ticket #2012050221003422: Add unit test Organization: Univention GmbH, Bremen, Germany Add unit test for broken filter.c:cache_entry_ldap_filter_match() --- .../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 diff --git a/branches/ucs-3.0/ucs/management/univention-directory-listener/debian/rules b/branches/ucs-3.0/ucs/management/univention-directory-listener/debian/rules index c27f5bc..4934058 100755 --- a/branches/ucs-3.0/ucs/management/univention-directory-listener/debian/rules +++ b/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 diff --git a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/Makefile b/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/Makefile new file mode 100644 index 0000000..7c2d04b --- /dev/null +++ b/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 diff --git a/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/test__filter__cache_entry_ldap_filter_match.c b/branches/ucs-3.0/ucs/management/univention-directory-listener/tests/test__filter__cache_entry_ldap_filter_match.c new file mode 100644 index 0000000..226d931 --- /dev/null +++ b/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; +} -- 1.7.1 From 73dcb83d14c4326b76ce39f4852116537292fb29 Mon Sep 17 00:00:00 2001 Message-Id: <73dcb83d14c4326b76ce39f4852116537292fb29.1338362352.git.hahn@univention.de> In-Reply-To: <61f080fd3c017bc99ae38fb4580b6adf673e2973.1338362352.git.hahn@univention.de> References: <61f080fd3c017bc99ae38fb4580b6adf673e2973.1338362352.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 30 May 2012 09:08:16 +0200 Subject: [PATCH 2/2] Ticket #2012050221003422: Fix cache_entry_ldap_filter_match() Organization: Univention GmbH, Bremen, Germany Detecting if the base matches is currently broken: *p is a pointer in dn, which is compared to a pointer in (*f)->base in the while-loop, which will never match! 1. Check that the required DN in longer than the testes DN. 2. Check that the testes DN ends on the required DN. 3. Check SCOPE using switch-case-statement. 4. Add some documentation. --- .../univention-directory-listener/src/filter.c | 36 +++++++++++--------- 1 files changed, 20 insertions(+), 16 deletions(-) diff --git a/branches/ucs-3.0/ucs/management/univention-directory-listener/src/filter.c b/branches/ucs-3.0/ucs/management/univention-directory-listener/src/filter.c index ed4cff0..fc27eab 100644 --- a/branches/ucs-3.0/ucs/management/univention-directory-listener/src/filter.c +++ b/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; } -- 1.7.1