b838ff
From c30bbedaa57951b2cb357d581b8f1e27165fdfce Mon Sep 17 00:00:00 2001
b838ff
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Date: Fri, 5 Mar 2021 15:47:56 +1300
b838ff
Subject: [PATCH 1/4] ldb: add tests for ldb_wildcard_compare
b838ff
MIME-Version: 1.0
b838ff
Content-Type: text/plain; charset=UTF-8
b838ff
Content-Transfer-Encoding: 8bit
b838ff
b838ff
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14044
b838ff
b838ff
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Reviewed-by: Björn Jacke <bjacke@samba.org>
b838ff
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
b838ff
b838ff
(cherry-picked from commit 33a95a1e75b85e9795c4490b78ead2162e2a1f47)
b838ff
---
b838ff
 lib/ldb/tests/ldb_match_test.c | 134 ++++++++++++++++++++++++++++++---
b838ff
 1 file changed, 124 insertions(+), 10 deletions(-)
b838ff
b838ff
diff --git a/lib/ldb/tests/ldb_match_test.c b/lib/ldb/tests/ldb_match_test.c
b838ff
index e09f50c86ba..3028aed072c 100644
b838ff
--- a/lib/ldb/tests/ldb_match_test.c
b838ff
+++ b/lib/ldb/tests/ldb_match_test.c
b838ff
@@ -91,6 +91,33 @@ static int teardown(void **state)
b838ff
 	return 0;
b838ff
 }
b838ff
 
b838ff
+static void escape_string(uint8_t *buf, size_t buflen,
b838ff
+			  const uint8_t *s, size_t len)
b838ff
+{
b838ff
+	size_t i;
b838ff
+	size_t j = 0;
b838ff
+	for (i = 0; i < len; i++) {
b838ff
+		if (j == buflen - 1) {
b838ff
+			goto fin;
b838ff
+		}
b838ff
+		if (s[i] >= 0x20) {
b838ff
+			buf[j] = s[i];
b838ff
+			j++;
b838ff
+		} else {
b838ff
+			if (j >= buflen - 4) {
b838ff
+				goto fin;
b838ff
+			}
b838ff
+			/* utf-8 control char representation */
b838ff
+			buf[j] = 0xE2;
b838ff
+			buf[j + 1] = 0x90;
b838ff
+			buf[j + 2] = 0x80 + s[i];
b838ff
+			j+= 3;
b838ff
+		}
b838ff
+	}
b838ff
+fin:
b838ff
+	buf[j] = 0;
b838ff
+}
b838ff
+
b838ff
 
b838ff
 /*
b838ff
  * The wild card pattern "attribute=*" is parsed as an LDB_OP_PRESENT operation
b838ff
@@ -122,23 +149,110 @@ static void test_wildcard_match_star(void **state)
b838ff
  * Test basic wild card matching
b838ff
  *
b838ff
  */
b838ff
+struct wildcard_test {
b838ff
+	uint8_t *val;
b838ff
+	size_t val_size;
b838ff
+	const char *search;
b838ff
+	bool should_match;
b838ff
+	bool fold;
b838ff
+};
b838ff
+
b838ff
+/*
b838ff
+ * Q: Why this macro rather than plain struct values?
b838ff
+ * A: So we can get the size of the const char[] value while it is still a
b838ff
+ * true array, not a pointer.
b838ff
+ *
b838ff
+ * Q: but why not just use strlen?
b838ff
+ * A: so values can contain '\0', which we supposedly allow.
b838ff
+ */
b838ff
+
b838ff
+#define TEST_ENTRY(val, search, should_match, fold)	\
b838ff
+	{						\
b838ff
+		(uint8_t*)discard_const(val),		\
b838ff
+		sizeof(val) - 1,			\
b838ff
+		search,					\
b838ff
+		should_match,				\
b838ff
+		fold					\
b838ff
+	 }
b838ff
+
b838ff
 static void test_wildcard_match(void **state)
