!37 fix CVE-2023-0614
From: @xinghe_1 Reviewed-by: @t_feng Signed-off-by: @t_feng
This commit is contained in:
commit
9e3d15492d
174
backport-0001-CVE-2023-0614.patch
Normal file
174
backport-0001-CVE-2023-0614.patch
Normal file
@ -0,0 +1,174 @@
|
||||
From 197d1f09158ee0575cd92c461ed12bdbf4efc074 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Mon, 13 Mar 2023 14:25:56 +1300
|
||||
Subject: [PATCH 01/35] CVE-2023-0614 lib/ldb: Avoid allocation and memcpy()
|
||||
for every wildcard match candidate
|
||||
|
||||
The value can be quite large, the allocation will take much
|
||||
longer than the actual match and is repeated per candidate
|
||||
record.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15331
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
(cherry picked from commit cad96f59a08192df927fb1df4e9787c7f70991a2)
|
||||
|
||||
[abartlet@samba.org Included in the security release as this
|
||||
makes the new large_ldap.py timeout test more reliable]
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_match.c | 60 +++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 50 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/common/ldb_match.c b/common/ldb_match.c
|
||||
index 2f4d41f3441..51376871b4c 100644
|
||||
--- a/common/ldb_match.c
|
||||
+++ b/common/ldb_match.c
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "ldb_private.h"
|
||||
#include "dlinklist.h"
|
||||
+#include "ldb_handlers.h"
|
||||
|
||||
/*
|
||||
check if the scope matches in a search result
|
||||
@@ -259,20 +260,42 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
|
||||
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
+ /* No need to just copy this value for a binary match */
|
||||
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
|
||||
+ if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
|
||||
+ return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Only set save_p if we allocate (call
|
||||
+ * a->syntax->canonicalise_fn()), as we
|
||||
+ * talloc_free(save_p) below to clean up
|
||||
+ */
|
||||
+ save_p = val.data;
|
||||
+ } else {
|
||||
+ val = value;
|
||||
}
|
||||
|
||||
- save_p = val.data;
|
||||
cnk.data = NULL;
|
||||
|
||||
if ( ! tree->u.substring.start_with_wildcard ) {
|
||||
+ uint8_t *cnk_to_free = NULL;
|
||||
|
||||
chunk = tree->u.substring.chunks[c];
|
||||
- if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
|
||||
+ /* No need to just copy this value for a binary match */
|
||||
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
|
||||
+ if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
|
||||
+ goto mismatch;
|
||||
+ }
|
||||
+
|
||||
+ cnk_to_free = cnk.data;
|
||||
+ } else {
|
||||
+ cnk = *chunk;
|
||||
+ }
|
||||
|
||||
/* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
|
||||
if (cnk.length > val.length) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
goto mismatch;
|
||||
}
|
||||
/*
|
||||
@@ -280,32 +303,47 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
|
||||
* we can cope with this.
|
||||
*/
|
||||
if (cnk.length == 0) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
+ goto mismatch;
|
||||
+ }
|
||||
+
|
||||
+ if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
goto mismatch;
|
||||
}
|
||||
|
||||
- if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch;
|
||||
val.length -= cnk.length;
|
||||
val.data += cnk.length;
|
||||
c++;
|
||||
- talloc_free(cnk.data);
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
cnk.data = NULL;
|
||||
}
|
||||
|
||||
while (tree->u.substring.chunks[c]) {
|
||||
uint8_t *p;
|
||||
+ uint8_t *cnk_to_free = NULL;
|
||||
|
||||
chunk = tree->u.substring.chunks[c];
|
||||
- if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
|
||||
- goto mismatch;
|
||||
+ /* No need to just copy this value for a binary match */
|
||||
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
|
||||
+ if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
|
||||
+ goto mismatch;
|
||||
+ }
|
||||
+
|
||||
+ cnk_to_free = cnk.data;
|
||||
+ } else {
|
||||
+ cnk = *chunk;
|
||||
}
|
||||
/*
|
||||
* Empty strings are returned as length 0. Ensure
|
||||
* we can cope with this.
|
||||
*/
|
||||
if (cnk.length == 0) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
goto mismatch;
|
||||
}
|
||||
if (cnk.length > val.length) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
goto mismatch;
|
||||
}
|
||||
|
||||
@@ -320,6 +358,8 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
|
||||
cmp = memcmp(p,
|
||||
cnk.data,
|
||||
cnk.length);
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
+
|
||||
if (cmp != 0) {
|
||||
goto mismatch;
|
||||
}
|
||||
@@ -331,15 +371,16 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
|
||||
p = memmem((const void *)val.data, val.length,
|
||||
(const void *)cnk.data, cnk.length);
|
||||
if (p == NULL) {
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
goto mismatch;
|
||||
}
|
||||
/* move val to the end of the match */
|
||||
p += cnk.length;
|
||||
val.length -= (p - val.data);
|
||||
val.data = p;
|
||||
+ TALLOC_FREE(cnk_to_free);
|
||||
}
|
||||
c++;
|
||||
- TALLOC_FREE(cnk.data);
|
||||
}
|
||||
|
||||
talloc_free(save_p);
|
||||
@@ -349,7 +390,6 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
|
||||
mismatch:
|
||||
*matched = false;
|
||||
talloc_free(save_p);
|
||||
- talloc_free(cnk.data);
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
--
|
||||
2.25.1
|
||||
72
backport-0002-CVE-2023-0614.patch
Normal file
72
backport-0002-CVE-2023-0614.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From b01d3ae3261264236504475a26c54ab45dd2175f Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 27 Jan 2023 08:28:36 +1300
|
||||
Subject: [PATCH 05/34] CVE-2023-0614 ldb: Add functions for handling
|
||||
inaccessible message elements
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_msg.c | 26 ++++++++++++++++++++++++++
|
||||
include/ldb_module.h | 4 ++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/common/ldb_msg.c b/common/ldb_msg.c
|
||||
index 9cd7998e21c..cbc7e32b2ba 100644
|
||||
--- a/common/ldb_msg.c
|
||||
+++ b/common/ldb_msg.c
|
||||
@@ -795,6 +795,32 @@ int ldb_msg_element_compare_name(struct ldb_message_element *el1,
|
||||
return ldb_attr_cmp(el1->name, el2->name);
|
||||
}
|
||||
|
||||
+void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
|
||||
+{
|
||||
+ el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
|
||||
+}
|
||||
+
|
||||
+bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
|
||||
+{
|
||||
+ return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
|
||||
+}
|
||||
+
|
||||
+void ldb_msg_remove_inaccessible(struct ldb_message *msg)
|
||||
+{
|
||||
+ unsigned i;
|
||||
+ unsigned num_del = 0;
|
||||
+
|
||||
+ for (i = 0; i < msg->num_elements; ++i) {
|
||||
+ if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
|
||||
+ ++num_del;
|
||||
+ } else if (num_del) {
|
||||
+ msg->elements[i - num_del] = msg->elements[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ msg->num_elements -= num_del;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
convenience functions to return common types from a message
|
||||
these return the first value if the attribute is multi-valued
|
||||
diff --git a/include/ldb_module.h b/include/ldb_module.h
|
||||
index 4c7c85a17f0..8481fd3991a 100644
|
||||
--- a/include/ldb_module.h
|
||||
+++ b/include/ldb_module.h
|
||||
@@ -513,6 +513,10 @@ struct ldb_extended_match_rule
|
||||
int ldb_register_extended_match_rule(struct ldb_context *ldb,
|
||||
const struct ldb_extended_match_rule *rule);
|
||||
|
||||
+void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el);
|
||||
+bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el);
|
||||
+void ldb_msg_remove_inaccessible(struct ldb_message *msg);
|
||||
+
|
||||
/*
|
||||
* these pack/unpack functions are exposed in the library for use by
|
||||
* ldb tools like ldbdump and for use in tests,
|
||||
--
|
||||
2.25.1
|
||||
409
backport-0003-CVE-2023-0614.patch
Normal file
409
backport-0003-CVE-2023-0614.patch
Normal file
@ -0,0 +1,409 @@
|
||||
From e7445d18badee6c3b1bbee48c689eb2629c31681 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Wed, 15 Feb 2023 12:34:51 +1300
|
||||
Subject: [PATCH 07/34] CVE-2023-0614 ldb:tests: Ensure ldb_val data is
|
||||
zero-terminated
|
||||
|
||||
If the value of an ldb message element is not zero-terminated, calling
|
||||
ldb_msg_find_attr_as_string() will cause the function to read off the
|
||||
end of the buffer in an attempt to verify that the value is
|
||||
zero-terminated. This can cause unexpected behaviour and make the test
|
||||
randomly fail.
|
||||
|
||||
To avoid this, we must have a terminating null byte that is *not*
|
||||
counted as part of the length, and so we must calculate the length with
|
||||
strlen() rather than sizeof.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
tests/ldb_filter_attrs_test.c | 171 +++++++++++++-------------
|
||||
1 file changed, 86 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/tests/ldb_filter_attrs_test.c b/tests/ldb_filter_attrs_test.c
|
||||
index 7d555e0da2e..442d9c77ed2 100644
|
||||
--- a/tests/ldb_filter_attrs_test.c
|
||||
+++ b/tests/ldb_filter_attrs_test.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
+#include <string.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
@@ -96,10 +97,10 @@ static void test_filter_attrs_one_attr_matched(void **state)
|
||||
|
||||
const char *attrs[] = {"foo", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -130,9 +131,9 @@ static void test_filter_attrs_one_attr_matched(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "foo");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value));
|
||||
+ strlen(value));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value, sizeof(value));
|
||||
+ value, strlen(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -148,10 +149,10 @@ static void test_filter_attrs_one_attr_matched_of_many(void **state)
|
||||
|
||||
const char *attrs[] = {"foo", "bar", "baz", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -182,9 +183,9 @@ static void test_filter_attrs_one_attr_matched_of_many(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "foo");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value));
|
||||
+ strlen(value));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value, sizeof(value));
|
||||
+ value, strlen(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -201,15 +202,15 @@ static void test_filter_attrs_two_attr_matched_attrs(void **state)
|
||||
/* deliberatly the other order */
|
||||
const char *attrs[] = {"bar", "foo", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -251,15 +252,15 @@ static void test_filter_attrs_two_attr_matched_attrs(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "foo");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value1));
|
||||
+ strlen(value1));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value1, sizeof(value1));
|
||||
+ value1, strlen(value1));
|
||||
assert_string_equal(filtered_msg->elements[1].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[1].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[1].values[0].length,
|
||||
- sizeof(value2));
|
||||
+ strlen(value2));
|
||||
assert_memory_equal(filtered_msg->elements[1].values[0].data,
|
||||
- value2, sizeof(value2));
|
||||
+ value2, strlen(value2));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -276,15 +277,15 @@ static void test_filter_attrs_two_attr_matched_one_attr(void **state)
|
||||
/* deliberatly the other order */
|
||||
const char *attrs[] = {"bar", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -326,9 +327,9 @@ static void test_filter_attrs_two_attr_matched_one_attr(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value2));
|
||||
+ strlen(value2));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value2, sizeof(value2));
|
||||
+ value2, strlen(value2));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -345,15 +346,15 @@ static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state)
|
||||
/* deliberatly the other order */
|
||||
const char *attrs[] = {"bar", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -400,15 +401,15 @@ static void test_filter_attrs_two_dup_attr_matched_dup(void **state)
|
||||
|
||||
const char *attrs[] = {"bar", "bar", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -445,15 +446,15 @@ static void test_filter_attrs_two_dup_attr_matched_dup(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value1));
|
||||
+ strlen(value1));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value1, sizeof(value1));
|
||||
+ value1, strlen(value1));
|
||||
assert_string_equal(filtered_msg->elements[1].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[1].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[1].values[0].length,
|
||||
- sizeof(value2));
|
||||
+ strlen(value2));
|
||||
assert_memory_equal(filtered_msg->elements[1].values[0].data,
|
||||
- value2, sizeof(value2));
|
||||
+ value2, strlen(value2));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -469,15 +470,15 @@ static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state)
|
||||
|
||||
const char *attrs[] = {"bar", "foo", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -514,15 +515,15 @@ static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value1));
|
||||
+ strlen(value1));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value1, sizeof(value1));
|
||||
+ value1, strlen(value1));
|
||||
assert_string_equal(filtered_msg->elements[1].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[1].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[1].values[0].length,
|
||||
- sizeof(value2));
|
||||
+ strlen(value2));
|
||||
assert_memory_equal(filtered_msg->elements[1].values[0].data,
|
||||
- value2, sizeof(value2));
|
||||
+ value2, strlen(value2));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -538,15 +539,15 @@ static void test_filter_attrs_two_dup_attr_matched_star(void **state)
|
||||
|
||||
const char *attrs[] = {"*", "foo", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
|
||||
/* foo and bar are the other order to in attrs */
|
||||
@@ -586,15 +587,15 @@ static void test_filter_attrs_two_dup_attr_matched_star(void **state)
|
||||
assert_string_equal(filtered_msg->elements[0].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[0].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[0].values[0].length,
|
||||
- sizeof(value1));
|
||||
+ strlen(value1));
|
||||
assert_memory_equal(filtered_msg->elements[0].values[0].data,
|
||||
- value1, sizeof(value1));
|
||||
+ value1, strlen(value1));
|
||||
assert_string_equal(filtered_msg->elements[1].name, "bar");
|
||||
assert_int_equal(filtered_msg->elements[1].num_values, 1);
|
||||
assert_int_equal(filtered_msg->elements[1].values[0].length,
|
||||
- sizeof(value2));
|
||||
+ strlen(value2));
|
||||
assert_memory_equal(filtered_msg->elements[1].values[0].data,
|
||||
- value2, sizeof(value2));
|
||||
+ value2, strlen(value2));
|
||||
/*
|
||||
* assert the ldb_filter_attrs does not modify filtered_msg.dn
|
||||
* in this case
|
||||
@@ -619,10 +620,10 @@ static void test_filter_attrs_one_attr_matched_star(void **state)
|
||||
|
||||
const char *attrs[] = {"*", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -676,15 +677,15 @@ static void test_filter_attrs_two_attr_matched_star(void **state)
|
||||
|
||||
const char *attrs[] = {"*", NULL};
|
||||
|
||||
- uint8_t value1[] = "The value.......end";
|
||||
- uint8_t value2[] = "The value..MUST.end";
|
||||
+ char value1[] = "The value.......end";
|
||||
+ char value2[] = "The value..MUST.end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value1,
|
||||
- .length = (sizeof(value1))
|
||||
+ .data = (uint8_t *)value1,
|
||||
+ .length = strlen(value1)
|
||||
};
|
||||
struct ldb_val value_2 = {
|
||||
- .data = value2,
|
||||
- .length = (sizeof(value2))
|
||||
+ .data = (uint8_t *)value2,
|
||||
+ .length = strlen(value2)
|
||||
};
|
||||
struct ldb_message_element elements[] = {
|
||||
{
|
||||
@@ -750,10 +751,10 @@ static void test_filter_attrs_one_attr_matched_star_no_dn(void **state)
|
||||
|
||||
const char *attrs[] = {"*", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -789,10 +790,10 @@ static void test_filter_attrs_one_attr_matched_star_dn(void **state)
|
||||
|
||||
const char *attrs[] = {"*", "distinguishedName", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -844,10 +845,10 @@ static void test_filter_attrs_one_attr_matched_dn(void **state)
|
||||
|
||||
const char *attrs[] = {"distinguishedName", NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
@@ -894,10 +895,10 @@ static void test_filter_attrs_one_attr_empty_list(void **state)
|
||||
|
||||
const char *attrs[] = {NULL};
|
||||
|
||||
- uint8_t value[] = "The value.......end";
|
||||
+ char value[] = "The value.......end";
|
||||
struct ldb_val value_1 = {
|
||||
- .data = value,
|
||||
- .length = (sizeof(value))
|
||||
+ .data = (uint8_t *)value,
|
||||
+ .length = strlen(value)
|
||||
};
|
||||
struct ldb_message_element element_1 = {
|
||||
.name = "foo",
|
||||
--
|
||||
2.25.1
|
||||
48
backport-0004-CVE-2023-0614.patch
Normal file
48
backport-0004-CVE-2023-0614.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 936bfcb6ef804d2224072f3770ca09fe2596ee1f Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Wed, 15 Feb 2023 14:08:57 +1300
|
||||
Subject: [PATCH 08/34] CVE-2023-0614 ldb:tests: Ensure all tests are accounted
|
||||
for
|
||||
|
||||
Add ldb_filter_attrs_test to the list of tests so that it actually gets
|
||||
run.
|
||||
|
||||
Remove a duplicate ldb_msg_test that was accidentally added in commit
|
||||
5ca90e758ade97fb5e335029c7a1768094e70564.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
wscript | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/wscript b/wscript
|
||||
index 60bb7cf48b3..c862229822d 100644
|
||||
--- a/wscript
|
||||
+++ b/wscript
|
||||
@@ -627,7 +627,6 @@ def test(ctx):
|
||||
'ldb_msg_test',
|
||||
'ldb_tdb_mod_op_test',
|
||||
'ldb_tdb_guid_mod_op_test',
|
||||
- 'ldb_msg_test',
|
||||
'ldb_tdb_kv_ops_test',
|
||||
'ldb_tdb_test',
|
||||
'ldb_match_test',
|
||||
@@ -637,7 +636,9 @@ def test(ctx):
|
||||
# on operations which the TDB backend does not currently
|
||||
# support
|
||||
# 'ldb_key_value_sub_txn_tdb_test'
|
||||
- 'ldb_parse_test']
|
||||
+ 'ldb_parse_test',
|
||||
+ 'ldb_filter_attrs_test',
|
||||
+ ]
|
||||
|
||||
# if LIB_LDAP and LIB_LBER defined, then we can test ldb_ldap backend
|
||||
# behavior regression for bz#14413
|
||||
--
|
||||
2.25.1
|
||||
104
backport-0005-CVE-2023-0614.patch
Normal file
104
backport-0005-CVE-2023-0614.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From 83217ce77381f8faa3cde948e15a36db234d3033 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:23:42 +1300
|
||||
Subject: [PATCH 09/34] CVE-2023-0614 ldb: Add function to take ownership of an
|
||||
ldb message
|
||||
|
||||
Many places in Samba depend upon various components of an ldb message
|
||||
being talloc allocated, and hence able to be used as talloc contexts.
|
||||
The elements and values of an unpacked ldb message point to unowned data
|
||||
inside the memory-mapped database, and this function ensures that such
|
||||
messages have talloc ownership of said elements and values.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_pack.c | 41 ++++++++++++++++++++++++++++++++++++
|
||||
include/ldb_module.h | 4 ++++
|
||||
2 files changed, 45 insertions(+)
|
||||
|
||||
diff --git a/common/ldb_pack.c b/common/ldb_pack.c
|
||||
index e7dd364008a..028d96a619a 100644
|
||||
--- a/common/ldb_pack.c
|
||||
+++ b/common/ldb_pack.c
|
||||
@@ -690,6 +690,7 @@ static int ldb_unpack_data_flags_v1(struct ldb_context *ldb,
|
||||
element->values = NULL;
|
||||
if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
|
||||
element->values = &ldb_val_single_array[nelem];
|
||||
+ element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
|
||||
} else if (element->num_values != 0) {
|
||||
element->values = talloc_array(message->elements,
|
||||
struct ldb_val,
|
||||
@@ -932,6 +933,7 @@ static int ldb_unpack_data_flags_v2(struct ldb_context *ldb,
|
||||
if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) &&
|
||||
element->num_values == 1) {
|
||||
element->values = &ldb_val_single_array[nelem];
|
||||
+ element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
|
||||
} else if (element->num_values != 0) {
|
||||
element->values = talloc_array(message->elements,
|
||||
struct ldb_val,
|
||||
@@ -1259,3 +1261,42 @@ failed:
|
||||
TALLOC_FREE(filtered_msg->elements);
|
||||
return -1;
|
||||
}
|
||||
+
|
||||
+/* Have an unpacked ldb message take talloc ownership of its elements. */
|
||||
+int ldb_msg_elements_take_ownership(struct ldb_message *msg)
|
||||
+{
|
||||
+ unsigned int i = 0;
|
||||
+
|
||||
+ for (i = 0; i < msg->num_elements; i++) {
|
||||
+ struct ldb_message_element *el = &msg->elements[i];
|
||||
+ const char *name;
|
||||
+ unsigned int j;
|
||||
+
|
||||
+ name = talloc_strdup(msg->elements,
|
||||
+ el->name);
|
||||
+ if (name == NULL) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ el->name = name;
|
||||
+
|
||||
+ if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
|
||||
+ struct ldb_val *values = talloc_memdup(msg->elements, el->values,
|
||||
+ sizeof(struct ldb_val) * el->num_values);
|
||||
+ if (values == NULL) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ el->values = values;
|
||||
+ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
|
||||
+ }
|
||||
+
|
||||
+ for (j = 0; j < el->num_values; j++) {
|
||||
+ struct ldb_val val = ldb_val_dup(el->values, &el->values[j]);
|
||||
+ if (val.data == NULL && el->values[j].length != 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ el->values[j] = val;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return LDB_SUCCESS;
|
||||
+}
|
||||
diff --git a/include/ldb_module.h b/include/ldb_module.h
|
||||
index 8481fd3991a..8c7f33496fb 100644
|
||||
--- a/include/ldb_module.h
|
||||
+++ b/include/ldb_module.h
|
||||
@@ -542,6 +542,10 @@ int ldb_filter_attrs(struct ldb_context *ldb,
|
||||
const struct ldb_message *msg,
|
||||
const char *const *attrs,
|
||||
struct ldb_message *filtered_msg);
|
||||
+
|
||||
+/* Have an unpacked ldb message take talloc ownership of its elements. */
|
||||
+int ldb_msg_elements_take_ownership(struct ldb_message *msg);
|
||||
+
|
||||
/*
|
||||
* Unpack a ldb message from a linear buffer in ldb_val
|
||||
*
|
||||
--
|
||||
2.25.1
|
||||
62
backport-0006-CVE-2023-0614.patch
Normal file
62
backport-0006-CVE-2023-0614.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From a9b625bc8ab00b83b55bcd21ba0df48e73e4df29 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:26:04 +1300
|
||||
Subject: [PATCH 10/34] CVE-2023-0614 ldb: Add function to remove excess
|
||||
capacity from an ldb message
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
[abartlet@samba.org Adapted to conflict from lack of new
|
||||
ldb_ascii_toupper() in ldb_private.h]
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_msg.c | 16 ++++++++++++++++
|
||||
include/ldb_private.h | 3 +++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/common/ldb_msg.c b/common/ldb_msg.c
|
||||
index cbc7e32b2ba..2ea2cce2e83 100644
|
||||
--- a/common/ldb_msg.c
|
||||
+++ b/common/ldb_msg.c
|
||||
@@ -1497,6 +1497,22 @@ void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Reallocate elements to drop any excess capacity. */
|
||||
+void ldb_msg_shrink_to_fit(struct ldb_message *msg)
|
||||
+{
|
||||
+ if (msg->num_elements > 0) {
|
||||
+ struct ldb_message_element *elements = talloc_realloc(msg,
|
||||
+ msg->elements,
|
||||
+ struct ldb_message_element,
|
||||
+ msg->num_elements);
|
||||
+ if (elements != NULL) {
|
||||
+ msg->elements = elements;
|
||||
+ }
|
||||
+ } else {
|
||||
+ TALLOC_FREE(msg->elements);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
return a LDAP formatted GeneralizedTime string
|
||||
*/
|
||||
diff --git a/include/ldb_private.h b/include/ldb_private.h
|
||||
index 4deb24691ca..338e71def6d 100644
|
||||
--- a/include/ldb_private.h
|
||||
+++ b/include/ldb_private.h
|
||||
@@ -317,4 +317,7 @@ int ldb_match_message(struct ldb_context *ldb,
|
||||
const struct ldb_parse_tree *tree,
|
||||
enum ldb_scope scope, bool *matched);
|
||||
|
||||
+/* Reallocate elements to drop any excess capacity. */
|
||||
+void ldb_msg_shrink_to_fit(struct ldb_message *msg);
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.25.1
|
||||
68
backport-0007-CVE-2023-0614.patch
Normal file
68
backport-0007-CVE-2023-0614.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 8b7374780e3e7b67e51a1b54a09bf48d89fa9f26 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:27:38 +1300
|
||||
Subject: [PATCH 11/34] CVE-2023-0614 ldb: Add function to add
|
||||
distinguishedName to message
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
[abartlet@samba.org Adapted to conflict from lack of new
|
||||
ldb_ascii_toupper() in ldb_private.h]
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_pack.c | 6 +++---
|
||||
include/ldb_private.h | 5 +++++
|
||||
2 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/common/ldb_pack.c b/common/ldb_pack.c
|
||||
index 028d96a619a..b0b0d64a5ba 100644
|
||||
--- a/common/ldb_pack.c
|
||||
+++ b/common/ldb_pack.c
|
||||
@@ -1098,7 +1098,7 @@ int ldb_unpack_data(struct ldb_context *ldb,
|
||||
/*
|
||||
add the special distinguishedName element
|
||||
*/
|
||||
-static int msg_add_distinguished_name(struct ldb_message *msg)
|
||||
+int ldb_msg_add_distinguished_name(struct ldb_message *msg)
|
||||
{
|
||||
const char *dn_attr = "distinguishedName";
|
||||
char *dn = NULL;
|
||||
@@ -1158,7 +1158,7 @@ int ldb_filter_attrs(struct ldb_context *ldb,
|
||||
|
||||
/* Shortcuts for the simple cases */
|
||||
} else if (add_dn && i == 1) {
|
||||
- if (msg_add_distinguished_name(filtered_msg) != 0) {
|
||||
+ if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
return 0;
|
||||
@@ -1238,7 +1238,7 @@ int ldb_filter_attrs(struct ldb_context *ldb,
|
||||
filtered_msg->num_elements = num_elements;
|
||||
|
||||
if (add_dn) {
|
||||
- if (msg_add_distinguished_name(filtered_msg) != 0) {
|
||||
+ if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
diff --git a/include/ldb_private.h b/include/ldb_private.h
|
||||
index 338e71def6d..ca43817d07a 100644
|
||||
--- a/include/ldb_private.h
|
||||
+++ b/include/ldb_private.h
|
||||
@@ -320,4 +320,9 @@ int ldb_match_message(struct ldb_context *ldb,
|
||||
/* Reallocate elements to drop any excess capacity. */
|
||||
void ldb_msg_shrink_to_fit(struct ldb_message *msg);
|
||||
|
||||
+/*
|
||||
+ add the special distinguishedName element
|
||||
+*/
|
||||
+int ldb_msg_add_distinguished_name(struct ldb_message *msg);
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.25.1
|
||||
1224
backport-0008-CVE-2023-0614.patch
Normal file
1224
backport-0008-CVE-2023-0614.patch
Normal file
File diff suppressed because it is too large
Load Diff
1275
backport-0009-CVE-2023-0614.patch
Normal file
1275
backport-0009-CVE-2023-0614.patch
Normal file
File diff suppressed because it is too large
Load Diff
257
backport-0010-CVE-2023-0614.patch
Normal file
257
backport-0010-CVE-2023-0614.patch
Normal file
@ -0,0 +1,257 @@
|
||||
From 8e84201f508b2893b6ec9383c656cccb08b148ef Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Mon, 27 Feb 2023 10:31:52 +1300
|
||||
Subject: [PATCH 14/34] CVE-2023-0614 ldb: Make use of
|
||||
ldb_filter_attrs_in_place()
|
||||
|
||||
Change all uses of ldb_kv_filter_attrs() to use
|
||||
ldb_filter_attrs_in_place() instead. This function does less work than
|
||||
its predecessor, and no longer requires the allocation of a second ldb
|
||||
message. Some of the work is able to be split out into separate
|
||||
functions that each accomplish a single task, with a purpose to make the
|
||||
code clearer.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
ldb_key_value/ldb_kv.h | 6 +-
|
||||
ldb_key_value/ldb_kv_index.c | 27 +++++----
|
||||
ldb_key_value/ldb_kv_search.c | 86 ++++++++++++++-------------
|
||||
4 files changed, 66 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/ldb_key_value/ldb_kv.h b/ldb_key_value/ldb_kv.h
|
||||
index ac474b04b4c..7d5a40e76e9 100644
|
||||
--- a/ldb_key_value/ldb_kv.h
|
||||
+++ b/ldb_key_value/ldb_kv.h
|
||||
@@ -301,10 +301,8 @@ int ldb_kv_search_key(struct ldb_module *module,
|
||||
const struct ldb_val ldb_key,
|
||||
struct ldb_message *msg,
|
||||
unsigned int unpack_flags);
|
||||
-int ldb_kv_filter_attrs(struct ldb_context *ldb,
|
||||
- const struct ldb_message *msg,
|
||||
- const char *const *attrs,
|
||||
- struct ldb_message *filtered_msg);
|
||||
+int ldb_kv_filter_attrs_in_place(struct ldb_message *msg,
|
||||
+ const char *const *attrs);
|
||||
int ldb_kv_search(struct ldb_kv_context *ctx);
|
||||
|
||||
/*
|
||||
diff --git a/ldb_key_value/ldb_kv_index.c b/ldb_key_value/ldb_kv_index.c
|
||||
index d70e5f619ef..203266ea8c9 100644
|
||||
--- a/ldb_key_value/ldb_kv_index.c
|
||||
+++ b/ldb_key_value/ldb_kv_index.c
|
||||
@@ -2264,7 +2264,6 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv,
|
||||
{
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
|
||||
struct ldb_message *msg;
|
||||
- struct ldb_message *filtered_msg;
|
||||
unsigned int i;
|
||||
unsigned int num_keys = 0;
|
||||
uint8_t previous_guid_key[LDB_KV_GUID_KEY_SIZE] = {0};
|
||||
@@ -2456,27 +2455,31 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv,
|
||||
continue;
|
||||
}
|
||||
|
||||
- filtered_msg = ldb_msg_new(ac);
|
||||
- if (filtered_msg == NULL) {
|
||||
- TALLOC_FREE(keys);
|
||||
- TALLOC_FREE(msg);
|
||||
+ ret = ldb_msg_add_distinguished_name(msg);
|
||||
+ if (ret == -1) {
|
||||
+ talloc_free(msg);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
- filtered_msg->dn = talloc_steal(filtered_msg, msg->dn);
|
||||
-
|
||||
/* filter the attributes that the user wants */
|
||||
- ret = ldb_kv_filter_attrs(ldb, msg, ac->attrs, filtered_msg);
|
||||
+ ret = ldb_kv_filter_attrs_in_place(msg, ac->attrs);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(keys);
|
||||
+ talloc_free(msg);
|
||||
+ return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ }
|
||||
|
||||
- talloc_free(msg);
|
||||
+ ldb_msg_shrink_to_fit(msg);
|
||||
|
||||
- if (ret == -1) {
|
||||
- TALLOC_FREE(filtered_msg);
|
||||
+ /* Ensure the message elements are all talloc'd. */
|
||||
+ ret = ldb_msg_elements_take_ownership(msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
talloc_free(keys);
|
||||
+ talloc_free(msg);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
- ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
|
||||
+ ret = ldb_module_send_entry(ac->req, msg, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* Regardless of success or failure, the msg
|
||||
* is the callbacks responsiblity, and should
|
||||
diff --git a/ldb_key_value/ldb_kv_search.c b/ldb_key_value/ldb_kv_search.c
|
||||
index 46031b99c16..f3333510eab 100644
|
||||
--- a/ldb_key_value/ldb_kv_search.c
|
||||
+++ b/ldb_key_value/ldb_kv_search.c
|
||||
@@ -292,15 +292,13 @@ int ldb_kv_search_dn1(struct ldb_module *module,
|
||||
|
||||
/*
|
||||
* filter the specified list of attributes from msg,
|
||||
- * adding requested attributes, and perhaps all for *,
|
||||
- * but not the DN to filtered_msg.
|
||||
+ * adding requested attributes, and perhaps all for *.
|
||||
+ * The DN will not be added if it is missing.
|
||||
*/
|
||||
-int ldb_kv_filter_attrs(struct ldb_context *ldb,
|
||||
- const struct ldb_message *msg,
|
||||
- const char *const *attrs,
|
||||
- struct ldb_message *filtered_msg)
|
||||
+int ldb_kv_filter_attrs_in_place(struct ldb_message *msg,
|
||||
+ const char *const *attrs)
|
||||
{
|
||||
- return ldb_filter_attrs(ldb, msg, attrs, filtered_msg);
|
||||
+ return ldb_filter_attrs_in_place(msg, attrs);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -313,7 +311,7 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_kv_context *ac;
|
||||
- struct ldb_message *msg, *filtered_msg;
|
||||
+ struct ldb_message *msg;
|
||||
struct timeval now;
|
||||
int ret, timeval_cmp;
|
||||
bool matched;
|
||||
@@ -410,25 +408,31 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- filtered_msg = ldb_msg_new(ac);
|
||||
- if (filtered_msg == NULL) {
|
||||
- TALLOC_FREE(msg);
|
||||
+ ret = ldb_msg_add_distinguished_name(msg);
|
||||
+ if (ret == -1) {
|
||||
+ talloc_free(msg);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
- filtered_msg->dn = talloc_steal(filtered_msg, msg->dn);
|
||||
-
|
||||
/* filter the attributes that the user wants */
|
||||
- ret = ldb_kv_filter_attrs(ldb, msg, ac->attrs, filtered_msg);
|
||||
- talloc_free(msg);
|
||||
+ ret = ldb_kv_filter_attrs_in_place(msg, ac->attrs);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ ac->error = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- if (ret == -1) {
|
||||
- TALLOC_FREE(filtered_msg);
|
||||
+ ldb_msg_shrink_to_fit(msg);
|
||||
+
|
||||
+ /* Ensure the message elements are all talloc'd. */
|
||||
+ ret = ldb_msg_elements_take_ownership(msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
ac->error = LDB_ERR_OPERATIONS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
- ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
|
||||
+ ret = ldb_module_send_entry(ac->req, msg, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
ac->request_terminated = true;
|
||||
/* the callback failed, abort the operation */
|
||||
@@ -491,7 +495,7 @@ static int ldb_kv_search_full(struct ldb_kv_context *ctx)
|
||||
static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv,
|
||||
struct ldb_kv_context *ctx)
|
||||
{
|
||||
- struct ldb_message *msg, *filtered_msg;
|
||||
+ struct ldb_message *msg;
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
|
||||
const char *dn_linearized;
|
||||
const char *msg_dn_linearized;
|
||||
@@ -549,12 +553,6 @@ static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv,
|
||||
dn_linearized = ldb_dn_get_linearized(ctx->base);
|
||||
msg_dn_linearized = ldb_dn_get_linearized(msg->dn);
|
||||
|
||||
- filtered_msg = ldb_msg_new(ctx);
|
||||
- if (filtered_msg == NULL) {
|
||||
- talloc_free(msg);
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
- }
|
||||
-
|
||||
if (strcmp(dn_linearized, msg_dn_linearized) == 0) {
|
||||
/*
|
||||
* If the DN is exactly the same string, then
|
||||
@@ -562,36 +560,42 @@ static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv,
|
||||
* returned result, as it has already been
|
||||
* casefolded
|
||||
*/
|
||||
- filtered_msg->dn = ldb_dn_copy(filtered_msg, ctx->base);
|
||||
+ struct ldb_dn *dn = ldb_dn_copy(msg, ctx->base);
|
||||
+ if (dn != NULL) {
|
||||
+ msg->dn = dn;
|
||||
+ }
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If the ldb_dn_copy() failed, or if we did not choose that
|
||||
- * optimisation (filtered_msg is zeroed at allocation),
|
||||
- * steal the one from the unpack
|
||||
- */
|
||||
- if (filtered_msg->dn == NULL) {
|
||||
- filtered_msg->dn = talloc_steal(filtered_msg, msg->dn);
|
||||
+ ret = ldb_msg_add_distinguished_name(msg);
|
||||
+ if (ret == -1) {
|
||||
+ talloc_free(msg);
|
||||
+ return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* filter the attributes that the user wants.
|
||||
*/
|
||||
- ret = ldb_kv_filter_attrs(ldb, msg, ctx->attrs, filtered_msg);
|
||||
- if (ret == -1) {
|
||||
+ ret = ldb_kv_filter_attrs_in_place(msg, ctx->attrs);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ ldb_msg_shrink_to_fit(msg);
|
||||
+
|
||||
+ /* Ensure the message elements are all talloc'd. */
|
||||
+ ret = ldb_msg_elements_take_ownership(msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
talloc_free(msg);
|
||||
- filtered_msg = NULL;
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
- * Remove any extended components possibly copied in from
|
||||
- * msg->dn, we just want the casefold components
|
||||
+ * Remove any extended components, we just want the casefold components
|
||||
*/
|
||||
- ldb_dn_remove_extended_components(filtered_msg->dn);
|
||||
- talloc_free(msg);
|
||||
+ ldb_dn_remove_extended_components(msg->dn);
|
||||
|
||||
- ret = ldb_module_send_entry(ctx->req, filtered_msg, NULL);
|
||||
+ ret = ldb_module_send_entry(ctx->req, msg, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* Regardless of success or failure, the msg
|
||||
* is the callbacks responsiblity, and should
|
||||
--
|
||||
2.25.1
|
||||
66
backport-0011-CVE-2023-0614.patch
Normal file
66
backport-0011-CVE-2023-0614.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From b23fb132e63a6d3d791469614593c43906686ac9 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:31:54 +1300
|
||||
Subject: [PATCH 20/34] CVE-2023-0614 ldb: Add ldb_parse_tree_get_attr()
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_parse.c | 25 +++++++++++++++++++++++++
|
||||
include/ldb_module.h | 3 +++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/common/ldb_parse.c b/common/ldb_parse.c
|
||||
index f0045ad2093..2d102ff750e 100644
|
||||
--- a/common/ldb_parse.c
|
||||
+++ b/common/ldb_parse.c
|
||||
@@ -997,3 +997,28 @@ struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx,
|
||||
|
||||
return nt;
|
||||
}
|
||||
+
|
||||
+/* Get the attribute (if any) associated with the top node of a parse tree. */
|
||||
+const char *ldb_parse_tree_get_attr(const struct ldb_parse_tree *tree)
|
||||
+{
|
||||
+ switch (tree->operation) {
|
||||
+ case LDB_OP_AND:
|
||||
+ case LDB_OP_OR:
|
||||
+ case LDB_OP_NOT:
|
||||
+ return NULL;
|
||||
+ case LDB_OP_EQUALITY:
|
||||
+ return tree->u.equality.attr;
|
||||
+ case LDB_OP_SUBSTRING:
|
||||
+ return tree->u.substring.attr;
|
||||
+ case LDB_OP_GREATER:
|
||||
+ case LDB_OP_LESS:
|
||||
+ case LDB_OP_APPROX:
|
||||
+ return tree->u.comparison.attr;
|
||||
+ case LDB_OP_PRESENT:
|
||||
+ return tree->u.present.attr;
|
||||
+ case LDB_OP_EXTENDED:
|
||||
+ return tree->u.extended.attr;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/include/ldb_module.h b/include/ldb_module.h
|
||||
index 4ae381ba5be..bd369ed9512 100644
|
||||
--- a/include/ldb_module.h
|
||||
+++ b/include/ldb_module.h
|
||||
@@ -490,6 +490,9 @@ int ldb_init_module(const char *version);
|
||||
*/
|
||||
bool ldb_dn_replace_components(struct ldb_dn *dn, struct ldb_dn *new_dn);
|
||||
|
||||
+/* Get the attribute (if any) associated with the top node of a parse tree. */
|
||||
+const char *ldb_parse_tree_get_attr(const struct ldb_parse_tree *tree);
|
||||
+
|
||||
/*
|
||||
walk a parse tree, calling the provided callback on each node
|
||||
*/
|
||||
--
|
||||
2.25.1
|
||||
231
backport-0012-CVE-2023-0614.patch
Normal file
231
backport-0012-CVE-2023-0614.patch
Normal file
@ -0,0 +1,231 @@
|
||||
From f87af853e2db99269acea572dcc109bc6f797aa9 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:34:29 +1300
|
||||
Subject: [PATCH 24/34] CVE-2023-0614 ldb: Prevent disclosure of confidential
|
||||
attributes
|
||||
|
||||
Add a hook, acl_redact_msg_for_filter(), in the aclread module, that
|
||||
marks inaccessible any message elements used by an LDAP search filter
|
||||
that the user has no right to access. Make the various ldb_match_*()
|
||||
functions check whether message elements are accessible, and refuse to
|
||||
match any that are not. Remaining message elements, not mentioned in the
|
||||
search filter, are checked in aclread_callback(), and any inaccessible
|
||||
elements are removed at this point.
|
||||
|
||||
Certain attributes, namely objectClass, distinguishedName, name, and
|
||||
objectGUID, are always present, and hence the presence of said
|
||||
attributes is always allowed to be checked in a search filter. This
|
||||
corresponds with the behaviour of Windows.
|
||||
|
||||
Further, we unconditionally allow the attributes isDeleted and
|
||||
isRecycled in a check for presence or equality. Windows is not known to
|
||||
make this special exception, but it seems mostly harmless, and should
|
||||
mitigate the performance impact on searches made by the show_deleted
|
||||
module.
|
||||
|
||||
As a result of all these changes, our behaviour regarding confidential
|
||||
attributes happens to match Windows more closely. For the test in
|
||||
confidential_attr.py, we can now model our attribute handling with
|
||||
DC_MODE_RETURN_ALL, which corresponds to the behaviour exhibited by
|
||||
Windows.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
[abartlet@samba.org adapted due to Samba 4.17 and lower
|
||||
not having the patches for CVE-2020-25720]
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_match.c | 37 +
|
||||
include/ldb_module.h | 11 +
|
||||
include/ldb_private.h | 5 +
|
||||
ldb_key_value/ldb_kv_index.c | 8 +
|
||||
ldb_key_value/ldb_kv_search.c | 15 +
|
||||
12 files changed, 672 insertions(+), 455 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/confidential-attr-timing
|
||||
|
||||
diff --git a/common/ldb_match.c b/common/ldb_match.c
|
||||
index 2f4d41f3441..17314f1b9ca 100644
|
||||
--- a/common/ldb_match.c
|
||||
+++ b/common/ldb_match.c
|
||||
@@ -98,6 +98,11 @@ static int ldb_match_present(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ if (ldb_msg_element_is_inaccessible(el)) {
|
||||
+ *matched = false;
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (!a) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -139,6 +144,11 @@ static int ldb_match_comparison(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ if (ldb_msg_element_is_inaccessible(el)) {
|
||||
+ *matched = false;
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (!a) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -209,6 +219,11 @@ static int ldb_match_equality(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ if (ldb_msg_element_is_inaccessible(el)) {
|
||||
+ *matched = false;
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (a == NULL) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -370,6 +385,11 @@ static int ldb_match_substring(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ if (ldb_msg_element_is_inaccessible(el)) {
|
||||
+ *matched = false;
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < el->num_values; i++) {
|
||||
int ret;
|
||||
ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
|
||||
@@ -443,6 +463,11 @@ static int ldb_match_bitmask(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ if (ldb_msg_element_is_inaccessible(el)) {
|
||||
+ *matched = false;
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
for (i=0;i<el->num_values;i++) {
|
||||
int ret;
|
||||
struct ldb_val *v = &el->values[i];
|
||||
@@ -741,3 +766,15 @@ int ldb_register_extended_match_rule(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+int ldb_register_redact_callback(struct ldb_context *ldb,
|
||||
+ ldb_redact_fn redact_fn,
|
||||
+ struct ldb_module *module)
|
||||
+{
|
||||
+ if (ldb->redact.callback != NULL) {
|
||||
+ return LDB_ERR_ENTRY_ALREADY_EXISTS;
|
||||
+ }
|
||||
+
|
||||
+ ldb->redact.callback = redact_fn;
|
||||
+ ldb->redact.module = module;
|
||||
+ return LDB_SUCCESS;
|
||||
+}
|
||||
diff --git a/include/ldb_module.h b/include/ldb_module.h
|
||||
index bd369ed9512..0f14b1ad346 100644
|
||||
--- a/include/ldb_module.h
|
||||
+++ b/include/ldb_module.h
|
||||
@@ -102,6 +102,12 @@ struct ldb_module;
|
||||
*/
|
||||
#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200
|
||||
|
||||
+/*
|
||||
+ * this attribute has been access checked. We know the user has the right to
|
||||
+ * view it. Used internally in Samba aclread module.
|
||||
+ */
|
||||
+#define LDB_FLAG_INTERNAL_ACCESS_CHECKED 0x400
|
||||
+
|
||||
/* an extended match rule that always fails to match */
|
||||
#define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1"
|
||||
|
||||
@@ -520,6 +526,11 @@ void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el);
|
||||
bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el);
|
||||
void ldb_msg_remove_inaccessible(struct ldb_message *msg);
|
||||
|
||||
+typedef int (*ldb_redact_fn)(struct ldb_module *, struct ldb_request *, struct ldb_message *);
|
||||
+int ldb_register_redact_callback(struct ldb_context *ldb,
|
||||
+ ldb_redact_fn redact_fn,
|
||||
+ struct ldb_module *module);
|
||||
+
|
||||
/*
|
||||
* these pack/unpack functions are exposed in the library for use by
|
||||
* ldb tools like ldbdump and for use in tests,
|
||||
diff --git a/include/ldb_private.h b/include/ldb_private.h
|
||||
index ca43817d07a..b0a42f6421c 100644
|
||||
--- a/include/ldb_private.h
|
||||
+++ b/include/ldb_private.h
|
||||
@@ -119,6 +119,11 @@ struct ldb_context {
|
||||
struct ldb_extended_match_entry *prev, *next;
|
||||
} *extended_match_rules;
|
||||
|
||||
+ struct {
|
||||
+ struct ldb_module *module;
|
||||
+ ldb_redact_fn callback;
|
||||
+ } redact;
|
||||
+
|
||||
/* custom utf8 functions */
|
||||
struct ldb_utf8_fns utf8_fns;
|
||||
|
||||
diff --git a/ldb_key_value/ldb_kv_index.c b/ldb_key_value/ldb_kv_index.c
|
||||
index 203266ea8c9..163052fecf7 100644
|
||||
--- a/ldb_key_value/ldb_kv_index.c
|
||||
+++ b/ldb_key_value/ldb_kv_index.c
|
||||
@@ -2428,6 +2428,14 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv,
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
+ if (ldb->redact.callback != NULL) {
|
||||
+ ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* We trust the index for LDB_SCOPE_ONELEVEL
|
||||
* unless the index key has been truncated.
|
||||
diff --git a/ldb_key_value/ldb_kv_search.c b/ldb_key_value/ldb_kv_search.c
|
||||
index f3333510eab..d187ba223e1 100644
|
||||
--- a/ldb_key_value/ldb_kv_search.c
|
||||
+++ b/ldb_key_value/ldb_kv_search.c
|
||||
@@ -395,6 +395,14 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (ldb->redact.callback != NULL) {
|
||||
+ ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* see if it matches the given expression */
|
||||
ret = ldb_match_msg_error(ldb, msg,
|
||||
ac->tree, ac->base, ac->scope, &matched);
|
||||
@@ -530,6 +538,13 @@ static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ if (ldb->redact.callback != NULL) {
|
||||
+ ret = ldb->redact.callback(ldb->redact.module, ctx->req, msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/*
|
||||
* We use this, not ldb_match_msg_error() as we know
|
||||
--
|
||||
130
backport-0013-CVE-2023-0614.patch
Normal file
130
backport-0013-CVE-2023-0614.patch
Normal file
@ -0,0 +1,130 @@
|
||||
From 94efa3fc3053a623a7a5c3a4a6428356bc334152 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Tue, 14 Feb 2023 13:17:24 +1300
|
||||
Subject: [PATCH 27/34] CVE-2023-0614 ldb: Centralise checking for inaccessible
|
||||
matches
|
||||
|
||||
This makes it less likely that we forget to handle a case.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_match.c | 56 +++++++++++++++++-------------
|
||||
2 files changed, 31 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/common/ldb_match.c b/common/ldb_match.c
|
||||
index 17314f1b9ca..645cb695ef1 100644
|
||||
--- a/common/ldb_match.c
|
||||
+++ b/common/ldb_match.c
|
||||
@@ -98,11 +98,6 @@ static int ldb_match_present(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (ldb_msg_element_is_inaccessible(el)) {
|
||||
- *matched = false;
|
||||
- return LDB_SUCCESS;
|
||||
- }
|
||||
-
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (!a) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -144,11 +139,6 @@ static int ldb_match_comparison(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (ldb_msg_element_is_inaccessible(el)) {
|
||||
- *matched = false;
|
||||
- return LDB_SUCCESS;
|
||||
- }
|
||||
-
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (!a) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -219,11 +209,6 @@ static int ldb_match_equality(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (ldb_msg_element_is_inaccessible(el)) {
|
||||
- *matched = false;
|
||||
- return LDB_SUCCESS;
|
||||
- }
|
||||
-
|
||||
a = ldb_schema_attribute_by_name(ldb, el->name);
|
||||
if (a == NULL) {
|
||||
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
|
||||
@@ -385,11 +370,6 @@ static int ldb_match_substring(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (ldb_msg_element_is_inaccessible(el)) {
|
||||
- *matched = false;
|
||||
- return LDB_SUCCESS;
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < el->num_values; i++) {
|
||||
int ret;
|
||||
ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
|
||||
@@ -463,11 +443,6 @@ static int ldb_match_bitmask(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
- if (ldb_msg_element_is_inaccessible(el)) {
|
||||
- *matched = false;
|
||||
- return LDB_SUCCESS;
|
||||
- }
|
||||
-
|
||||
for (i=0;i<el->num_values;i++) {
|
||||
int ret;
|
||||
struct ldb_val *v = &el->values[i];
|
||||
@@ -556,6 +531,26 @@ static int ldb_match_extended(struct ldb_context *ldb,
|
||||
&tree->u.extended.value, matched);
|
||||
}
|
||||
|
||||
+static bool ldb_must_suppress_match(const struct ldb_message *msg,
|
||||
+ const struct ldb_parse_tree *tree)
|
||||
+{
|
||||
+ const char *attr = NULL;
|
||||
+ struct ldb_message_element *el = NULL;
|
||||
+
|
||||
+ attr = ldb_parse_tree_get_attr(tree);
|
||||
+ if (attr == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* find the message element */
|
||||
+ el = ldb_msg_find_element(msg, attr);
|
||||
+ if (el == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return ldb_msg_element_is_inaccessible(el);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
Check if a particular message will match the given filter
|
||||
|
||||
@@ -580,6 +575,17 @@ int ldb_match_message(struct ldb_context *ldb,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Suppress matches on confidential attributes (handled
|
||||
+ * manually in extended matches as these can do custom things
|
||||
+ * like read other parts of the DB or other attributes).
|
||||
+ */
|
||||
+ if (tree->operation != LDB_OP_EXTENDED) {
|
||||
+ if (ldb_must_suppress_match(msg, tree)) {
|
||||
+ return LDB_SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
switch (tree->operation) {
|
||||
case LDB_OP_AND:
|
||||
for (i=0;i<tree->u.list.num_elements;i++) {
|
||||
--
|
||||
2.25.1
|
||||
155
backport-0014-CVE-2023-0614.patch
Normal file
155
backport-0014-CVE-2023-0614.patch
Normal file
@ -0,0 +1,155 @@
|
||||
From a0c888bd0ed2ec5b4d84f9df241bebd5d428818c Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Date: Fri, 3 Mar 2023 17:35:55 +1300
|
||||
Subject: [PATCH 28/34] CVE-2023-0614 ldb: Filter on search base before
|
||||
redacting message
|
||||
|
||||
Redaction may be expensive if we end up needing to fetch a security
|
||||
descriptor to verify rights to an attribute. Checking the search scope
|
||||
is probably cheaper, so do that first.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270
|
||||
|
||||
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://attachments.samba.org/attachment.cgi?id=17821
|
||||
---
|
||||
common/ldb_match.c | 8 +++---
|
||||
include/ldb_private.h | 8 ++++++
|
||||
ldb_key_value/ldb_kv_index.c | 40 +++++++++++++++------------
|
||||
ldb_key_value/ldb_kv_search.c | 14 ++++++++--
|
||||
4 files changed, 47 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/common/ldb_match.c b/common/ldb_match.c
|
||||
index 645cb695ef1..8e27ecbe723 100644
|
||||
--- a/common/ldb_match.c
|
||||
+++ b/common/ldb_match.c
|
||||
@@ -38,10 +38,10 @@
|
||||
/*
|
||||
check if the scope matches in a search result
|
||||
*/
|
||||
-static int ldb_match_scope(struct ldb_context *ldb,
|
||||
- struct ldb_dn *base,
|
||||
- struct ldb_dn *dn,
|
||||
- enum ldb_scope scope)
|
||||
+int ldb_match_scope(struct ldb_context *ldb,
|
||||
+ struct ldb_dn *base,
|
||||
+ struct ldb_dn *dn,
|
||||
+ enum ldb_scope scope)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
diff --git a/include/ldb_private.h b/include/ldb_private.h
|
||||
index b0a42f6421c..5e29de34f79 100644
|
||||
--- a/include/ldb_private.h
|
||||
+++ b/include/ldb_private.h
|
||||
@@ -322,6 +322,14 @@ int ldb_match_message(struct ldb_context *ldb,
|
||||
const struct ldb_parse_tree *tree,
|
||||
enum ldb_scope scope, bool *matched);
|
||||
|
||||
+/*
|
||||
+ check if the scope matches in a search result
|
||||
+*/
|
||||
+int ldb_match_scope(struct ldb_context *ldb,
|
||||
+ struct ldb_dn *base,
|
||||
+ struct ldb_dn *dn,
|
||||
+ enum ldb_scope scope);
|
||||
+
|
||||
/* Reallocate elements to drop any excess capacity. */
|
||||
void ldb_msg_shrink_to_fit(struct ldb_message *msg);
|
||||
|
||||
diff --git a/ldb_key_value/ldb_kv_index.c b/ldb_key_value/ldb_kv_index.c
|
||||
index 163052fecf7..aac0913f431 100644
|
||||
--- a/ldb_key_value/ldb_kv_index.c
|
||||
+++ b/ldb_key_value/ldb_kv_index.c
|
||||
@@ -2428,31 +2428,37 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv,
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
- if (ldb->redact.callback != NULL) {
|
||||
- ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
|
||||
- if (ret != LDB_SUCCESS) {
|
||||
- talloc_free(msg);
|
||||
- return ret;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* We trust the index for LDB_SCOPE_ONELEVEL
|
||||
* unless the index key has been truncated.
|
||||
*
|
||||
* LDB_SCOPE_BASE is not passed in by our only caller.
|
||||
*/
|
||||
- if (ac->scope == LDB_SCOPE_ONELEVEL &&
|
||||
- ldb_kv->cache->one_level_indexes &&
|
||||
- scope_one_truncation == KEY_NOT_TRUNCATED) {
|
||||
- ret = ldb_match_message(ldb, msg, ac->tree,
|
||||
- ac->scope, &matched);
|
||||
- } else {
|
||||
- ret = ldb_match_msg_error(ldb, msg,
|
||||
- ac->tree, ac->base,
|
||||
- ac->scope, &matched);
|
||||
+ if (ac->scope != LDB_SCOPE_ONELEVEL ||
|
||||
+ !ldb_kv->cache->one_level_indexes ||
|
||||
+ scope_one_truncation != KEY_NOT_TRUNCATED)
|
||||
+ {
|
||||
+ /*
|
||||
+ * The redaction callback may be expensive to call if it
|
||||
+ * fetches a security descriptor. Check the DN early and
|
||||
+ * bail out if it doesn't match the base.
|
||||
+ */
|
||||
+ if (!ldb_match_scope(ldb, ac->base, msg->dn, ac->scope)) {
|
||||
+ talloc_free(msg);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (ldb->redact.callback != NULL) {
|
||||
+ ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ talloc_free(msg);
|
||||
+ return ret;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ ret = ldb_match_message(ldb, msg, ac->tree,
|
||||
+ ac->scope, &matched);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(keys);
|
||||
talloc_free(msg);
|
||||
diff --git a/ldb_key_value/ldb_kv_search.c b/ldb_key_value/ldb_kv_search.c
|
||||
index d187ba223e1..27f68caef01 100644
|
||||
--- a/ldb_key_value/ldb_kv_search.c
|
||||
+++ b/ldb_key_value/ldb_kv_search.c
|
||||
@@ -395,6 +395,16 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
|
||||
}
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * The redaction callback may be expensive to call if it fetches a
|
||||
+ * security descriptor. Check the DN early and bail out if it doesn't
|
||||
+ * match the base.
|
||||
+ */
|
||||
+ if (!ldb_match_scope(ldb, ac->base, msg->dn, ac->scope)) {
|
||||
+ talloc_free(msg);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (ldb->redact.callback != NULL) {
|
||||
ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
@@ -404,8 +414,8 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
|
||||
}
|
||||
|
||||
/* see if it matches the given expression */
|
||||
- ret = ldb_match_msg_error(ldb, msg,
|
||||
- ac->tree, ac->base, ac->scope, &matched);
|
||||
+ ret = ldb_match_message(ldb, msg,
|
||||
+ ac->tree, ac->scope, &matched);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(msg);
|
||||
ac->error = LDB_ERR_OPERATIONS_ERROR;
|
||||
--
|
||||
2.25.1
|
||||
22
libldb.spec
22
libldb.spec
@ -6,7 +6,7 @@
|
||||
|
||||
Name: libldb
|
||||
Version: 2.6.1
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: A schema-less, ldap like, API and database
|
||||
Requires: libtalloc%{?_isa} >= %{talloc_version}
|
||||
Requires: libtdb%{?_isa} >= %{tdb_version}
|
||||
@ -17,6 +17,20 @@ Source0: http://samba.org/ftp/ldb/ldb-%{version}.tar.gz
|
||||
Source1: http://samba.org/ftp/ldb/ldb-%{version}.tar.asc
|
||||
|
||||
Patch0: backport-Skip-ldb_lmdb_free_list_test-on-ppc64el-ppc64-and-sp.patch
|
||||
patch0001: backport-0001-CVE-2023-0614.patch
|
||||
patch0002: backport-0002-CVE-2023-0614.patch
|
||||
patch0003: backport-0003-CVE-2023-0614.patch
|
||||
patch0004: backport-0004-CVE-2023-0614.patch
|
||||
patch0005: backport-0005-CVE-2023-0614.patch
|
||||
patch0006: backport-0006-CVE-2023-0614.patch
|
||||
patch0007: backport-0007-CVE-2023-0614.patch
|
||||
patch0008: backport-0008-CVE-2023-0614.patch
|
||||
patch0009: backport-0009-CVE-2023-0614.patch
|
||||
patch0010: backport-0010-CVE-2023-0614.patch
|
||||
patch0011: backport-0011-CVE-2023-0614.patch
|
||||
patch0012: backport-0012-CVE-2023-0614.patch
|
||||
patch0013: backport-0013-CVE-2023-0614.patch
|
||||
patch0014: backport-0014-CVE-2023-0614.patch
|
||||
|
||||
BuildRequires: gcc libtalloc-devel >= %{talloc_version} libtdb-devel >= %{tdb_version}
|
||||
BuildRequires: libtevent-devel >= %{tevent_version} lmdb-devel >= 0.9.16 popt-devel
|
||||
@ -170,6 +184,12 @@ echo "%{_libdir}/ldb" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.conf
|
||||
%{_mandir}/man1/ldbsearch.1.*
|
||||
|
||||
%changelog
|
||||
* Sat Apr 01 2023 xinghe <xinghe2@h-partners.com> - 2.6.1-2
|
||||
- Type:CVE
|
||||
- ID:CVE-2023-0614
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-0614
|
||||
|
||||
* Fri Nov 04 2022 yanglu <yanglu72@h-partners.com> - 2.6.1-1
|
||||
- Type:requirement
|
||||
- ID:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user