b838ff
 {
b838ff
 	struct ldbtest_ctx *ctx = *state;
b838ff
-	bool matched = false;
b838ff
-
b838ff
-	uint8_t value[] = "The value.......end";
b838ff
-	struct ldb_val val = {
b838ff
-		.data   = value,
b838ff
-		.length = (sizeof(value))
b838ff
+	size_t failed = 0;
b838ff
+	size_t i;
b838ff
+	struct wildcard_test tests[] = {
b838ff
+		TEST_ENTRY("The value.......end", "*end", true, true),
b838ff
+		TEST_ENTRY("The value.......end", "*fend", false, true),
b838ff
+		TEST_ENTRY("The value.......end", "*eel", false, true),
b838ff
+		TEST_ENTRY("The value.......end", "*d", true, true),
b838ff
+		TEST_ENTRY("The value.......end", "*D*", true, true),
b838ff
+		TEST_ENTRY("The value.......end", "*e*d*", true, true),
b838ff
+		TEST_ENTRY("end", "*e*d*", true, true),
b838ff
+		TEST_ENTRY("end", "  *e*d*", true, true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0aaaaaaaaaaaa", "*aaaaa", true, true),
b838ff
+		TEST_ENTRY("1.0..0.0.0.0.0.0.0aAaaaAAAAAAA", "*a", true,  true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0aaaa", "*aaaaa", false, true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0", true, true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0.0", true, true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", true,
b838ff
+			   true),
b838ff
+		TEST_ENTRY("1.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", false,
b838ff
+			   true),
b838ff
+		TEST_ENTRY("1.0.0.0.000.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", true,
b838ff
+			   true),
b838ff
+		TEST_ENTRY("1\n0\r0\t000.0.0.0.0", "1*0*0*0*0*0*0*0*0", true,
b838ff
+			   true),
b838ff
+		/*
b838ff
+		 *  We allow NUL bytes in non-casefolding syntaxes.
b838ff
+		 */
b838ff
+		TEST_ENTRY("1\x00 x", "1*x", true, false),
b838ff
+		TEST_ENTRY("1\x00 x", "*x", true, false),
b838ff
+		TEST_ENTRY("1\x00 x", "*x*", true, false),
b838ff
+		TEST_ENTRY("1\x00 x", "* *", true, false),
b838ff
+		TEST_ENTRY("1\x00 x", "1*", true, false),
b838ff
+		TEST_ENTRY("1\x00 b* x", "1*b*", true, false),
b838ff
+		TEST_ENTRY("1.0..0.0.0.0.0.0.0aAaaaAAAAAAA", "*a", false,  false),
b838ff
 	};
b838ff
-	struct ldb_parse_tree *tree = ldb_parse_tree(ctx, "objectClass=*end");
b838ff
-	assert_non_null(tree);
b838ff
 
b838ff
-	ldb_wildcard_compare(ctx->ldb, tree, val, &matched);
b838ff
-	assert_true(matched);
b838ff
+	for (i = 0; i < ARRAY_SIZE(tests); i++) {
b838ff
+		bool matched;
b838ff
+		int ret;
b838ff
+		struct ldb_val val = {
b838ff
+			.data   = (uint8_t *)tests[i].val,
b838ff
+			.length = tests[i].val_size
b838ff
+		};
b838ff
+		const char *attr = tests[i].fold ? "objectclass" : "birthLocation";
b838ff
+		const char *s = talloc_asprintf(ctx, "%s=%s",
b838ff
+						attr, tests[i].search);
b838ff
+		struct ldb_parse_tree *tree = ldb_parse_tree(ctx, s);
b838ff
+		assert_non_null(tree);
b838ff
+		ret = ldb_wildcard_compare(ctx->ldb, tree, val, &matched);
b838ff
+		if (ret != LDB_SUCCESS) {
b838ff
+			uint8_t buf[100];
b838ff
+			escape_string(buf, sizeof(buf),
b838ff
+				      tests[i].val, tests[i].val_size);
b838ff
+			print_error("%zu val: «%s», search «%s» FAILED with %d\n",
b838ff
+				    i, buf, tests[i].search, ret);
b838ff
+			failed++;
b838ff
+		}
b838ff
+		if (matched != tests[i].should_match) {
b838ff
+			uint8_t buf[100];
b838ff
+			escape_string(buf, sizeof(buf),
b838ff
+				      tests[i].val, tests[i].val_size);
b838ff
+			print_error("%zu val: «%s», search «%s» should %s\n",
b838ff
+				    i, buf, tests[i].search,
b838ff
+				    matched ? "not match" : "match");
b838ff
+			failed++;
b838ff
+		}
b838ff
+	}
b838ff
+	if (failed != 0) {
b838ff
+		fail_msg("wrong results for %zu/%zu wildcard searches\n",
b838ff
+			 failed, ARRAY_SIZE(tests));
b838ff
+	}
b838ff
 }
b838ff
 
b838ff
+#undef TEST_ENTRY
b838ff
+
b838ff
 
b838ff
 /*
b838ff
  * ldb_handler_copy and ldb_val_dup over allocate by one and add a trailing '\0'
b838ff
-- 
b838ff
2.25.1
b838ff
b838ff
b838ff
From f2f01f83b8e881846dc9d2edd8b5412bf6885887 Mon Sep 17 00:00:00 2001
b838ff
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Date: Fri, 5 Mar 2021 20:13:01 +1300
b838ff
Subject: [PATCH 2/4] CVE-2021-20277 ldb tests: ldb_match tests with extra
b838ff
 spaces
b838ff
b838ff
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14655
b838ff
b838ff
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
b838ff
(cherry-picked from commit for master)
b838ff
---
b838ff
 lib/ldb/tests/ldb_match_test.c | 8 +++++++-
b838ff
 1 file changed, 7 insertions(+), 1 deletion(-)
b838ff
b838ff
diff --git a/lib/ldb/tests/ldb_match_test.c b/lib/ldb/tests/ldb_match_test.c
b838ff
index 3028aed072c..ba6ea56be15 100644
b838ff
--- a/lib/ldb/tests/ldb_match_test.c
b838ff
+++ b/lib/ldb/tests/ldb_match_test.c
b838ff
@@ -181,6 +181,8 @@ static void test_wildcard_match(void **state)
b838ff
 	size_t failed = 0;
b838ff
 	size_t i;
b838ff
 	struct wildcard_test tests[] = {
b838ff
+		TEST_ENTRY("                     1  0", "1*0*", true, true),
b838ff
+		TEST_ENTRY("                     1  0", "1 *0", true, true),
b838ff
 		TEST_ENTRY("The value.......end", "*end", true, true),
b838ff
 		TEST_ENTRY("The value.......end", "*fend", false, true),
b838ff
 		TEST_ENTRY("The value.......end", "*eel", false, true),
b838ff
@@ -203,8 +205,12 @@ static void test_wildcard_match(void **state)
b838ff
 		TEST_ENTRY("1\n0\r0\t000.0.0.0.0", "1*0*0*0*0*0*0*0*0", true,
b838ff
 			   true),
b838ff
 		/*
b838ff
-		 *  We allow NUL bytes in non-casefolding syntaxes.
b838ff
+		 *  We allow NUL bytes and redundant spaces in non-casefolding
b838ff
+		 *  syntaxes.
b838ff
 		 */
b838ff
+		TEST_ENTRY("                  1  0", "*1  0", true, false),
b838ff
+		TEST_ENTRY("                  1  0", "*1  0", true, false),
b838ff
+		TEST_ENTRY("1    0", "*1 0", false, false),
b838ff
 		TEST_ENTRY("1\x00 x", "1*x", true, false),
b838ff
 		TEST_ENTRY("1\x00 x", "*x", true, false),
b838ff
 		TEST_ENTRY("1\x00 x", "*x*", true, false),
b838ff
-- 
b838ff
2.25.1
b838ff
b838ff
b838ff
From 11ed7d579fee9de8c51188c4718a2bd398dc7126 Mon Sep 17 00:00:00 2001
b838ff
From: Andrew Bartlett <abartlet@samba.org>
b838ff
Date: Fri, 12 Mar 2021 11:51:56 +1300
b838ff
Subject: [PATCH 3/4] CVE-2021-20277 ldb: Remove tests from ldb_match_test that
b838ff
 do not pass
b838ff
b838ff
This reverts some of the backport of 33a95a1e75b85e9795c4490b78ead2162e2a1f47
b838ff
b838ff
This is done here rather than squashed in the cherry-pick of the expanded testsuite
b838ff
because it allows this commit to be simply reverted for the backport of bug 14044
b838ff
if this lands first, or to be dropped if bug 14044 lands first.
b838ff
b838ff
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14655
b838ff
b838ff
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
b838ff
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
---
b838ff
 lib/ldb/tests/ldb_match_test.c | 2 --
b838ff
 1 file changed, 2 deletions(-)
b838ff
b838ff
diff --git a/lib/ldb/tests/ldb_match_test.c b/lib/ldb/tests/ldb_match_test.c
b838ff
index ba6ea56be15..fbf4106fa78 100644
b838ff
--- a/lib/ldb/tests/ldb_match_test.c
b838ff
+++ b/lib/ldb/tests/ldb_match_test.c
b838ff
@@ -191,11 +191,9 @@ static void test_wildcard_match(void **state)
b838ff
 		TEST_ENTRY("The value.......end", "*e*d*", true, true),
b838ff
 		TEST_ENTRY("end", "*e*d*", true, true),
b838ff
 		TEST_ENTRY("end", "  *e*d*", true, true),
b838ff
-		TEST_ENTRY("1.0.0.0.0.0.0.0aaaaaaaaaaaa", "*aaaaa", true, true),
b838ff
 		TEST_ENTRY("1.0..0.0.0.0.0.0.0aAaaaAAAAAAA", "*a", true,  true),
b838ff
 		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0aaaa", "*aaaaa", false, true),
b838ff
 		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0", true, true),
b838ff
-		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0.0", true, true),
b838ff
 		TEST_ENTRY("1.0.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", true,
b838ff
 			   true),
b838ff
 		TEST_ENTRY("1.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", false,
b838ff
-- 
b838ff
2.25.1
b838ff
b838ff
b838ff
From 18f9cfabdc560ed58d728ead290ce123737e4716 Mon Sep 17 00:00:00 2001
b838ff
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Date: Tue, 8 Dec 2020 21:32:09 +1300
b838ff
Subject: [PATCH 4/4] CVE-2021-20277 ldb/attrib_handlers casefold: stay in
b838ff
 bounds
b838ff
b838ff
For a string that had N spaces at the beginning, we would
b838ff
try to move N bytes beyond the end of the string.
b838ff
b838ff
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14655
b838ff
b838ff
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
b838ff
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
b838ff
b838ff
(cherry-picked from commit for master)
b838ff
---
b838ff
 lib/ldb/common/attrib_handlers.c | 2 +-
b838ff
 1 file changed, 1 insertion(+), 1 deletion(-)
b838ff
b838ff
diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c
b838ff
index b5212b73159..c6ef5ad477b 100644
b838ff
--- a/lib/ldb/common/attrib_handlers.c
b838ff
+++ b/lib/ldb/common/attrib_handlers.c
b838ff
@@ -76,7 +76,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
b838ff
 	
b838ff
 	/* remove leading spaces if any */
b838ff
 	if (*s == ' ') {
b838ff
-		for (t = s; *s == ' '; s++) ;
b838ff
+		for (t = s; *s == ' '; s++, l--) ;
b838ff
 
b838ff
 		/* remove leading spaces by moving down the string */
b838ff
 		memmove(t, s, l);
b838ff
-- 
b838ff
2.25.1
b838ff