diff --git a/backport-0001-CVE-2023-0225.patch b/backport-0001-CVE-2023-0225.patch deleted file mode 100644 index 1f6fe7ddf16a81e9e314ebd55e6ad5652ae205e7..0000000000000000000000000000000000000000 --- a/backport-0001-CVE-2023-0225.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0bc08daf4c191c370cb218e9a0ecac51b8c36468 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Thu, 28 Apr 2022 20:34:36 +1200 -Subject: [PATCH 1/4] CVE-2023-0225 CVE-2020-25720 s4/dsdb/util: Add functions - for dsHeuristics 28, 29 - -These are the newly-added AttributeAuthorizationOnLDAPAdd and -BlockOwnerImplicitRights. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810 -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15276 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett -(cherry picked from commit 0af5706b559e89c77123ed174b41fd3d01705aa5) - -[abartlet@samba.org This patch is needed for a clean backport of - CVE-2023-0225 as these constants are used in the acl_modify test - even when this behaviour is not itself used.] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17833 ---- - libds/common/flags.h | 2 ++ - source4/dsdb/samdb/ldb_modules/util.c | 40 +++++++++++++++++++++++++++ - 2 files changed, 42 insertions(+) - -diff --git a/libds/common/flags.h b/libds/common/flags.h -index 75e04b0c488..bee1016b294 100644 ---- a/libds/common/flags.h -+++ b/libds/common/flags.h -@@ -258,6 +258,8 @@ - #define DS_HR_KVNOEMUW2K 0x00000011 - - #define DS_HR_TWENTIETH_CHAR 0x00000014 -+#define DS_HR_ATTR_AUTHZ_ON_LDAP_ADD 0x0000001C -+#define DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS 0x0000001D - #define DS_HR_THIRTIETH_CHAR 0x0000001E - #define DS_HR_FOURTIETH_CHAR 0x00000028 - #define DS_HR_FIFTIETH_CHAR 0x00000032 -diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c -index 9e00aedd09e..c2949f0734d 100644 ---- a/source4/dsdb/samdb/ldb_modules/util.c -+++ b/source4/dsdb/samdb/ldb_modules/util.c -@@ -1433,6 +1433,46 @@ bool dsdb_do_list_object(struct ldb_module *module, - return result; - } - -+bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module, -+ TALLOC_CTX *mem_ctx, -+ struct ldb_request *parent) -+{ -+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); -+ bool result = false; -+ const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module, -+ tmp_ctx, -+ parent); -+ if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) { -+ uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1]; -+ if (val != '0' && val != '2') { -+ result = true; -+ } -+ } -+ -+ talloc_free(tmp_ctx); -+ return result; -+} -+ -+bool dsdb_block_owner_implicit_rights(struct ldb_module *module, -+ TALLOC_CTX *mem_ctx, -+ struct ldb_request *parent) -+{ -+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); -+ bool result = false; -+ const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module, -+ tmp_ctx, -+ parent); -+ if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) { -+ uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1]; -+ if (val != '0' && val != '2') { -+ result = true; -+ } -+ } -+ -+ talloc_free(tmp_ctx); -+ return result; -+} -+ - /* - show the chain of requests, useful for debugging async requests - */ --- -2.25.1 \ No newline at end of file diff --git a/backport-0001-CVE-2023-0614.patch b/backport-0001-CVE-2023-0614.patch deleted file mode 100644 index 47c3049e1f068dbebf57f7431ceb0450a1b7fae9..0000000000000000000000000000000000000000 --- a/backport-0001-CVE-2023-0614.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 197d1f09158ee0575cd92c461ed12bdbf4efc074 Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -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 -Reviewed-by: Joseph Sutton -(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 ---- - lib/ldb/common/ldb_match.c | 60 +++++++++++++++++++++++++++++++------- - 1 file changed, 50 insertions(+), 10 deletions(-) - -diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c -index 2f4d41f3441..51376871b4c 100644 ---- a/lib/ldb/common/ldb_match.c -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0002-CVE-2023-0225.patch b/backport-0002-CVE-2023-0225.patch deleted file mode 100644 index 445e1b64a6892b6770264e99f00079a9f27eefc2..0000000000000000000000000000000000000000 --- a/backport-0002-CVE-2023-0225.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 47f8a529885d321c4f787832d5934757656e8094 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Tue, 6 Sep 2022 19:23:13 +1200 -Subject: [PATCH 2/4] CVE-2023-0225 CVE-2020-25720 pydsdb: Add dsHeuristics - constant definitions - -We want to be able to use these values in Python tests. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810 -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15276 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett -(cherry picked from commit cc709077822a39227174b91ed2345c2bd603f61f) - -[abartlet@samba.org This patch is needed for a clean backport of - CVE-2023-0225 as these constants are used in the acl_modify test - even when this behaviour is not itself used.] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17833 ---- - source4/dsdb/pydsdb.c | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - -diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c -index bcfc7e95478..626d849a561 100644 ---- a/source4/dsdb/pydsdb.c -+++ b/source4/dsdb/pydsdb.c -@@ -1665,6 +1665,36 @@ MODULE_INIT_FUNC(dsdb) - ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE); - ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION); - -+ /* dsHeuristics character indexes (see MS-ADTS 7.1.1.2.4.1.2) */ -+ ADD_DSDB_FLAG(DS_HR_SUPFIRSTLASTANR); -+ ADD_DSDB_FLAG(DS_HR_SUPLASTFIRSTANR); -+ ADD_DSDB_FLAG(DS_HR_DOLISTOBJECT); -+ ADD_DSDB_FLAG(DS_HR_DONICKRES); -+ ADD_DSDB_FLAG(DS_HR_LDAP_USEPERMMOD); -+ ADD_DSDB_FLAG(DS_HR_HIDEDSID); -+ ADD_DSDB_FLAG(DS_HR_BLOCK_ANONYMOUS_OPS); -+ ADD_DSDB_FLAG(DS_HR_ALLOW_ANON_NSPI); -+ ADD_DSDB_FLAG(DS_HR_USER_PASSWORD_SUPPORT); -+ ADD_DSDB_FLAG(DS_HR_TENTH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_SPECIFY_GUID_ON_ADD); -+ ADD_DSDB_FLAG(DS_HR_NO_STANDARD_SD); -+ ADD_DSDB_FLAG(DS_HR_ALLOW_NONSECURE_PWD_OPS); -+ ADD_DSDB_FLAG(DS_HR_NO_PROPAGATE_ON_NOCHANGE); -+ ADD_DSDB_FLAG(DS_HR_COMPUTE_ANR_STATS); -+ ADD_DSDB_FLAG(DS_HR_ADMINSDEXMASK); -+ ADD_DSDB_FLAG(DS_HR_KVNOEMUW2K); -+ -+ ADD_DSDB_FLAG(DS_HR_TWENTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_ATTR_AUTHZ_ON_LDAP_ADD); -+ ADD_DSDB_FLAG(DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS); -+ ADD_DSDB_FLAG(DS_HR_THIRTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_FOURTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_FIFTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_SIXTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_SEVENTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_EIGHTIETH_CHAR); -+ ADD_DSDB_FLAG(DS_HR_NINETIETH_CHAR); -+ - ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY); - ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY); - ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY); --- -2.25.1 \ No newline at end of file diff --git a/backport-0002-CVE-2023-0614.patch b/backport-0002-CVE-2023-0614.patch deleted file mode 100644 index 1653dec170858d9b3ca1b14e4a22aa5eec9bcabe..0000000000000000000000000000000000000000 --- a/backport-0002-CVE-2023-0614.patch +++ /dev/null @@ -1,137 +0,0 @@ -From ba8c9eae1392bf21d3e36530eda1780defd22300 Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Mon, 13 Mar 2023 17:20:00 +1300 -Subject: [PATCH 02/35] CVE-2023-0614 selftest: Use setUpClass() to reduce - "make test TESTS=large_ldap" time - -This reduces the elapsed time to 6m from 20m on my laptop. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15332 -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Autobuild-User(master): Andrew Bartlett -Autobuild-Date(master): Tue Mar 14 07:16:04 UTC 2023 on atb-devel-224 - -(cherry picked from commit b4a6c054ec6acefacd22cb7230a783d20cb07c05) - -[abartlet@samba.org Included in the security release as this - makes working on the large_ldap test practical by reducing - the elapsed time taken] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/tests/python/large_ldap.py | 69 +++++++++++++------------ - 1 file changed, 36 insertions(+), 33 deletions(-) - -diff --git a/source4/dsdb/tests/python/large_ldap.py b/source4/dsdb/tests/python/large_ldap.py -index 0805119a700..13729052e65 100644 ---- a/source4/dsdb/tests/python/large_ldap.py -+++ b/source4/dsdb/tests/python/large_ldap.py -@@ -66,30 +66,32 @@ creds = credopts.get_credentials(lp) - - class ManyLDAPTest(samba.tests.TestCase): - -- def setUp(self): -- super(ManyLDAPTest, self).setUp() -- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -- self.base_dn = self.ldb.domain_dn() -- self.OU_NAME_MANY="many_ou" + format(random.randint(0, 99999), "05") -- self.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME_MANY + "," + str(self.base_dn)) -- -- samba.tests.delete_force(self.ldb, self.ou_dn, -+ @classmethod -+ def setUpClass(cls): -+ super().setUpClass() -+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -+ cls.base_dn = self.ldb.domain_dn() -+ cls.OU_NAME_MANY="many_ou" + format(random.randint(0, 99999), "05") -+ cls.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME_MANY + "," + str(self.base_dn)) -+ -+ samba.tests.delete_force(cls.ldb, cls.ou_dn, - controls=['tree_delete:1']) - -- self.ldb.add({ -- "dn": self.ou_dn, -+ cls.ldb.add({ -+ "dn": cls.ou_dn, - "objectclass": "organizationalUnit", -- "ou": self.OU_NAME_MANY}) -+ "ou": cls.OU_NAME_MANY}) - - for x in range(2000): -- ou_name = self.OU_NAME_MANY + str(x) -- self.ldb.add({ -- "dn": "ou=" + ou_name + "," + str(self.ou_dn), -+ ou_name = cls.OU_NAME_MANY + str(x) -+ cls.ldb.add({ -+ "dn": "ou=" + ou_name + "," + str(cls.ou_dn), - "objectclass": "organizationalUnit", - "ou": ou_name}) - -- def tearDown(self): -- samba.tests.delete_force(self.ldb, self.ou_dn, -+ @classmethod -+ def tearDownClass(cls): -+ samba.tests.delete_force(cls.ldb, self.ou_dn, - controls=['tree_delete:1']) - - def test_unindexed_iterator_search(self): -@@ -117,34 +119,35 @@ class ManyLDAPTest(samba.tests.TestCase): - - class LargeLDAPTest(samba.tests.TestCase): - -- def setUp(self): -- super(LargeLDAPTest, self).setUp() -- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -- self.base_dn = self.ldb.domain_dn() -- self.USER_NAME = "large_user" + format(random.randint(0, 99999), "05") + "-" -- self.OU_NAME="large_user_ou" + format(random.randint(0, 99999), "05") -- self.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME + "," + str(self.base_dn)) -+ @classmethod -+ def setUpClass(cls): -+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -+ cls.base_dn = cls.ldb.domain_dn() -+ cls.USER_NAME = "large_user" + format(random.randint(0, 99999), "05") + "-" -+ cls.OU_NAME="large_user_ou" + format(random.randint(0, 99999), "05") -+ cls.ou_dn = ldb.Dn(cls.ldb, "ou=" + cls.OU_NAME + "," + str(cls.base_dn)) - -- samba.tests.delete_force(self.ldb, self.ou_dn, -+ samba.tests.delete_force(cls.ldb, cls.ou_dn, - controls=['tree_delete:1']) - -- self.ldb.add({ -- "dn": self.ou_dn, -+ cls.ldb.add({ -+ "dn": cls.ou_dn, - "objectclass": "organizationalUnit", -- "ou": self.OU_NAME}) -+ "ou": cls.OU_NAME}) - - for x in range(200): -- user_name = self.USER_NAME + format(x, "03") -- self.ldb.add({ -- "dn": "cn=" + user_name + "," + str(self.ou_dn), -+ user_name = cls.USER_NAME + format(x, "03") -+ cls.ldb.add({ -+ "dn": "cn=" + user_name + "," + str(cls.ou_dn), - "objectclass": "user", - "sAMAccountName": user_name, - "jpegPhoto": b'a' * (2 * 1024 * 1024)}) - -- def tearDown(self): -+ @classmethod -+ def tearDownClass(cls): - # Remake the connection for tear-down (old Samba drops the socket) -- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -- samba.tests.delete_force(self.ldb, self.ou_dn, -+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) -+ samba.tests.delete_force(cls.ldb, cls.ou_dn, - controls=['tree_delete:1']) - - def test_unindexed_iterator_search(self): --- -2.25.1 \ No newline at end of file diff --git a/backport-0003-CVE-2023-0225.patch b/backport-0003-CVE-2023-0225.patch deleted file mode 100644 index 5a997ac894073c33485ecb522f3dcf829e31099a..0000000000000000000000000000000000000000 --- a/backport-0003-CVE-2023-0225.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 417fda9bfde2f8db315ea0460fb7da6e780b859c Mon Sep 17 00:00:00 2001 -From: Douglas Bagnall -Date: Wed, 4 Jan 2023 21:37:49 +1300 -Subject: [PATCH 3/4] CVE-2023-0225 pytest/acl: test deleting dNSHostName as - unprivileged user - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15276 - -Signed-off-by: Douglas Bagnall -Reviewed-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -[abartlet@samba.org The self.set_heuristic(samba.dsdb.DS_HR_ATTR_AUTHZ_ON_LDAP_ADD, b'11') - in the test setUp() is unused in this test but is included as a - clean backport, so the fact that the server does not implement this - is unimportant] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17833 ---- - selftest/knownfail.d/dns-host-name-deletion | 2 + - source4/dsdb/tests/python/acl_modify.py | 236 ++++++++++++++++++++ - source4/selftest/tests.py | 1 + - 3 files changed, 239 insertions(+) - create mode 100644 selftest/knownfail.d/dns-host-name-deletion - create mode 100755 source4/dsdb/tests/python/acl_modify.py - -diff --git a/selftest/knownfail.d/dns-host-name-deletion b/selftest/knownfail.d/dns-host-name-deletion -new file mode 100644 -index 00000000000..ac11619ffc3 ---- /dev/null -+++ b/selftest/knownfail.d/dns-host-name-deletion -@@ -0,0 +1,2 @@ -+^samba4.ldap.acl_modify.python\(.*\).__main__.AclModifyTests.test_modify_delete_dns_host_name_ldif_unspecified\(.*\) -+^samba4.ldap.acl_modify.python\(.*\).__main__.AclModifyTests.test_modify_delete_dns_host_name_unspecified\(.*\) -diff --git a/source4/dsdb/tests/python/acl_modify.py b/source4/dsdb/tests/python/acl_modify.py -new file mode 100755 -index 00000000000..c85748a764f ---- /dev/null -+++ b/source4/dsdb/tests/python/acl_modify.py -@@ -0,0 +1,236 @@ -+#!/usr/bin/env python3 -+# -*- coding: utf-8 -*- -+ -+ -+import optparse -+import sys -+sys.path.insert(0, "bin/python") -+import samba -+ -+from samba.tests.subunitrun import SubunitOptions, TestProgram -+ -+import samba.getopt as options -+ -+from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS -+from ldb import Message, MessageElement, Dn -+from ldb import FLAG_MOD_REPLACE, FLAG_MOD_DELETE -+from samba.dcerpc import security -+ -+from samba.auth import system_session -+from samba import gensec, sd_utils -+from samba.samdb import SamDB -+from samba.credentials import Credentials, DONT_USE_KERBEROS -+import samba.tests -+import samba.dsdb -+ -+ -+parser = optparse.OptionParser("acl.py [options] ") -+sambaopts = options.SambaOptions(parser) -+parser.add_option_group(sambaopts) -+parser.add_option_group(options.VersionOptions(parser)) -+ -+# use command line creds if available -+credopts = options.CredentialsOptions(parser) -+parser.add_option_group(credopts) -+subunitopts = SubunitOptions(parser) -+parser.add_option_group(subunitopts) -+ -+opts, args = parser.parse_args() -+ -+if len(args) < 1: -+ parser.print_usage() -+ sys.exit(1) -+ -+host = args[0] -+if "://" not in host: -+ ldaphost = "ldap://%s" % host -+else: -+ ldaphost = host -+ start = host.rindex("://") -+ host = host.lstrip(start + 3) -+ -+lp = sambaopts.get_loadparm() -+creds = credopts.get_credentials(lp) -+creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) -+ -+# -+# Tests start here -+# -+ -+ -+class AclTests(samba.tests.TestCase): -+ -+ def setUp(self): -+ super(AclTests, self).setUp() -+ -+ strict_checking = samba.tests.env_get_var_value('STRICT_CHECKING', allow_missing=True) -+ if strict_checking is None: -+ strict_checking = '1' -+ self.strict_checking = bool(int(strict_checking)) -+ -+ self.ldb_admin = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) -+ self.base_dn = self.ldb_admin.domain_dn() -+ self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid()) -+ self.user_pass = "samba123@" -+ self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized() -+ self.sd_utils = sd_utils.SDUtils(self.ldb_admin) -+ self.addCleanup(self.delete_admin_connection) -+ # used for anonymous login -+ self.creds_tmp = Credentials() -+ self.creds_tmp.set_username("") -+ self.creds_tmp.set_password("") -+ self.creds_tmp.set_domain(creds.get_domain()) -+ self.creds_tmp.set_realm(creds.get_realm()) -+ self.creds_tmp.set_workstation(creds.get_workstation()) -+ print("baseDN: %s" % self.base_dn) -+ -+ # set AttributeAuthorizationOnLDAPAdd and BlockOwnerImplicitRights -+ self.set_heuristic(samba.dsdb.DS_HR_ATTR_AUTHZ_ON_LDAP_ADD, b'11') -+ -+ def set_heuristic(self, index, values): -+ self.assertGreater(index, 0) -+ self.assertLess(index, 30) -+ self.assertIsInstance(values, bytes) -+ -+ # Get the old "dSHeuristics" if it was set -+ dsheuristics = self.ldb_admin.get_dsheuristics() -+ # Reset the "dSHeuristics" as they were before -+ self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics) -+ # Set the "dSHeuristics" to activate the correct behaviour -+ default_heuristics = b"000000000100000000020000000003" -+ if dsheuristics is None: -+ dsheuristics = b"" -+ dsheuristics += default_heuristics[len(dsheuristics):] -+ dsheuristics = (dsheuristics[:index - 1] + -+ values + -+ dsheuristics[index - 1 + len(values):]) -+ self.ldb_admin.set_dsheuristics(dsheuristics) -+ -+ def get_user_dn(self, name): -+ return "CN=%s,CN=Users,%s" % (name, self.base_dn) -+ -+ def get_ldb_connection(self, target_username, target_password): -+ creds_tmp = Credentials() -+ creds_tmp.set_username(target_username) -+ creds_tmp.set_password(target_password) -+ creds_tmp.set_domain(creds.get_domain()) -+ creds_tmp.set_realm(creds.get_realm()) -+ creds_tmp.set_workstation(creds.get_workstation()) -+ creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() -+ | gensec.FEATURE_SEAL) -+ creds_tmp.set_kerberos_state(DONT_USE_KERBEROS) # kinit is too expensive to use in a tight loop -+ ldb_target = SamDB(url=ldaphost, credentials=creds_tmp, lp=lp) -+ return ldb_target -+ -+ # Test if we have any additional groups for users than default ones -+ def assert_user_no_group_member(self, username): -+ res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % self.get_user_dn(username)) -+ try: -+ self.assertEqual(res[0]["memberOf"][0], "") -+ except KeyError: -+ pass -+ else: -+ self.fail() -+ -+ def delete_admin_connection(self): -+ del self.sd_utils -+ del self.ldb_admin -+ -+ -+class AclModifyTests(AclTests): -+ -+ def setup_computer_with_hostname(self, account_name): -+ ou_dn = f'OU={account_name},{self.base_dn}' -+ dn = f'CN={account_name},{ou_dn}' -+ -+ user, password = "mouse", "mus musculus 123!" -+ self.addCleanup(self.ldb_admin.deleteuser, user) -+ -+ self.ldb_admin.newuser(user, password) -+ self.ldb_user = self.get_ldb_connection(user, password) -+ -+ self.addCleanup(self.ldb_admin.delete, ou_dn, -+ controls=["tree_delete:0"]) -+ self.ldb_admin.create_ou(ou_dn) -+ -+ self.ldb_admin.add({ -+ 'dn': dn, -+ 'objectClass': 'computer', -+ 'sAMAccountName': account_name + '$', -+ }) -+ -+ host_name = f'{account_name}.{self.ldb_user.domain_dns_name()}' -+ -+ m = Message(Dn(self.ldb_admin, dn)) -+ m['dNSHostName'] = MessageElement(host_name, -+ FLAG_MOD_REPLACE, -+ 'dNSHostName') -+ -+ self.ldb_admin.modify(m) -+ return host_name, dn -+ -+ def test_modify_delete_dns_host_name_specified(self): -+ '''Test deleting dNSHostName''' -+ account_name = self.id().rsplit(".", 1)[1][:63] -+ host_name, dn = self.setup_computer_with_hostname(account_name) -+ -+ m = Message(Dn(self.ldb_user, dn)) -+ m['dNSHostName'] = MessageElement(host_name, -+ FLAG_MOD_DELETE, -+ 'dNSHostName') -+ -+ self.assertRaisesLdbError( -+ ERR_INSUFFICIENT_ACCESS_RIGHTS, -+ "User able to delete dNSHostName (with specified name)", -+ self.ldb_user.modify, m) -+ -+ def test_modify_delete_dns_host_name_unspecified(self): -+ '''Test deleting dNSHostName''' -+ account_name = self.id().rsplit(".", 1)[1][:63] -+ host_name, dn = self.setup_computer_with_hostname(account_name) -+ -+ m = Message(Dn(self.ldb_user, dn)) -+ m['dNSHostName'] = MessageElement([], -+ FLAG_MOD_DELETE, -+ 'dNSHostName') -+ -+ self.assertRaisesLdbError( -+ ERR_INSUFFICIENT_ACCESS_RIGHTS, -+ "User able to delete dNSHostName (without specified name)", -+ self.ldb_user.modify, m) -+ -+ def test_modify_delete_dns_host_name_ldif_specified(self): -+ '''Test deleting dNSHostName''' -+ account_name = self.id().rsplit(".", 1)[1][:63] -+ host_name, dn = self.setup_computer_with_hostname(account_name) -+ -+ ldif = f""" -+dn: {dn} -+changetype: modify -+delete: dNSHostName -+dNSHostName: {host_name} -+""" -+ self.assertRaisesLdbError( -+ ERR_INSUFFICIENT_ACCESS_RIGHTS, -+ "User able to delete dNSHostName (with specified name)", -+ self.ldb_user.modify_ldif, ldif) -+ -+ def test_modify_delete_dns_host_name_ldif_unspecified(self): -+ '''Test deleting dNSHostName''' -+ account_name = self.id().rsplit(".", 1)[1][:63] -+ host_name, dn = self.setup_computer_with_hostname(account_name) -+ -+ ldif = f""" -+dn: {dn} -+changetype: modify -+delete: dNSHostName -+""" -+ self.assertRaisesLdbError( -+ ERR_INSUFFICIENT_ACCESS_RIGHTS, -+ "User able to delete dNSHostName (without specific name)", -+ self.ldb_user.modify_ldif, ldif) -+ -+ -+ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) -+ -+TestProgram(module=__name__, opts=subunitopts) -diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py -index c6bf668aa9c..9ef9600d886 100755 ---- a/source4/selftest/tests.py -+++ b/source4/selftest/tests.py -@@ -1417,6 +1417,7 @@ for env in all_fl_envs + ["schema_dc"]: - plantestsuite("samba4.ldap.possibleInferiors.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/samdb/ldb_modules/tests/possibleinferiors.py"), "ldap://$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) - plantestsuite_loadlist("samba4.ldap.secdesc.python(%s)" % env, env, [python, os.path.join(DSDB_PYTEST_DIR, "sec_descriptor.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - plantestsuite_loadlist("samba4.ldap.acl.python(%s)" % env, env, ["STRICT_CHECKING=0", python, os.path.join(DSDB_PYTEST_DIR, "acl.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) -+ plantestsuite_loadlist("samba4.ldap.acl_modify.python(%s)" % env, env, ["STRICT_CHECKING=0", python, os.path.join(DSDB_PYTEST_DIR, "acl_modify.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - - for env in all_fl_envs + ["schema_dc", "ad_dc_no_ntlm"]: - if env != "fl2000dc": --- -2.25.1 \ No newline at end of file diff --git a/backport-0003-CVE-2023-0614.patch b/backport-0003-CVE-2023-0614.patch deleted file mode 100644 index 9608e668ee76b47ffe145308ac52338c4ae6cdd1..0000000000000000000000000000000000000000 --- a/backport-0003-CVE-2023-0614.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e7aa14a5405735234b989bdeba384c7c9249257a Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Fri, 3 Mar 2023 10:31:40 +1300 -Subject: [PATCH 01/34] CVE-2023-0614 dsdb: Alter timeout test in large_ldap.py - to be slower by matching on large objects - -This changes the slow aspect to be the object matching not the filter parsing. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/tests/python/large_ldap.py | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - -diff --git a/source4/dsdb/tests/python/large_ldap.py b/source4/dsdb/tests/python/large_ldap.py -index 0805119a700..f7569607cb2 100644 ---- a/source4/dsdb/tests/python/large_ldap.py -+++ b/source4/dsdb/tests/python/large_ldap.py -@@ -32,7 +32,7 @@ from samba.tests.subunitrun import SubunitOptions, TestProgram - import samba.getopt as options - - from samba.auth import system_session --from samba import ldb -+from samba import ldb, sd_utils - from samba.samdb import SamDB - from samba.ndr import ndr_unpack - from samba import gensec -@@ -123,10 +123,13 @@ class LargeLDAPTest(samba.tests.TestCase): - def setUpClass(cls): - cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) - cls.base_dn = cls.ldb.domain_dn() -+ -+ cls.sd_utils = sd_utils.SDUtils(cls.ldb) - cls.USER_NAME = "large_user" + format(random.randint(0, 99999), "05") + "-" - cls.OU_NAME="large_user_ou" + format(random.randint(0, 99999), "05") - cls.ou_dn = ldb.Dn(cls.ldb, "ou=" + cls.OU_NAME + "," + str(cls.base_dn)) - -+ - samba.tests.delete_force(cls.ldb, cls.ou_dn, - controls=['tree_delete:1']) - -@@ -249,6 +252,7 @@ class LargeLDAPTest(samba.tests.TestCase): - self.assertGreater(count, count_jpeg) - - def test_timeout(self): -+ - policy_dn = ldb.Dn(self.ldb, - 'CN=Default Query Policy,CN=Query-Policies,' - 'CN=Directory Service,CN=Windows NT,CN=Services,' -@@ -283,9 +286,19 @@ class LargeLDAPTest(samba.tests.TestCase): - session_info=system_session(lp), - lp=lp) - -+ for x in range(200): -+ user_name = self.USER_NAME + format(x, "03") -+ ace = "(OD;;RP;{6bc69afa-7bd9-4184-88f5-28762137eb6a};;S-1-%d)" % x -+ dn = ldb.Dn(self.ldb, "cn=" + user_name + "," + str(self.ou_dn)) -+ -+ # add an ACE that denies access to the above random attr -+ # for a not-existing user. This makes each SD distinct -+ # and so will slow SD parsing. -+ self.sd_utils.dacl_add_ace(dn, ace) -+ - # Create a large search expression that will take a long time to - # evaluate. -- expression = '(anr=l)' * 10000 -+ expression = f'(jpegPhoto=*X*)' * 1000 - expression = f'(|{expression})' - - # Perform the LDAP search. --- -2.25.1 \ No newline at end of file diff --git a/backport-0004-CVE-2023-0225.patch b/backport-0004-CVE-2023-0225.patch deleted file mode 100644 index 56384243352b8a43b9f6ce0e1213af8b05b70671..0000000000000000000000000000000000000000 --- a/backport-0004-CVE-2023-0225.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0d753cc8f2b072175f994ede8b3a541303a8a2d5 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Mon, 9 Jan 2023 11:22:34 +1300 -Subject: [PATCH 4/4] CVE-2023-0225 s4-acl: Don't return early if dNSHostName - element has no values - -This early return would mistakenly allow an unprivileged user to delete -the dNSHostName attribute by making an LDAP modify request with no -values. We should no longer allow this. - -Add or replace operations with no values and no privileges are -disallowed. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15276 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17833 ---- - selftest/knownfail.d/dns-host-name-deletion | 2 -- - source4/dsdb/samdb/ldb_modules/acl.c | 12 +++++++----- - 2 files changed, 7 insertions(+), 7 deletions(-) - delete mode 100644 selftest/knownfail.d/dns-host-name-deletion - -diff --git a/selftest/knownfail.d/dns-host-name-deletion b/selftest/knownfail.d/dns-host-name-deletion -deleted file mode 100644 -index ac11619ffc3..00000000000 ---- a/selftest/knownfail.d/dns-host-name-deletion -+++ /dev/null -@@ -1,2 +0,0 @@ --^samba4.ldap.acl_modify.python\(.*\).__main__.AclModifyTests.test_modify_delete_dns_host_name_ldif_unspecified\(.*\) --^samba4.ldap.acl_modify.python\(.*\).__main__.AclModifyTests.test_modify_delete_dns_host_name_unspecified\(.*\) -diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c -index 4098ae2d671..b602520ca2b 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl.c -+++ b/source4/dsdb/samdb/ldb_modules/acl.c -@@ -900,11 +900,6 @@ static int acl_check_dns_host_name(TALLOC_CTX *mem_ctx, - NULL - }; - -- if (el->num_values == 0) { -- return LDB_SUCCESS; -- } -- dnsHostName = &el->values[0]; -- - tmp_ctx = talloc_new(mem_ctx); - if (tmp_ctx == NULL) { - return ldb_oom(ldb); -@@ -1050,6 +1045,13 @@ static int acl_check_dns_host_name(TALLOC_CTX *mem_ctx, - --account_name_len; - } - -+ /* Check for add or replace requests with no value. */ -+ if (el->num_values == 0) { -+ talloc_free(tmp_ctx); -+ return ldb_operr(ldb); -+ } -+ dnsHostName = &el->values[0]; -+ - dnsHostName_str = (const char *)dnsHostName->data; - dns_host_name_len = dnsHostName->length; - --- -2.25.1 - diff --git a/backport-0004-CVE-2023-0614.patch b/backport-0004-CVE-2023-0614.patch deleted file mode 100644 index 3b6d2e9b6328c7956f4b97c7edb21dbd570dfd52..0000000000000000000000000000000000000000 --- a/backport-0004-CVE-2023-0614.patch +++ /dev/null @@ -1,79 +0,0 @@ -From ad6945f667329d75174cfb9e90786f811c579355 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 27 Jan 2023 07:57:27 +1300 -Subject: [PATCH 02/34] CVE-2023-0614 libcli/security: Make some parameters - const - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -[abartlet@samba.org Updated to add const to sec_access_check_ds() -instead of the sec_access_check_ds_implicit_owner() wrapper -found in 4.18 and later] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - libcli/security/access_check.c | 10 +++++----- - libcli/security/access_check.h | 2 +- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c -index f5051b0fa93..7dd3798703c 100644 ---- a/libcli/security/access_check.c -+++ b/libcli/security/access_check.c -@@ -394,7 +394,7 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd, - return NT_STATUS_OK; - } - --static const struct GUID *get_ace_object_type(struct security_ace *ace) -+static const struct GUID *get_ace_object_type(const struct security_ace *ace) - { - if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) { - return &ace->object.object.type.type; -@@ -412,7 +412,7 @@ static const struct GUID *get_ace_object_type(struct security_ace *ace) - * rights to the object/attribute - * @returns NT_STATUS_OK, unless access was denied - */ --static NTSTATUS check_object_specific_access(struct security_ace *ace, -+static NTSTATUS check_object_specific_access(const struct security_ace *ace, - struct object_tree *tree, - bool *grant_access) - { -@@ -505,7 +505,7 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, - uint32_t access_desired, - uint32_t *access_granted, - struct object_tree *tree, -- struct dom_sid *replace_sid) -+ const struct dom_sid *replace_sid) - { - uint32_t i; - uint32_t bits_remaining; -@@ -556,8 +556,8 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, - - /* check each ace in turn. */ - for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { -- struct dom_sid *trustee; -- struct security_ace *ace = &sd->dacl->aces[i]; -+ const struct dom_sid *trustee; -+ const struct security_ace *ace = &sd->dacl->aces[i]; - NTSTATUS status; - bool grant_access = false; - -diff --git a/libcli/security/access_check.h b/libcli/security/access_check.h -index 96e33c6624f..37ca078a24e 100644 ---- a/libcli/security/access_check.h -+++ b/libcli/security/access_check.h -@@ -74,7 +74,7 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, - uint32_t access_desired, - uint32_t *access_granted, - struct object_tree *tree, -- struct dom_sid *replace_sid); -+ const struct dom_sid *replace_sid); - - bool insert_in_object_tree(TALLOC_CTX *mem_ctx, - const struct GUID *guid, --- -2.25.1 \ No newline at end of file diff --git a/backport-0005-CVE-2023-0614.patch b/backport-0005-CVE-2023-0614.patch deleted file mode 100644 index 62df6733d40524c20d1dce242ded426ac31f0ca1..0000000000000000000000000000000000000000 --- a/backport-0005-CVE-2023-0614.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 89f882b49d2669ba8b51e9b5de644164f5c1995e Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Tue, 7 Feb 2023 09:29:51 +1300 -Subject: [PATCH 03/34] CVE-2023-0614 s4:dsdb: Use talloc_get_type_abort() more - consistently - -It is better to explicitly abort than to dereference a NULL pointer or -try to read data cast to the wrong type. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 4 ++-- - source4/dsdb/samdb/ldb_modules/acl_util.c | 2 +- - source4/dsdb/samdb/ldb_modules/linked_attributes.c | 2 +- - source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- - 4 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index b221dcde445..16a1927183c 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -268,7 +268,7 @@ static int aclread_get_sd_from_ldb_message(struct aclread_context *ac, - struct ldb_message_element *sd_element; - struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - struct aclread_private *private_data -- = talloc_get_type(ldb_module_get_private(ac->module), -+ = talloc_get_type_abort(ldb_module_get_private(ac->module), - struct aclread_private); - enum ndr_err_code ndr_err; - -@@ -568,7 +568,7 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - const struct dsdb_class *objectclass; - bool suppress_result = false; - -- ac = talloc_get_type(req->context, struct aclread_context); -+ ac = talloc_get_type_abort(req->context, struct aclread_context); - ldb = ldb_module_get_ctx(ac->module); - if (!ares) { - return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); -diff --git a/source4/dsdb/samdb/ldb_modules/acl_util.c b/source4/dsdb/samdb/ldb_modules/acl_util.c -index 12f00fbff16..367c11d1ba9 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_util.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_util.c -@@ -298,7 +298,7 @@ uint32_t dsdb_request_sd_flags(struct ldb_request *req, bool *explicit) - - sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID); - if (sd_control != NULL && sd_control->data != NULL) { -- struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data; -+ struct ldb_sd_flags_control *sdctr = talloc_get_type_abort(sd_control->data, struct ldb_sd_flags_control); - - sd_flags = sdctr->secinfo_flags; - -diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c -index 5ef075f2037..317df9d3e0e 100644 ---- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c -+++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c -@@ -104,7 +104,7 @@ static int handle_verify_name_control(TALLOC_CTX *ctx, struct ldb_context *ldb, - * If we are a GC let's remove the control, - * if there is a specified GC check that is us. - */ -- struct ldb_verify_name_control *lvnc = (struct ldb_verify_name_control *)control->data; -+ struct ldb_verify_name_control *lvnc = talloc_get_type_abort(control->data, struct ldb_verify_name_control); - if (samdb_is_gc(ldb)) { - /* Because we can't easily talloc a struct ldb_dn*/ - struct ldb_dn **dn = talloc_array(ctx, struct ldb_dn *, 1); -diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c -index b308226a9f9..6a713b86736 100644 ---- a/source4/dsdb/samdb/ldb_modules/password_hash.c -+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c -@@ -4066,7 +4066,7 @@ static void ph_apply_controls(struct ph_context *ac) - ctrl = ldb_request_get_control(ac->req, - DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID); - if (ctrl != NULL) { -- ac->change = (struct dsdb_control_password_change *) ctrl->data; -+ ac->change = talloc_get_type_abort(ctrl->data, struct dsdb_control_password_change); - - /* Mark the "change" control as uncritical (done) */ - ctrl->critical = false; --- -2.25.1 \ No newline at end of file diff --git a/backport-0006-CVE-2023-0614.patch b/backport-0006-CVE-2023-0614.patch deleted file mode 100644 index f90a1d9a8e0a375fa5a0cda6f74325253cb9ff9d..0000000000000000000000000000000000000000 --- a/backport-0006-CVE-2023-0614.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 003c65be1c6d8f8ea853896a75b315ef8e98cfb3 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 27 Jan 2023 08:00:32 +1300 -Subject: [PATCH 04/34] CVE-2023-0614 s4-acl: Make some parameters const - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -[abartlet@samba.org Adapted to code without newer - acl_check_access_on_attribute_implicit_owner name] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_util.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_util.c b/source4/dsdb/samdb/ldb_modules/acl_util.c -index 367c11d1ba9..56aa4bd7531 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_util.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_util.c -@@ -97,8 +97,8 @@ int dsdb_module_check_access_on_dn(struct ldb_module *module, - - int acl_check_access_on_attribute(struct ldb_module *module, - TALLOC_CTX *mem_ctx, -- struct security_descriptor *sd, -- struct dom_sid *rp_sid, -+ const struct security_descriptor *sd, -+ const struct dom_sid *rp_sid, - uint32_t access_mask, - const struct dsdb_attribute *attr, - const struct dsdb_class *objectclass) --- -2.25.1 \ No newline at end of file diff --git a/backport-0007-CVE-2023-0614.patch b/backport-0007-CVE-2023-0614.patch deleted file mode 100644 index cc293a52c1855c6bab7f73e66871d849ccedef64..0000000000000000000000000000000000000000 --- a/backport-0007-CVE-2023-0614.patch +++ /dev/null @@ -1,72 +0,0 @@ -From b01d3ae3261264236504475a26c54ab45dd2175f Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_msg.c | 26 ++++++++++++++++++++++++++ - lib/ldb/include/ldb_module.h | 4 ++++ - 2 files changed, 30 insertions(+) - -diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c -index 9cd7998e21c..cbc7e32b2ba 100644 ---- a/lib/ldb/common/ldb_msg.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index 4c7c85a17f0..8481fd3991a 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0008-CVE-2023-0614.patch b/backport-0008-CVE-2023-0614.patch deleted file mode 100644 index a56265dcc82c0a4e4bc76cd5c7a4da57768a17a5..0000000000000000000000000000000000000000 --- a/backport-0008-CVE-2023-0614.patch +++ /dev/null @@ -1,140 +0,0 @@ -From c818c16912f5af248b91f0688c3e57012db89011 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 27 Jan 2023 08:29:33 +1300 -Subject: [PATCH 06/34] CVE-2023-0614 s4-acl: Use ldb functions for handling - inaccessible message elements - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 62 ++++------------------- - 1 file changed, 10 insertions(+), 52 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 16a1927183c..8814a816797 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -70,14 +70,6 @@ struct aclread_private { - struct ldb_val sd_cached_blob; - }; - --static void aclread_mark_inaccesslible(struct ldb_message_element *el) { -- el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE; --} -- --static bool aclread_is_inaccessible(struct ldb_message_element *el) { -- return el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE; --} -- - /* - * the object has a parent, so we have to check for visibility - * -@@ -557,11 +549,9 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - { - struct ldb_context *ldb; - struct aclread_context *ac; -- struct ldb_message *ret_msg; - struct ldb_message *msg; - int ret; -- size_t num_of_attrs = 0; -- unsigned int i, k = 0; -+ unsigned int i; - struct security_descriptor *sd = NULL; - struct dom_sid *sid = NULL; - TALLOC_CTX *tmp_ctx; -@@ -651,26 +641,26 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - msg->elements[i].name) == 0; - /* these attributes were added to perform access checks and must be removed */ - if (is_objectsid && ac->added_objectSid) { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } - if (is_instancetype && ac->added_instanceType) { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } - if (is_objectclass && ac->added_objectClass) { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } - if (is_sd && ac->added_nTSecurityDescriptor) { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } - - access_mask = get_attr_access_mask(attr, ac->sd_flags); - - if (access_mask == 0) { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } - -@@ -714,7 +704,7 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - return LDB_SUCCESS; - } - } else { -- aclread_mark_inaccesslible(&msg->elements[i]); -+ ldb_msg_element_mark_inaccessible(&msg->elements[i]); - } - } else if (ret != LDB_SUCCESS) { - ldb_debug_set(ldb, LDB_DEBUG_FATAL, -@@ -757,44 +747,12 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - } - } - -- for (i=0; i < msg->num_elements; i++) { -- if (!aclread_is_inaccessible(&msg->elements[i])) { -- num_of_attrs++; -- } -- } -- /*create a new message to return*/ -- ret_msg = ldb_msg_new(ac->req); -- ret_msg->dn = msg->dn; -- talloc_steal(ret_msg, msg->dn); -- ret_msg->num_elements = num_of_attrs; -- if (num_of_attrs > 0) { -- ret_msg->elements = talloc_array(ret_msg, -- struct ldb_message_element, -- num_of_attrs); -- if (ret_msg->elements == NULL) { -- return ldb_oom(ldb); -- } -- for (i=0; i < msg->num_elements; i++) { -- bool to_remove = aclread_is_inaccessible(&msg->elements[i]); -- if (!to_remove) { -- ret_msg->elements[k] = msg->elements[i]; -- talloc_steal(ret_msg->elements, msg->elements[i].name); -- talloc_steal(ret_msg->elements, msg->elements[i].values); -- k++; -- } -- } -- /* -- * This should not be needed, but some modules -- * may allocate values on the wrong context... -- */ -- talloc_steal(ret_msg->elements, msg); -- } else { -- ret_msg->elements = NULL; -- } -+ ldb_msg_remove_inaccessible(msg); -+ - talloc_free(tmp_ctx); - - ac->num_entries++; -- return ldb_module_send_entry(ac->req, ret_msg, ares->controls); -+ return ldb_module_send_entry(ac->req, msg, ares->controls); - case LDB_REPLY_REFERRAL: - return ldb_module_send_referral(ac->req, ares->referral); - case LDB_REPLY_DONE: --- -2.25.1 \ No newline at end of file diff --git a/backport-0009-CVE-2023-0614.patch b/backport-0009-CVE-2023-0614.patch deleted file mode 100644 index 8c5062529c407ca4c7cd74848a1db3fa831aa8a8..0000000000000000000000000000000000000000 --- a/backport-0009-CVE-2023-0614.patch +++ /dev/null @@ -1,409 +0,0 @@ -From e7445d18badee6c3b1bbee48c689eb2629c31681 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/tests/ldb_filter_attrs_test.c | 171 +++++++++++++------------- - 1 file changed, 86 insertions(+), 85 deletions(-) - -diff --git a/lib/ldb/tests/ldb_filter_attrs_test.c b/lib/ldb/tests/ldb_filter_attrs_test.c -index 7d555e0da2e..442d9c77ed2 100644 ---- a/lib/ldb/tests/ldb_filter_attrs_test.c -+++ b/lib/ldb/tests/ldb_filter_attrs_test.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -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 \ No newline at end of file diff --git a/backport-0010-CVE-2023-0614.patch b/backport-0010-CVE-2023-0614.patch deleted file mode 100644 index 4e79b61682f3de291aa1aa5daff7f700156ca1fd..0000000000000000000000000000000000000000 --- a/backport-0010-CVE-2023-0614.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 936bfcb6ef804d2224072f3770ca09fe2596ee1f Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/wscript | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/lib/ldb/wscript b/lib/ldb/wscript -index 60bb7cf48b3..c862229822d 100644 ---- a/lib/ldb/wscript -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0011-CVE-2023-0614.patch b/backport-0011-CVE-2023-0614.patch deleted file mode 100644 index 95423624ecd2d508281aa8a94d01469464481d46..0000000000000000000000000000000000000000 --- a/backport-0011-CVE-2023-0614.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 83217ce77381f8faa3cde948e15a36db234d3033 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_pack.c | 41 ++++++++++++++++++++++++++++++++++++ - lib/ldb/include/ldb_module.h | 4 ++++ - 2 files changed, 45 insertions(+) - -diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c -index e7dd364008a..028d96a619a 100644 ---- a/lib/ldb/common/ldb_pack.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index 8481fd3991a..8c7f33496fb 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0012-CVE-2023-0614.patch b/backport-0012-CVE-2023-0614.patch deleted file mode 100644 index 7861a1cc84f0d65ff33ae4523a288fede6c908fe..0000000000000000000000000000000000000000 --- a/backport-0012-CVE-2023-0614.patch +++ /dev/null @@ -1,62 +0,0 @@ -From a9b625bc8ab00b83b55bcd21ba0df48e73e4df29 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -[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 ---- - lib/ldb/common/ldb_msg.c | 16 ++++++++++++++++ - lib/ldb/include/ldb_private.h | 3 +++ - 2 files changed, 19 insertions(+) - -diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c -index cbc7e32b2ba..2ea2cce2e83 100644 ---- a/lib/ldb/common/ldb_msg.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h -index 4deb24691ca..338e71def6d 100644 ---- a/lib/ldb/include/ldb_private.h -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0013-CVE-2023-0614.patch b/backport-0013-CVE-2023-0614.patch deleted file mode 100644 index c0f961b16435be1b81b7669f207804eebfe10331..0000000000000000000000000000000000000000 --- a/backport-0013-CVE-2023-0614.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 8b7374780e3e7b67e51a1b54a09bf48d89fa9f26 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -[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 ---- - lib/ldb/common/ldb_pack.c | 6 +++--- - lib/ldb/include/ldb_private.h | 5 +++++ - 2 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c -index 028d96a619a..b0b0d64a5ba 100644 ---- a/lib/ldb/common/ldb_pack.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h -index 338e71def6d..ca43817d07a 100644 ---- a/lib/ldb/include/ldb_private.h -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0014-CVE-2023-0614.patch b/backport-0014-CVE-2023-0614.patch deleted file mode 100644 index ed63e9fd14318dedbffe2a78c44e8859e58ab677..0000000000000000000000000000000000000000 --- a/backport-0014-CVE-2023-0614.patch +++ /dev/null @@ -1,1224 +0,0 @@ -From 4f8b4ce403ff68ca26d33d7272276052829c96f7 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 3 Mar 2023 17:29:03 +1300 -Subject: [PATCH 12/34] CVE-2023-0614 ldb: Add function to filter message in - place - -At present this function is an exact duplicate of ldb_filter_attrs(), -but in the next commit we shall modify it to work in place, without the -need for the allocation of a second message. - -The test is a near duplicate of the existing test for -ldb_filter_attrs(). - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_pack.c | 143 +++ - lib/ldb/include/ldb_module.h | 10 + - .../tests/ldb_filter_attrs_in_place_test.c | 989 ++++++++++++++++++ - lib/ldb/wscript | 6 + - 4 files changed, 1148 insertions(+) - create mode 100644 lib/ldb/tests/ldb_filter_attrs_in_place_test.c - -diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c -index b0b0d64a5ba..f19ac73fa5e 100644 ---- a/lib/ldb/common/ldb_pack.c -+++ b/lib/ldb/common/ldb_pack.c -@@ -1262,6 +1262,149 @@ failed: - return -1; - } - -+/* -+ * filter the specified list of attributes from msg, -+ * adding requested attributes, and perhaps all for *, -+ * but not the DN to filtered_msg. -+ */ -+int ldb_filter_attrs_in_place(struct ldb_context *ldb, -+ const struct ldb_message *msg, -+ const char *const *attrs, -+ struct ldb_message *filtered_msg) -+{ -+ unsigned int i; -+ bool keep_all = false; -+ bool add_dn = false; -+ uint32_t num_elements; -+ uint32_t elements_size; -+ -+ if (attrs) { -+ /* check for special attrs */ -+ for (i = 0; attrs[i]; i++) { -+ int cmp = strcmp(attrs[i], "*"); -+ if (cmp == 0) { -+ keep_all = true; -+ break; -+ } -+ cmp = ldb_attr_cmp(attrs[i], "distinguishedName"); -+ if (cmp == 0) { -+ add_dn = true; -+ } -+ } -+ } else { -+ keep_all = true; -+ } -+ -+ if (keep_all) { -+ add_dn = true; -+ elements_size = msg->num_elements + 1; -+ -+ /* Shortcuts for the simple cases */ -+ } else if (add_dn && i == 1) { -+ if (ldb_msg_add_distinguished_name(filtered_msg) != 0) { -+ goto failed; -+ } -+ return 0; -+ } else if (i == 0) { -+ return 0; -+ -+ /* -+ * Otherwise we are copying at most as many elements as we -+ * have attributes -+ */ -+ } else { -+ elements_size = i; -+ } -+ -+ filtered_msg->elements = talloc_array(filtered_msg, -+ struct ldb_message_element, -+ elements_size); -+ if (filtered_msg->elements == NULL) goto failed; -+ -+ num_elements = 0; -+ -+ for (i = 0; i < msg->num_elements; i++) { -+ struct ldb_message_element *el = &msg->elements[i]; -+ -+ /* -+ * el2 is assigned after the Pigeonhole principle -+ * check below for clarity -+ */ -+ struct ldb_message_element *el2 = NULL; -+ unsigned int j; -+ -+ if (keep_all == false) { -+ bool found = false; -+ for (j = 0; attrs[j]; j++) { -+ int cmp = ldb_attr_cmp(el->name, attrs[j]); -+ if (cmp == 0) { -+ found = true; -+ break; -+ } -+ } -+ if (found == false) { -+ continue; -+ } -+ } -+ -+ /* -+ * Pigeonhole principle: we can't have more elements -+ * than the number of attributes if they are unique in -+ * the DB. -+ */ -+ if (num_elements >= elements_size) { -+ goto failed; -+ } -+ -+ el2 = &filtered_msg->elements[num_elements]; -+ -+ *el2 = *el; -+ el2->name = talloc_strdup(filtered_msg->elements, -+ el->name); -+ if (el2->name == NULL) { -+ goto failed; -+ } -+ el2->values = talloc_array(filtered_msg->elements, -+ struct ldb_val, el->num_values); -+ if (el2->values == NULL) { -+ goto failed; -+ } -+ for (j=0;jnum_values;j++) { -+ el2->values[j] = ldb_val_dup(el2->values, &el->values[j]); -+ if (el2->values[j].data == NULL && el->values[j].length != 0) { -+ goto failed; -+ } -+ } -+ num_elements++; -+ } -+ -+ filtered_msg->num_elements = num_elements; -+ -+ if (add_dn) { -+ if (ldb_msg_add_distinguished_name(filtered_msg) != 0) { -+ goto failed; -+ } -+ } -+ -+ if (filtered_msg->num_elements > 0) { -+ filtered_msg->elements -+ = talloc_realloc(filtered_msg, -+ filtered_msg->elements, -+ struct ldb_message_element, -+ filtered_msg->num_elements); -+ if (filtered_msg->elements == NULL) { -+ goto failed; -+ } -+ } else { -+ TALLOC_FREE(filtered_msg->elements); -+ } -+ -+ return 0; -+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) - { -diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index 8c7f33496fb..105093cf38c 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/include/ldb_module.h -@@ -543,6 +543,16 @@ int ldb_filter_attrs(struct ldb_context *ldb, - const char *const *attrs, - struct ldb_message *filtered_msg); - -+/* -+ * filter the specified list of attributes from msg, -+ * adding requested attributes, and perhaps all for *, -+ * but not the DN to filtered_msg. -+ */ -+int ldb_filter_attrs_in_place(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); - -diff --git a/lib/ldb/tests/ldb_filter_attrs_in_place_test.c b/lib/ldb/tests/ldb_filter_attrs_in_place_test.c -new file mode 100644 -index 00000000000..bef961f8f9c ---- /dev/null -+++ b/lib/ldb/tests/ldb_filter_attrs_in_place_test.c -@@ -0,0 +1,989 @@ -+/* -+ * Tests exercising ldb_filter_attrs_in_place(). -+ * -+ * -+ * Copyright (C) Catalyst.NET Ltd 2017 -+ * Copyright (C) Andrew Bartlett 2019 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+/* -+ * from cmocka.c: -+ * These headers or their equivalents should be included prior to -+ * including -+ * this header file. -+ * -+ * #include -+ * #include -+ * #include -+ * -+ * This allows test applications to use custom definitions of C standard -+ * library functions and types. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../include/ldb.h" -+#include "../include/ldb_module.h" -+ -+struct ldbtest_ctx { -+ struct tevent_context *ev; -+ struct ldb_context *ldb; -+}; -+ -+/* -+ * NOTE WELL: -+ * -+ * This test checks the current behaviour of the function, however -+ * this is not in a public ABI and many of the tested behaviours are -+ * not ideal. If the behaviour is deliberatly improved, this test -+ * should be updated without worry to the new better behaviour. -+ * -+ * In particular the test is particularly to ensure the current -+ * behaviour is memory-safe. -+ */ -+ -+static int setup(void **state) -+{ -+ struct ldbtest_ctx *test_ctx; -+ -+ test_ctx = talloc_zero(NULL, struct ldbtest_ctx); -+ assert_non_null(test_ctx); -+ -+ test_ctx->ev = tevent_context_init(test_ctx); -+ assert_non_null(test_ctx->ev); -+ -+ test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); -+ assert_non_null(test_ctx->ldb); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int teardown(void **state) -+{ -+ talloc_free(*state); -+ return 0; -+} -+ -+ -+/* -+ * Test against a record with only one attribute, matching the one in -+ * the list -+ */ -+static void test_filter_attrs_one_attr_matched(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"foo", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not read or modify -+ * filtered_msg.dn in this case -+ */ -+ assert_null(filtered_msg->dn); -+ assert_int_equal(filtered_msg->num_elements, 1); -+ 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, -+ strlen(value)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ value, strlen(value)); -+} -+ -+/* -+ * Test against a record with only one attribute, matching the one of -+ * the multiple attributes in the list -+ */ -+static void test_filter_attrs_one_attr_matched_of_many(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"foo", "bar", "baz", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not read or modify -+ * filtered_msg.dn in this case -+ */ -+ assert_null(filtered_msg->dn); -+ assert_int_equal(filtered_msg->num_elements, 1); -+ 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, -+ strlen(value)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ value, strlen(value)); -+} -+ -+/* -+ * Test against a record with only one attribute, matching both -+ * attributes in the list -+ */ -+static void test_filter_attrs_two_attr_matched_attrs(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ /* deliberatly the other order */ -+ const char *attrs[] = {"bar", "foo", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 2); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not read or modify -+ * filtered_msg.dn in this case -+ */ -+ assert_null(filtered_msg->dn); -+ -+ /* Assert that DB order is preserved */ -+ 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, -+ strlen(value1)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ 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, -+ strlen(value2)); -+ assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ value2, strlen(value2)); -+} -+ -+/* -+ * Test against a record with two attributes, only of which is in -+ * the list -+ */ -+static void test_filter_attrs_two_attr_matched_one_attr(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ /* deliberatly the other order */ -+ const char *attrs[] = {"bar", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 1); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not read or modify -+ * filtered_msg.dn in this case -+ */ -+ assert_null(filtered_msg->dn); -+ -+ /* Assert that DB order is preserved */ -+ 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, -+ strlen(value2)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ value2, strlen(value2)); -+} -+ -+/* -+ * Test against a record with two attributes, both matching the one -+ * specified attribute in the list (a corrupt record) -+ */ -+static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ /* deliberatly the other order */ -+ const char *attrs[] = {"bar", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ -+ /* This should fail the pidgenhole test */ -+ assert_int_equal(ret, -1); -+ assert_null(filtered_msg->elements); -+} -+ -+/* -+ * Test against a record with two attributes, both matching the one -+ * specified attribute in the list (a corrupt record) -+ */ -+static void test_filter_attrs_two_dup_attr_matched_dup(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"bar", "bar", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ -+ /* This does not fail the pidgenhole test */ -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_int_equal(filtered_msg->num_elements, 2); -+ -+ /* Assert that DB order is preserved */ -+ 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, -+ strlen(value1)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ 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, -+ strlen(value2)); -+ assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ value2, strlen(value2)); -+} -+ -+/* -+ * Test against a record with two attributes, both matching one of the -+ * specified attributes in the list (a corrupt record) -+ */ -+static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"bar", "foo", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ -+ /* This does not fail the pidgenhole test */ -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_int_equal(filtered_msg->num_elements, 2); -+ -+ /* Assert that DB order is preserved */ -+ 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, -+ strlen(value1)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ 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, -+ strlen(value2)); -+ assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ value2, strlen(value2)); -+} -+ -+/* -+ * Test against a record with two attributes against * (but not the -+ * other named attribute) (a corrupt record) -+ */ -+static void test_filter_attrs_two_dup_attr_matched_star(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"*", "foo", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ -+ /* foo and bar are the other order to in attrs */ -+ struct ldb_message_element elements[] = { -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ /* Needed as * implies distinguishedName */ -+ filtered_msg->dn = in.dn; -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ -+ /* This does not fail the pidgenhole test */ -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_int_equal(filtered_msg->num_elements, 3); -+ -+ /* Assert that DB order is preserved */ -+ 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, -+ strlen(value1)); -+ assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ 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, -+ strlen(value2)); -+ assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ value2, strlen(value2)); -+ /* -+ * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -+ * in this case -+ */ -+ assert_ptr_equal(filtered_msg->dn, in.dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "distinguishedName", -+ NULL), -+ ldb_dn_get_linearized(in.dn)); -+} -+ -+/* -+ * Test against a record with only one attribute, matching the * in -+ * the list -+ */ -+static void test_filter_attrs_one_attr_matched_star(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"*", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ /* Needed as * implies distinguishedName */ -+ filtered_msg->dn = in.dn; -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 2); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -+ * in this case -+ */ -+ assert_ptr_equal(filtered_msg->dn, in.dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "distinguishedName", -+ NULL), -+ ldb_dn_get_linearized(in.dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "foo", -+ NULL), -+ value); -+} -+ -+/* -+ * Test against a record with two attributes, matching the * in -+ * the list -+ */ -+static void test_filter_attrs_two_attr_matched_star(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"*", NULL}; -+ -+ char value1[] = "The value.......end"; -+ char value2[] = "The value..MUST.end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value1, -+ .length = strlen(value1) -+ }; -+ struct ldb_val value_2 = { -+ .data = (uint8_t *)value2, -+ .length = strlen(value2) -+ }; -+ struct ldb_message_element elements[] = { -+ { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }, -+ { -+ .name = "bar", -+ .num_values = 1, -+ .values = &value_2 -+ } -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 2, -+ .elements = elements, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ /* Needed as * implies distinguishedName */ -+ filtered_msg->dn = in.dn; -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 3); -+ -+ /* -+ * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -+ * in this case -+ */ -+ assert_ptr_equal(filtered_msg->dn, in.dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "distinguishedName", -+ NULL), -+ ldb_dn_get_linearized(in.dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "foo", -+ NULL), -+ value1); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "bar", -+ NULL), -+ value2); -+} -+ -+/* -+ * Test against a record with only one attribute, matching the * in -+ * the list, but without the DN being pre-filled. Fails due to need -+ * to contstruct the distinguishedName -+ */ -+static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"*", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, -1); -+ assert_null(filtered_msg->elements); -+} -+ -+/* -+ * Test against a record with only one attribute, matching the * in -+ * the list plus requsesting distinguishedName -+ */ -+static void test_filter_attrs_one_attr_matched_star_dn(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"*", "distinguishedName", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ /* Needed for distinguishedName */ -+ filtered_msg->dn = in.dn; -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 2); -+ -+ /* show that ldb_filter_attrs_in_place does not modify in.dn */ -+ assert_ptr_equal(filtered_msg->dn, in.dn); -+ -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "distinguishedName", -+ NULL), -+ ldb_dn_get_linearized(in.dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ "foo", -+ NULL), -+ value); -+} -+ -+/* -+ * Test against a record with only one attribute, but returning -+ * distinguishedName from the list (only) -+ */ -+static void test_filter_attrs_one_attr_matched_dn(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {"distinguishedName", NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ /* Needed for distinguishedName */ -+ filtered_msg->dn = in.dn; -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 1); -+ -+ /* show that ldb_filter_attrs_in_place does not modify in.dn */ -+ assert_ptr_equal(filtered_msg->dn, in.dn); -+ assert_string_equal(filtered_msg->elements[0].name, "distinguishedName"); -+ assert_int_equal(filtered_msg->elements[0].num_values, 1); -+ assert_string_equal(filtered_msg->elements[0].values[0].data, -+ ldb_dn_get_linearized(in.dn)); -+} -+ -+/* -+ * Test against a record with only one attribute, not matching the -+ * empty attribute list -+ */ -+static void test_filter_attrs_one_attr_empty_list(void **state) -+{ -+ struct ldbtest_ctx *ctx = *state; -+ int ret; -+ -+ struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ -+ const char *attrs[] = {NULL}; -+ -+ char value[] = "The value.......end"; -+ struct ldb_val value_1 = { -+ .data = (uint8_t *)value, -+ .length = strlen(value) -+ }; -+ struct ldb_message_element element_1 = { -+ .name = "foo", -+ .num_values = 1, -+ .values = &value_1 -+ }; -+ struct ldb_message in = { -+ .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -+ .num_elements = 1, -+ .elements = &element_1, -+ }; -+ -+ assert_non_null(in.dn); -+ -+ ret = ldb_filter_attrs_in_place(ctx->ldb, -+ &in, -+ attrs, -+ filtered_msg); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_non_null(filtered_msg); -+ assert_int_equal(filtered_msg->num_elements, 0); -+ assert_null(filtered_msg->dn); -+ assert_null(filtered_msg->elements); -+} -+ -+int main(int argc, const char **argv) -+{ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched_of_many, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_attr_matched_attrs, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_attr_matched_one_attr, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_dup_attr_matched_one_attr, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_dup_attr_matched_dup, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_dup_attr_matched_one_of_two, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_dup_attr_matched_star, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched_star, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_two_attr_matched_star, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched_star_no_dn, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched_star_dn, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_matched_dn, -+ setup, -+ teardown), -+ cmocka_unit_test_setup_teardown( -+ test_filter_attrs_one_attr_empty_list, -+ setup, -+ teardown), -+ }; -+ -+ return cmocka_run_group_tests(tests, NULL, NULL); -+} -diff --git a/lib/ldb/wscript b/lib/ldb/wscript -index c862229822d..7e02309c1d5 100644 ---- a/lib/ldb/wscript -+++ b/lib/ldb/wscript -@@ -518,6 +518,11 @@ def build(bld): - deps='cmocka ldb ldb_tdb_err_map', - install=False) - -+ bld.SAMBA_BINARY('ldb_filter_attrs_in_place_test', -+ source='tests/ldb_filter_attrs_in_place_test.c', -+ deps='cmocka ldb ldb_tdb_err_map', -+ install=False) -+ - bld.SAMBA_BINARY('ldb_key_value_sub_txn_tdb_test', - bld.SUBDIR('ldb_key_value', - '''ldb_kv_search.c -@@ -638,6 +643,7 @@ def test(ctx): - # 'ldb_key_value_sub_txn_tdb_test' - 'ldb_parse_test', - 'ldb_filter_attrs_test', -+ 'ldb_filter_attrs_in_place_test', - ] - - # if LIB_LDAP and LIB_LBER defined, then we can test ldb_ldap backend --- -2.25.1 \ No newline at end of file diff --git a/backport-0015-CVE-2023-0614.patch b/backport-0015-CVE-2023-0614.patch deleted file mode 100644 index 5e885886b975b2be51796cb2273e09e997b2caa8..0000000000000000000000000000000000000000 --- a/backport-0015-CVE-2023-0614.patch +++ /dev/null @@ -1,1275 +0,0 @@ -From fd0f06e43f03bc8b8c5b4a978a119e4401c02160 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 3 Mar 2023 17:30:19 +1300 -Subject: [PATCH 13/34] CVE-2023-0614 ldb: Make ldb_filter_attrs_in_place() - work in place - -ldb_filter_attrs() previously did too much. Now its replacement, -ldb_filter_attrs_in_place(), only does the actual filtering, while -taking ownership of each element's values is handled in a separate -function, ldb_msg_elements_take_ownership(). - -Also, ldb_filter_attrs_in_place() no longer adds the distinguishedName -to the message if it is missing. That is handled in another function, -ldb_msg_add_distinguished_name(). - -As we're now modifying the original message rather than copying it into -a new one, we no longer need the filtered_msg parameter. - -We adapt a test, based on ldb_filter_attrs_test, to exercise the new -function. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_pack.c | 129 +--- - lib/ldb/include/ldb_module.h | 11 +- - .../tests/ldb_filter_attrs_in_place_test.c | 609 ++++++++---------- - 3 files changed, 307 insertions(+), 442 deletions(-) - -diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c -index f19ac73fa5e..28b9a8dfe07 100644 ---- a/lib/ldb/common/ldb_pack.c -+++ b/lib/ldb/common/ldb_pack.c -@@ -1264,19 +1264,16 @@ failed: - - /* - * 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 *. -+ * Unlike ldb_filter_attrs(), the DN will not be added -+ * if it is missing. - */ --int ldb_filter_attrs_in_place(struct ldb_context *ldb, -- const struct ldb_message *msg, -- const char *const *attrs, -- struct ldb_message *filtered_msg) -+int ldb_filter_attrs_in_place(struct ldb_message *msg, -+ const char *const *attrs) - { -- unsigned int i; -+ unsigned int i = 0; - bool keep_all = false; -- bool add_dn = false; -- uint32_t num_elements; -- uint32_t elements_size; -+ unsigned int num_del = 0; - - if (attrs) { - /* check for special attrs */ -@@ -1286,123 +1283,41 @@ int ldb_filter_attrs_in_place(struct ldb_context *ldb, - keep_all = true; - break; - } -- cmp = ldb_attr_cmp(attrs[i], "distinguishedName"); -- if (cmp == 0) { -- add_dn = true; -- } - } -- } else { -- keep_all = true; -- } -- -- if (keep_all) { -- add_dn = true; -- elements_size = msg->num_elements + 1; -- -- /* Shortcuts for the simple cases */ -- } else if (add_dn && i == 1) { -- if (ldb_msg_add_distinguished_name(filtered_msg) != 0) { -- goto failed; -+ if (!keep_all && i == 0) { -+ msg->num_elements = 0; -+ return LDB_SUCCESS; - } -- return 0; -- } else if (i == 0) { -- return 0; -- -- /* -- * Otherwise we are copying at most as many elements as we -- * have attributes -- */ - } else { -- elements_size = i; -+ keep_all = true; - } - -- filtered_msg->elements = talloc_array(filtered_msg, -- struct ldb_message_element, -- elements_size); -- if (filtered_msg->elements == NULL) goto failed; -- -- num_elements = 0; -- - for (i = 0; i < msg->num_elements; i++) { -- struct ldb_message_element *el = &msg->elements[i]; -- -- /* -- * el2 is assigned after the Pigeonhole principle -- * check below for clarity -- */ -- struct ldb_message_element *el2 = NULL; -+ bool found = false; - unsigned int j; - -- if (keep_all == false) { -- bool found = false; -+ if (keep_all) { -+ found = true; -+ } else { - for (j = 0; attrs[j]; j++) { -- int cmp = ldb_attr_cmp(el->name, attrs[j]); -+ int cmp = ldb_attr_cmp(msg->elements[i].name, attrs[j]); - if (cmp == 0) { - found = true; - break; - } - } -- if (found == false) { -- continue; -- } -- } -- -- /* -- * Pigeonhole principle: we can't have more elements -- * than the number of attributes if they are unique in -- * the DB. -- */ -- if (num_elements >= elements_size) { -- goto failed; - } - -- el2 = &filtered_msg->elements[num_elements]; -- -- *el2 = *el; -- el2->name = talloc_strdup(filtered_msg->elements, -- el->name); -- if (el2->name == NULL) { -- goto failed; -- } -- el2->values = talloc_array(filtered_msg->elements, -- struct ldb_val, el->num_values); -- if (el2->values == NULL) { -- goto failed; -+ if (!found) { -+ ++num_del; -+ } else if (num_del != 0) { -+ msg->elements[i - num_del] = msg->elements[i]; - } -- for (j=0;jnum_values;j++) { -- el2->values[j] = ldb_val_dup(el2->values, &el->values[j]); -- if (el2->values[j].data == NULL && el->values[j].length != 0) { -- goto failed; -- } -- } -- num_elements++; - } - -- filtered_msg->num_elements = num_elements; -- -- if (add_dn) { -- if (ldb_msg_add_distinguished_name(filtered_msg) != 0) { -- goto failed; -- } -- } -+ msg->num_elements -= num_del; - -- if (filtered_msg->num_elements > 0) { -- filtered_msg->elements -- = talloc_realloc(filtered_msg, -- filtered_msg->elements, -- struct ldb_message_element, -- filtered_msg->num_elements); -- if (filtered_msg->elements == NULL) { -- goto failed; -- } -- } else { -- TALLOC_FREE(filtered_msg->elements); -- } -- -- return 0; --failed: -- TALLOC_FREE(filtered_msg->elements); -- return -1; -+ return LDB_SUCCESS; - } - - /* Have an unpacked ldb message take talloc ownership of its elements. */ -diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index 105093cf38c..4ae381ba5be 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/include/ldb_module.h -@@ -545,13 +545,12 @@ int ldb_filter_attrs(struct ldb_context *ldb, - - /* - * 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 *. -+ * Unlike ldb_filter_attrs(), the DN will not be added -+ * if it is missing. - */ --int ldb_filter_attrs_in_place(struct ldb_context *ldb, -- const struct ldb_message *msg, -- const char *const *attrs, -- struct ldb_message *filtered_msg); -+int ldb_filter_attrs_in_place(struct ldb_message *msg, -+ const char *const *attrs); - - /* Have an unpacked ldb message take talloc ownership of its elements. */ - int ldb_msg_elements_take_ownership(struct ldb_message *msg); -diff --git a/lib/ldb/tests/ldb_filter_attrs_in_place_test.c b/lib/ldb/tests/ldb_filter_attrs_in_place_test.c -index bef961f8f9c..da333c73c99 100644 ---- a/lib/ldb/tests/ldb_filter_attrs_in_place_test.c -+++ b/lib/ldb/tests/ldb_filter_attrs_in_place_test.c -@@ -83,17 +83,41 @@ static int teardown(void **state) - return 0; - } - -+static void msg_add_dn(struct ldb_message *msg) -+{ -+ const char *dn_attr = "distinguishedName"; -+ char *dn = NULL; -+ int ret; -+ -+ assert_null(ldb_msg_find_element(msg, dn_attr)); -+ -+ assert_non_null(msg->dn); -+ dn = ldb_dn_alloc_linearized(msg, msg->dn); -+ assert_non_null(dn); -+ -+ /* -+ * The message's elements must be talloc allocated to call -+ * ldb_msg_add_steal_string(). -+ */ -+ msg->elements = talloc_memdup(msg, -+ msg->elements, -+ msg->num_elements * sizeof(msg->elements[0])); -+ assert_non_null(msg->elements); -+ -+ ret = ldb_msg_add_steal_string(msg, dn_attr, dn); -+ assert_int_equal(ret, LDB_SUCCESS); -+} - - /* - * Test against a record with only one attribute, matching the one in - * the list - */ --static void test_filter_attrs_one_attr_matched(void **state) -+static void test_filter_attrs_in_place_one_attr_matched(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"foo", NULL}; - -@@ -107,32 +131,25 @@ static void test_filter_attrs_one_attr_matched(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); - -- /* -- * assert the ldb_filter_attrs_in_place does not read or modify -- * filtered_msg.dn in this case -- */ -- assert_null(filtered_msg->dn); -- assert_int_equal(filtered_msg->num_elements, 1); -- 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, -+ assert_non_null(msg->dn); -+ assert_int_equal(msg->num_elements, 1); -+ assert_string_equal(msg->elements[0].name, "foo"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - value, strlen(value)); - } - -@@ -140,12 +157,12 @@ static void test_filter_attrs_one_attr_matched(void **state) - * Test against a record with only one attribute, matching the one of - * the multiple attributes in the list - */ --static void test_filter_attrs_one_attr_matched_of_many(void **state) -+static void test_filter_attrs_in_place_one_attr_matched_of_many(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"foo", "bar", "baz", NULL}; - -@@ -159,32 +176,25 @@ static void test_filter_attrs_one_attr_matched_of_many(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); - -- /* -- * assert the ldb_filter_attrs_in_place does not read or modify -- * filtered_msg.dn in this case -- */ -- assert_null(filtered_msg->dn); -- assert_int_equal(filtered_msg->num_elements, 1); -- 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, -+ assert_non_null(msg->dn); -+ assert_int_equal(msg->num_elements, 1); -+ assert_string_equal(msg->elements[0].name, "foo"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - value, strlen(value)); - } - -@@ -192,12 +202,12 @@ static void test_filter_attrs_one_attr_matched_of_many(void **state) - * Test against a record with only one attribute, matching both - * attributes in the list - */ --static void test_filter_attrs_two_attr_matched_attrs(void **state) -+static void test_filter_attrs_in_place_two_attr_matched_attrs(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - /* deliberatly the other order */ - const char *attrs[] = {"bar", "foo", NULL}; -@@ -226,40 +236,33 @@ static void test_filter_attrs_two_attr_matched_attrs(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 2); -+ assert_int_equal(msg->num_elements, 2); - -- /* -- * assert the ldb_filter_attrs_in_place does not read or modify -- * filtered_msg.dn in this case -- */ -- assert_null(filtered_msg->dn); -+ assert_non_null(msg->dn); - - /* Assert that DB order is preserved */ -- 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, -+ assert_string_equal(msg->elements[0].name, "foo"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value1)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - 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, -+ assert_string_equal(msg->elements[1].name, "bar"); -+ assert_int_equal(msg->elements[1].num_values, 1); -+ assert_int_equal(msg->elements[1].values[0].length, - strlen(value2)); -- assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ assert_memory_equal(msg->elements[1].values[0].data, - value2, strlen(value2)); - } - -@@ -267,14 +270,13 @@ static void test_filter_attrs_two_attr_matched_attrs(void **state) - * Test against a record with two attributes, only of which is in - * the list - */ --static void test_filter_attrs_two_attr_matched_one_attr(void **state) -+static void test_filter_attrs_in_place_two_attr_matched_one_attr(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - -- /* deliberatly the other order */ - const char *attrs[] = {"bar", NULL}; - - char value1[] = "The value.......end"; -@@ -288,7 +290,6 @@ static void test_filter_attrs_two_attr_matched_one_attr(void **state) - .length = strlen(value2) - }; - -- /* foo and bar are the other order to in attrs */ - struct ldb_message_element elements[] = { - { - .name = "foo", -@@ -301,34 +302,27 @@ static void test_filter_attrs_two_attr_matched_one_attr(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 1); -+ assert_int_equal(msg->num_elements, 1); - -- /* -- * assert the ldb_filter_attrs_in_place does not read or modify -- * filtered_msg.dn in this case -- */ -- assert_null(filtered_msg->dn); -+ assert_non_null(msg->dn); - - /* Assert that DB order is preserved */ -- 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, -+ assert_string_equal(msg->elements[0].name, "bar"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value2)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - value2, strlen(value2)); - } - -@@ -336,14 +330,13 @@ static void test_filter_attrs_two_attr_matched_one_attr(void **state) - * Test against a record with two attributes, both matching the one - * specified attribute in the list (a corrupt record) - */ --static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) -+static void test_filter_attrs_in_place_two_dup_attr_matched_one_attr(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - -- /* deliberatly the other order */ - const char *attrs[] = {"bar", NULL}; - - char value1[] = "The value.......end"; -@@ -357,7 +350,6 @@ static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) - .length = strlen(value2) - }; - -- /* foo and bar are the other order to in attrs */ - struct ldb_message_element elements[] = { - { - .name = "bar", -@@ -370,34 +362,49 @@ static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; -+ -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ /* Both elements match the filter */ -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_int_equal(msg->num_elements, 2); -+ -+ assert_non_null(msg->dn); - -- /* This should fail the pidgenhole test */ -- assert_int_equal(ret, -1); -- assert_null(filtered_msg->elements); -+ /* Assert that DB order is preserved */ -+ assert_string_equal(msg->elements[0].name, "bar"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, -+ strlen(value1)); -+ assert_memory_equal(msg->elements[0].values[0].data, -+ value1, strlen(value1)); -+ -+ assert_string_equal(msg->elements[1].name, "bar"); -+ assert_int_equal(msg->elements[1].num_values, 1); -+ assert_int_equal(msg->elements[1].values[0].length, -+ strlen(value2)); -+ assert_memory_equal(msg->elements[1].values[0].data, -+ value2, strlen(value2)); - } - - /* - * Test against a record with two attributes, both matching the one - * specified attribute in the list (a corrupt record) - */ --static void test_filter_attrs_two_dup_attr_matched_dup(void **state) -+static void test_filter_attrs_in_place_two_dup_attr_matched_dup(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"bar", "bar", NULL}; - -@@ -412,7 +419,6 @@ static void test_filter_attrs_two_dup_attr_matched_dup(void **state) - .length = strlen(value2) - }; - -- /* foo and bar are the other order to in attrs */ - struct ldb_message_element elements[] = { - { - .name = "bar", -@@ -425,35 +431,33 @@ static void test_filter_attrs_two_dup_attr_matched_dup(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; -+ -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - - /* This does not fail the pidgenhole test */ - assert_int_equal(ret, LDB_SUCCESS); -- assert_int_equal(filtered_msg->num_elements, 2); -+ assert_int_equal(msg->num_elements, 2); - - /* Assert that DB order is preserved */ -- 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, -+ assert_string_equal(msg->elements[0].name, "bar"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value1)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - 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, -+ assert_string_equal(msg->elements[1].name, "bar"); -+ assert_int_equal(msg->elements[1].num_values, 1); -+ assert_int_equal(msg->elements[1].values[0].length, - strlen(value2)); -- assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ assert_memory_equal(msg->elements[1].values[0].data, - value2, strlen(value2)); - } - -@@ -461,12 +465,12 @@ static void test_filter_attrs_two_dup_attr_matched_dup(void **state) - * Test against a record with two attributes, both matching one of the - * specified attributes in the list (a corrupt record) - */ --static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) -+static void test_filter_attrs_in_place_two_dup_attr_matched_one_of_two(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"bar", "foo", NULL}; - -@@ -481,7 +485,6 @@ static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) - .length = strlen(value2) - }; - -- /* foo and bar are the other order to in attrs */ - struct ldb_message_element elements[] = { - { - .name = "bar", -@@ -494,35 +497,33 @@ static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); -+ -+ ret = ldb_filter_attrs_in_place(msg, attrs); - - /* This does not fail the pidgenhole test */ - assert_int_equal(ret, LDB_SUCCESS); -- assert_int_equal(filtered_msg->num_elements, 2); -+ assert_int_equal(msg->num_elements, 2); - - /* Assert that DB order is preserved */ -- 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, -+ assert_string_equal(msg->elements[0].name, "bar"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value1)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - 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, -+ assert_string_equal(msg->elements[1].name, "bar"); -+ assert_int_equal(msg->elements[1].num_values, 1); -+ assert_int_equal(msg->elements[1].values[0].length, - strlen(value2)); -- assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ assert_memory_equal(msg->elements[1].values[0].data, - value2, strlen(value2)); - } - -@@ -530,12 +531,12 @@ static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) - * Test against a record with two attributes against * (but not the - * other named attribute) (a corrupt record) - */ --static void test_filter_attrs_two_dup_attr_matched_star(void **state) -+static void test_filter_attrs_in_place_two_dup_attr_matched_star(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"*", "foo", NULL}; - -@@ -550,7 +551,6 @@ static void test_filter_attrs_two_dup_attr_matched_star(void **state) - .length = strlen(value2) - }; - -- /* foo and bar are the other order to in attrs */ - struct ldb_message_element elements[] = { - { - .name = "bar", -@@ -563,60 +563,52 @@ static void test_filter_attrs_two_dup_attr_matched_star(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; - -- /* Needed as * implies distinguishedName */ -- filtered_msg->dn = in.dn; -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - - /* This does not fail the pidgenhole test */ - assert_int_equal(ret, LDB_SUCCESS); -- assert_int_equal(filtered_msg->num_elements, 3); -+ assert_int_equal(msg->num_elements, 3); - - /* Assert that DB order is preserved */ -- 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, -+ assert_string_equal(msg->elements[0].name, "bar"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_int_equal(msg->elements[0].values[0].length, - strlen(value1)); -- assert_memory_equal(filtered_msg->elements[0].values[0].data, -+ assert_memory_equal(msg->elements[0].values[0].data, - 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, -+ assert_string_equal(msg->elements[1].name, "bar"); -+ assert_int_equal(msg->elements[1].num_values, 1); -+ assert_int_equal(msg->elements[1].values[0].length, - strlen(value2)); -- assert_memory_equal(filtered_msg->elements[1].values[0].data, -+ assert_memory_equal(msg->elements[1].values[0].data, - value2, strlen(value2)); -- /* -- * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -- * in this case -- */ -- assert_ptr_equal(filtered_msg->dn, in.dn); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ -+ assert_non_null(msg->dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "distinguishedName", - NULL), -- ldb_dn_get_linearized(in.dn)); -+ ldb_dn_get_linearized(msg->dn)); - } - - /* - * Test against a record with only one attribute, matching the * in - * the list - */ --static void test_filter_attrs_one_attr_matched_star(void **state) -+static void test_filter_attrs_in_place_one_attr_matched_star(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"*", NULL}; - -@@ -630,35 +622,25 @@ static void test_filter_attrs_one_attr_matched_star(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; - -- /* Needed as * implies distinguishedName */ -- filtered_msg->dn = in.dn; -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 2); -+ assert_int_equal(msg->num_elements, 2); - -- /* -- * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -- * in this case -- */ -- assert_ptr_equal(filtered_msg->dn, in.dn); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ assert_non_null(msg->dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "distinguishedName", - NULL), -- ldb_dn_get_linearized(in.dn)); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ ldb_dn_get_linearized(msg->dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "foo", - NULL), - value); -@@ -668,12 +650,12 @@ static void test_filter_attrs_one_attr_matched_star(void **state) - * Test against a record with two attributes, matching the * in - * the list - */ --static void test_filter_attrs_two_attr_matched_star(void **state) -+static void test_filter_attrs_in_place_two_attr_matched_star(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"*", NULL}; - -@@ -699,39 +681,29 @@ static void test_filter_attrs_two_attr_matched_star(void **state) - .values = &value_2 - } - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 2, -- .elements = elements, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 2; -+ msg->elements = elements; - -- /* Needed as * implies distinguishedName */ -- filtered_msg->dn = in.dn; -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 3); -+ assert_int_equal(msg->num_elements, 3); - -- /* -- * assert the ldb_filter_attrs_in_place does not modify filtered_msg.dn -- * in this case -- */ -- assert_ptr_equal(filtered_msg->dn, in.dn); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ assert_non_null(msg->dn); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "distinguishedName", - NULL), -- ldb_dn_get_linearized(in.dn)); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ ldb_dn_get_linearized(msg->dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "foo", - NULL), - value1); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "bar", - NULL), - value2); -@@ -739,15 +711,15 @@ static void test_filter_attrs_two_attr_matched_star(void **state) - - /* - * Test against a record with only one attribute, matching the * in -- * the list, but without the DN being pre-filled. Fails due to need -- * to contstruct the distinguishedName -+ * the list, but without the DN being pre-filled. Succeeds, but the -+ * distinguishedName is not added. - */ --static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) -+static void test_filter_attrs_in_place_one_attr_matched_star_no_dn(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"*", NULL}; - -@@ -761,32 +733,29 @@ static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = NULL; -+ msg->num_elements = 1; -+ msg->elements = &element_1; -+ -+ assert_null(msg->dn); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -- assert_int_equal(ret, -1); -- assert_null(filtered_msg->elements); -+ ret = ldb_filter_attrs_in_place(msg, attrs); -+ assert_int_equal(ret, LDB_SUCCESS); -+ assert_int_equal(msg->num_elements, 1); - } - - /* - * Test against a record with only one attribute, matching the * in - * the list plus requsesting distinguishedName - */ --static void test_filter_attrs_one_attr_matched_star_dn(void **state) -+static void test_filter_attrs_in_place_one_attr_matched_star_dn(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"*", "distinguishedName", NULL}; - -@@ -800,33 +769,26 @@ static void test_filter_attrs_one_attr_matched_star_dn(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; - -- /* Needed for distinguishedName */ -- filtered_msg->dn = in.dn; -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 2); -+ assert_int_equal(msg->num_elements, 2); - -- /* show that ldb_filter_attrs_in_place does not modify in.dn */ -- assert_ptr_equal(filtered_msg->dn, in.dn); -+ assert_non_null(msg->dn); - -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "distinguishedName", - NULL), -- ldb_dn_get_linearized(in.dn)); -- assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, -+ ldb_dn_get_linearized(msg->dn)); -+ assert_string_equal(ldb_msg_find_attr_as_string(msg, - "foo", - NULL), - value); -@@ -836,12 +798,12 @@ static void test_filter_attrs_one_attr_matched_star_dn(void **state) - * Test against a record with only one attribute, but returning - * distinguishedName from the list (only) - */ --static void test_filter_attrs_one_attr_matched_dn(void **state) -+static void test_filter_attrs_in_place_one_attr_matched_dn(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {"distinguishedName", NULL}; - -@@ -855,43 +817,36 @@ static void test_filter_attrs_one_attr_matched_dn(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; - -- /* Needed for distinguishedName */ -- filtered_msg->dn = in.dn; -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 1); -- -- /* show that ldb_filter_attrs_in_place does not modify in.dn */ -- assert_ptr_equal(filtered_msg->dn, in.dn); -- assert_string_equal(filtered_msg->elements[0].name, "distinguishedName"); -- assert_int_equal(filtered_msg->elements[0].num_values, 1); -- assert_string_equal(filtered_msg->elements[0].values[0].data, -- ldb_dn_get_linearized(in.dn)); -+ assert_int_equal(msg->num_elements, 1); -+ -+ assert_non_null(msg->dn); -+ assert_string_equal(msg->elements[0].name, "distinguishedName"); -+ assert_int_equal(msg->elements[0].num_values, 1); -+ assert_string_equal(msg->elements[0].values[0].data, -+ ldb_dn_get_linearized(msg->dn)); - } - - /* - * Test against a record with only one attribute, not matching the - * empty attribute list - */ --static void test_filter_attrs_one_attr_empty_list(void **state) -+static void test_filter_attrs_in_place_one_attr_empty_list(void **state) - { - struct ldbtest_ctx *ctx = *state; - int ret; - -- struct ldb_message *filtered_msg = ldb_msg_new(ctx); -+ struct ldb_message *msg = ldb_msg_new(ctx); - - const char *attrs[] = {NULL}; - -@@ -905,82 +860,78 @@ static void test_filter_attrs_one_attr_empty_list(void **state) - .num_values = 1, - .values = &value_1 - }; -- struct ldb_message in = { -- .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), -- .num_elements = 1, -- .elements = &element_1, -- }; - -- assert_non_null(in.dn); -+ assert_non_null(msg); -+ msg->dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"); -+ msg->num_elements = 1; -+ msg->elements = &element_1; -+ -+ assert_non_null(msg->dn); -+ msg_add_dn(msg); - -- ret = ldb_filter_attrs_in_place(ctx->ldb, -- &in, -- attrs, -- filtered_msg); -+ ret = ldb_filter_attrs_in_place(msg, attrs); - assert_int_equal(ret, LDB_SUCCESS); -- assert_non_null(filtered_msg); -- assert_int_equal(filtered_msg->num_elements, 0); -- assert_null(filtered_msg->dn); -- assert_null(filtered_msg->elements); -+ assert_int_equal(msg->num_elements, 0); -+ assert_non_null(msg->dn); - } - - int main(int argc, const char **argv) - { - const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched, -+ test_filter_attrs_in_place_one_attr_matched, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched_of_many, -+ test_filter_attrs_in_place_one_attr_matched_of_many, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_attr_matched_attrs, -+ test_filter_attrs_in_place_two_attr_matched_attrs, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_attr_matched_one_attr, -+ test_filter_attrs_in_place_two_attr_matched_one_attr, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_dup_attr_matched_one_attr, -+ test_filter_attrs_in_place_two_dup_attr_matched_one_attr, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_dup_attr_matched_dup, -+ test_filter_attrs_in_place_two_dup_attr_matched_dup, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_dup_attr_matched_one_of_two, -+ test_filter_attrs_in_place_two_dup_attr_matched_one_of_two, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_dup_attr_matched_star, -+ test_filter_attrs_in_place_two_dup_attr_matched_star, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched_star, -+ test_filter_attrs_in_place_one_attr_matched_star, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_two_attr_matched_star, -+ test_filter_attrs_in_place_two_attr_matched_star, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched_star_no_dn, -+ test_filter_attrs_in_place_one_attr_matched_star_no_dn, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched_star_dn, -+ test_filter_attrs_in_place_one_attr_matched_star_dn, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_matched_dn, -+ test_filter_attrs_in_place_one_attr_matched_dn, - setup, - teardown), - cmocka_unit_test_setup_teardown( -- test_filter_attrs_one_attr_empty_list, -+ test_filter_attrs_in_place_one_attr_empty_list, - setup, - teardown), - }; --- -2.25.1 \ No newline at end of file diff --git a/backport-0016-CVE-2023-0614.patch b/backport-0016-CVE-2023-0614.patch deleted file mode 100644 index 0b8c1d8f549dff003402b0261c9e11b51990704e..0000000000000000000000000000000000000000 --- a/backport-0016-CVE-2023-0614.patch +++ /dev/null @@ -1,293 +0,0 @@ -From 8e84201f508b2893b6ec9383c656cccb08b148ef Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/ldb_key_value/ldb_kv.h | 6 +- - lib/ldb/ldb_key_value/ldb_kv_index.c | 27 +++++---- - lib/ldb/ldb_key_value/ldb_kv_search.c | 86 ++++++++++++++------------- - source4/torture/ldb/ldb.c | 12 ++-- - 4 files changed, 66 insertions(+), 65 deletions(-) - -diff --git a/lib/ldb/ldb_key_value/ldb_kv.h b/lib/ldb/ldb_key_value/ldb_kv.h -index ac474b04b4c..7d5a40e76e9 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv.h -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c -index d70e5f619ef..203266ea8c9 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_index.c -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c -index 46031b99c16..f3333510eab 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_search.c -+++ b/lib/ldb/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 -diff --git a/source4/torture/ldb/ldb.c b/source4/torture/ldb/ldb.c -index bd0ae3a382a..c170416bec4 100644 ---- a/source4/torture/ldb/ldb.c -+++ b/source4/torture/ldb/ldb.c -@@ -1634,7 +1634,6 @@ static bool torture_ldb_unpack_and_filter(struct torture_context *torture, - TALLOC_CTX *mem_ctx = talloc_new(torture); - struct ldb_context *ldb; - struct ldb_val data = *discard_const_p(struct ldb_val, data_p); -- struct ldb_message *unpack_msg = ldb_msg_new(mem_ctx); - struct ldb_message *msg = ldb_msg_new(mem_ctx); - const char *lookup_names[] = {"instanceType", "nonexistent", - "whenChanged", "objectClass", -@@ -1649,18 +1648,15 @@ static bool torture_ldb_unpack_and_filter(struct torture_context *torture, - "Failed to init samba"); - - torture_assert_int_equal(torture, -- ldb_unpack_data(ldb, &data, unpack_msg), -+ ldb_unpack_data(ldb, &data, msg), - 0, "ldb_unpack_data failed"); - -- torture_assert_int_equal(torture, unpack_msg->num_elements, 13, -+ torture_assert_int_equal(torture, msg->num_elements, 13, - "Got wrong count of elements"); - -- msg->dn = talloc_steal(msg, unpack_msg->dn); -- - torture_assert_int_equal(torture, -- ldb_filter_attrs(ldb, unpack_msg, -- lookup_names, msg), -- 0, "ldb_kv_filter_attrs failed"); -+ ldb_filter_attrs_in_place(msg, lookup_names), -+ 0, "ldb_filter_attrs_in_place failed"); - - /* Compare data in binary form */ - torture_assert_int_equal(torture, msg->num_elements, 6, --- -2.25.1 \ No newline at end of file diff --git a/backport-0017-CVE-2023-0614.patch b/backport-0017-CVE-2023-0614.patch deleted file mode 100644 index fcd8daa2292198cc62b2e7117e1db6d6fd89d949..0000000000000000000000000000000000000000 --- a/backport-0017-CVE-2023-0614.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 9e07df4e268fd49358382e8d90c2d151efb66569 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Tue, 7 Feb 2023 09:35:24 +1300 -Subject: [PATCH 15/34] CVE-2023-0614 s4:dsdb/extended_dn_in: Don't modify a - search tree we don't own - -In extended_dn_fix_filter() we had: - - req->op.search.tree = ldb_parse_tree_copy_shallow(req, req->op.search.tree); - -which overwrote the parse tree on an existing ldb request with a fixed -up tree. This became a problem if a module performed another search with -that same request structure, as extended_dn_in would try to fix up the -already-modified tree for a second time. The fixed-up tree element now -having an extended DN, it would fall foul of the ldb_dn_match_allowed() -check in extended_dn_filter_callback(), and be replaced with an -ALWAYS_FALSE match rule. In practice this meant that searches -would only work for one search in an ldb request, and fail for -subsequent ones. - -Fix this by creating a new request with the modified tree, and leaving -the original request unmodified. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - .../dsdb/samdb/ldb_modules/extended_dn_in.c | 40 +++++++++++++++---- - 1 file changed, 32 insertions(+), 8 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -index 2d0513a738b..1dc1e1f2d42 100644 ---- a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -@@ -48,6 +48,7 @@ - struct extended_search_context { - struct ldb_module *module; - struct ldb_request *req; -+ struct ldb_parse_tree *tree; - struct ldb_dn *basedn; - struct ldb_dn *dn; - char *wellknown_object; -@@ -200,7 +201,7 @@ static int extended_base_callback(struct ldb_request *req, struct ldb_reply *are - ldb_module_get_ctx(ac->module), ac->req, - ac->basedn, - ac->req->op.search.scope, -- ac->req->op.search.tree, -+ ac->tree, - ac->req->op.search.attrs, - ac->req->controls, - ac, extended_final_callback, -@@ -515,11 +516,14 @@ static int extended_dn_filter_callback(struct ldb_parse_tree *tree, void *privat - */ - static int extended_dn_fix_filter(struct ldb_module *module, - struct ldb_request *req, -- uint32_t default_dsdb_flags) -+ uint32_t default_dsdb_flags, -+ struct ldb_parse_tree **down_tree) - { - struct extended_dn_filter_ctx *filter_ctx; - int ret; - -+ *down_tree = NULL; -+ - filter_ctx = talloc_zero(req, struct extended_dn_filter_ctx); - if (filter_ctx == NULL) { - return ldb_module_oom(module); -@@ -550,12 +554,12 @@ static int extended_dn_fix_filter(struct ldb_module *module, - filter_ctx->test_only = false; - filter_ctx->matched = false; - -- req->op.search.tree = ldb_parse_tree_copy_shallow(req, req->op.search.tree); -- if (req->op.search.tree == NULL) { -+ *down_tree = ldb_parse_tree_copy_shallow(req, req->op.search.tree); -+ if (*down_tree == NULL) { - return ldb_oom(ldb_module_get_ctx(module)); - } - -- ret = ldb_parse_tree_walk(req->op.search.tree, extended_dn_filter_callback, filter_ctx); -+ ret = ldb_parse_tree_walk(*down_tree, extended_dn_filter_callback, filter_ctx); - if (ret != LDB_SUCCESS) { - talloc_free(filter_ctx); - return ret; -@@ -572,7 +576,8 @@ static int extended_dn_fix_filter(struct ldb_module *module, - static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn) - { - struct extended_search_context *ac; -- struct ldb_request *down_req; -+ struct ldb_request *down_req = NULL; -+ struct ldb_parse_tree *down_tree = NULL; - int ret; - struct ldb_dn *base_dn = NULL; - enum ldb_scope base_dn_scope = LDB_SCOPE_BASE; -@@ -595,7 +600,7 @@ static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req - } - - if (req->operation == LDB_SEARCH) { -- ret = extended_dn_fix_filter(module, req, dsdb_flags); -+ ret = extended_dn_fix_filter(module, req, dsdb_flags, &down_tree); - if (ret != LDB_SUCCESS) { - return ret; - } -@@ -603,7 +608,25 @@ static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req - - if (!ldb_dn_has_extended(dn)) { - /* Move along there isn't anything to see here */ -- return ldb_next_request(module, req); -+ if (down_tree == NULL) { -+ down_req = req; -+ } else { -+ ret = ldb_build_search_req_ex(&down_req, -+ ldb_module_get_ctx(module), req, -+ req->op.search.base, -+ req->op.search.scope, -+ down_tree, -+ req->op.search.attrs, -+ req->controls, -+ req, dsdb_next_callback, -+ req); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ LDB_REQ_SET_LOCATION(down_req); -+ } -+ -+ return ldb_next_request(module, down_req); - } else { - /* It looks like we need to map the DN */ - const struct ldb_val *sid_val, *guid_val, *wkguid_val; -@@ -690,6 +713,7 @@ static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req - - ac->module = module; - ac->req = req; -+ ac->tree = (down_tree != NULL) ? down_tree : req->op.search.tree; - ac->dn = dn; - ac->basedn = NULL; /* Filled in if the search finds the DN by SID/GUID etc */ - ac->wellknown_object = wellknown_object; --- -2.25.1 \ No newline at end of file diff --git a/backport-0018-CVE-2023-0614.patch b/backport-0018-CVE-2023-0614.patch deleted file mode 100644 index d2f85e5515ee38423f6e2371a3f5c9393a19db45..0000000000000000000000000000000000000000 --- a/backport-0018-CVE-2023-0614.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 13e0b2190c802dc876b465a201b8dc9f35f9720c Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Tue, 7 Feb 2023 09:48:37 +1300 -Subject: [PATCH 16/34] CVE-2023-0614 s4:dsdb:tests: Fix search in - confidential attributes test - -The object returned by schema_format_value() is a bytes object. -Therefore the search expression would resemble: - -(lastKnownParent=) - -which, due to the extra characters, would fail to match anything. - -Fix it to be: - -(lastKnownParent=) - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/tests/python/confidential_attr.py | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/source4/dsdb/tests/python/confidential_attr.py b/source4/dsdb/tests/python/confidential_attr.py -index d5c7785485a..1c9c456917a 100755 ---- a/source4/dsdb/tests/python/confidential_attr.py -+++ b/source4/dsdb/tests/python/confidential_attr.py -@@ -924,12 +924,12 @@ class ConfidentialAttrTestDirsync(ConfidentialAttrCommon): - self.assert_negative_searches(has_rights_to="all", - samdb=self.ldb_admin) - -- def get_guid(self, dn): -+ def get_guid_string(self, dn): - """Returns an object's GUID (in string format)""" - res = self.ldb_admin.search(base=dn, attrs=["objectGUID"], - scope=SCOPE_BASE) - guid = res[0]['objectGUID'][0] -- return self.ldb_admin.schema_format_value("objectGUID", guid) -+ return self.ldb_admin.schema_format_value("objectGUID", guid).decode('utf-8') - - def make_attr_preserve_on_delete(self): - """Marks the attribute under test as being preserve on delete""" -@@ -978,7 +978,7 @@ class ConfidentialAttrTestDirsync(ConfidentialAttrCommon): - # deleted objects, but only from this particular test run. We can do - # this by matching lastKnownParent against this test case's OU, which - # will match any deleted child objects. -- ou_guid = self.get_guid(self.ou) -+ ou_guid = self.get_guid_string(self.ou) - deleted_filter = "(lastKnownParent=)".format(ou_guid) - - # the extra-filter will get combined via AND with the search expression --- -2.25.1 \ No newline at end of file diff --git a/backport-0019-CVE-2023-0614.patch b/backport-0019-CVE-2023-0614.patch deleted file mode 100644 index ec217de92f18c8553d6c0b0cad7a91fb2ff42158..0000000000000000000000000000000000000000 --- a/backport-0019-CVE-2023-0614.patch +++ /dev/null @@ -1,49 +0,0 @@ -From e167524e306241ba14f925f412e3f89828ed8c61 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Thu, 25 Aug 2022 20:15:33 +1200 -Subject: [PATCH 17/34] schema_samba4.ldif: Allocate previously added OIDs - -DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID was added -to source4/dsdb/samdb/samdb.h in commit -c2ab1f4696fa3f52918a126d0b37993a07f68bcb. - -DSDB_EXTENDED_SCHEMA_LOAD was added in commit -1fd4cdfafaa6a41c824d1b3d76635bf3e446de0f. - -Signed-off-by: Joseph Sutton -Reviewed-by: Douglas Bagnall -Reviewed-by: Stefan Metzmacher -(cherry picked from commit 672ec6135f9ae3d7b5439523a4f456c19fb03a88) - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -[abartlet@samba.org This required as context for the above bug] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/setup/schema_samba4.ldif | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif -index a31b67750d4..54f48bde20e 100644 ---- a/source4/setup/schema_samba4.ldif -+++ b/source4/setup/schema_samba4.ldif -@@ -231,6 +231,7 @@ - #Allocated: DSDB_CONTROL_INVALID_NOT_IMPLEMENTED 1.3.6.1.4.1.7165.4.3.32 - #Allocated: DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID 1.3.6.1.4.1.7165.4.3.33 - #Allocated: DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID 1.3.6.1.4.1.7165.4.3.34 -+#Allocated: DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID 1.3.6.1.4.1.7165.4.3.35 - - - # Extended 1.3.6.1.4.1.7165.4.4.x -@@ -243,6 +244,7 @@ - #Allocated: DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.4.7 - #Allocated: DSDB_EXTENDED_CREATE_OWN_RID_SET 1.3.6.1.4.1.7165.4.4.8 - #Allocated: DSDB_EXTENDED_ALLOCATE_RID 1.3.6.1.4.1.7165.4.4.9 -+#Allocated: DSDB_EXTENDED_SCHEMA_LOAD 1.3.6.1.4.1.7165.4.4.10 - - - ############ --- -2.25.1 \ No newline at end of file diff --git a/backport-0020-CVE-2023-0614.patch b/backport-0020-CVE-2023-0614.patch deleted file mode 100644 index 3547310591521d7c6bdf0faedc002466866ade57..0000000000000000000000000000000000000000 --- a/backport-0020-CVE-2023-0614.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 829157cf07ec887a7164600a53bdc688aa4717be Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Tue, 7 Feb 2023 09:25:48 +1300 -Subject: [PATCH 18/34] CVE-2023-0614 schema_samba4.ldif: Allocate previously - added OID - -DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID was added in commit -08187833fee57a8dba6c67546dfca516cd1f9d7a. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/setup/schema_samba4.ldif | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif -index 54f48bde20e..79800bfd6df 100644 ---- a/source4/setup/schema_samba4.ldif -+++ b/source4/setup/schema_samba4.ldif -@@ -232,6 +232,7 @@ - #Allocated: DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID 1.3.6.1.4.1.7165.4.3.33 - #Allocated: DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID 1.3.6.1.4.1.7165.4.3.34 - #Allocated: DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID 1.3.6.1.4.1.7165.4.3.35 -+#Allocated: DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID 1.3.6.1.4.1.7165.4.3.36 - - - # Extended 1.3.6.1.4.1.7165.4.4.x --- -2.25.1 \ No newline at end of file diff --git a/backport-0021-CVE-2023-0614.patch b/backport-0021-CVE-2023-0614.patch deleted file mode 100644 index 0db2c42962932994c3f56d73fb7ec77228fbb749..0000000000000000000000000000000000000000 --- a/backport-0021-CVE-2023-0614.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 009026fae8eea85789bd912cbf397423480485da Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 27 Jan 2023 08:32:41 +1300 -Subject: [PATCH 19/34] CVE-2023-0614 tests/krb5: Add test for confidential - attributes timing differences - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - selftest/knownfail.d/confidential-attr-timing | 1 + - .../dsdb/tests/python/confidential_attr.py | 162 ++++++++++++++++++ - 2 files changed, 163 insertions(+) - create mode 100644 selftest/knownfail.d/confidential-attr-timing - -diff --git a/selftest/knownfail.d/confidential-attr-timing b/selftest/knownfail.d/confidential-attr-timing -new file mode 100644 -index 00000000000..e213cdb16d3 ---- /dev/null -+++ b/selftest/knownfail.d/confidential-attr-timing -@@ -0,0 +1 @@ -+^samba4.ldap.confidential_attr.python\(ad_dc_slowtests\).__main__.ConfidentialAttrTestDirsync.test_timing_attack\(ad_dc_slowtests\) -diff --git a/source4/dsdb/tests/python/confidential_attr.py b/source4/dsdb/tests/python/confidential_attr.py -index 1c9c456917a..031c9690ba6 100755 ---- a/source4/dsdb/tests/python/confidential_attr.py -+++ b/source4/dsdb/tests/python/confidential_attr.py -@@ -25,6 +25,9 @@ sys.path.insert(0, "bin/python") - - import samba - import os -+import random -+import statistics -+import time - from samba.tests.subunitrun import SubunitOptions, TestProgram - import samba.getopt as options - from ldb import SCOPE_BASE, SCOPE_SUBTREE -@@ -1022,4 +1025,163 @@ class ConfidentialAttrTestDirsync(ConfidentialAttrCommon): - self.assert_conf_attr_searches(has_rights_to=0) - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - -+ def test_timing_attack(self): -+ # Create the machine account. -+ mach_name = f'conf_timing_{random.randint(0, 0xffff)}' -+ mach_dn = Dn(self.ldb_admin, f'CN={mach_name},{self.ou}') -+ details = { -+ 'dn': mach_dn, -+ 'objectclass': 'computer', -+ 'sAMAccountName': f'{mach_name}$', -+ } -+ self.ldb_admin.add(details) -+ -+ # Get the machine account's GUID. -+ res = self.ldb_admin.search(mach_dn, -+ attrs=['objectGUID'], -+ scope=SCOPE_BASE) -+ mach_guid = res[0].get('objectGUID', idx=0) -+ -+ # Now we can create an msFVE-RecoveryInformation object that is a child -+ # of the machine account object. -+ recovery_dn = Dn(self.ldb_admin, str(mach_dn)) -+ recovery_dn.add_child('CN=recovery_info') -+ -+ secret_pw = 'Secret007' -+ not_secret_pw = 'Secret008' -+ -+ secret_pw_utf8 = secret_pw.encode('utf-8') -+ -+ # The crucial attribute, msFVE-RecoveryPassword, is a confidential -+ # attribute. -+ conf_attr = 'msFVE-RecoveryPassword' -+ -+ m = Message(recovery_dn) -+ m['objectClass'] = 'msFVE-RecoveryInformation' -+ m['msFVE-RecoveryGuid'] = mach_guid -+ m[conf_attr] = secret_pw -+ self.ldb_admin.add(m) -+ -+ attrs = [conf_attr] -+ -+ # Search for the confidential attribute as administrator, ensuring it -+ # is visible. -+ res = self.ldb_admin.search(recovery_dn, -+ attrs=attrs, -+ scope=SCOPE_BASE) -+ self.assertEqual(1, len(res)) -+ pw = res[0].get(conf_attr, idx=0) -+ self.assertEqual(secret_pw_utf8, pw) -+ -+ # Repeat the search with an expression matching on the confidential -+ # attribute. This should also work. -+ res = self.ldb_admin.search( -+ recovery_dn, -+ attrs=attrs, -+ expression=f'({conf_attr}={secret_pw})', -+ scope=SCOPE_BASE) -+ self.assertEqual(1, len(res)) -+ pw = res[0].get(conf_attr, idx=0) -+ self.assertEqual(secret_pw_utf8, pw) -+ -+ # Search for the attribute as an unprivileged user. It should not be -+ # visible. -+ user_res = self.ldb_user.search(recovery_dn, -+ attrs=attrs, -+ scope=SCOPE_BASE) -+ pw = user_res[0].get(conf_attr, idx=0) -+ # The attribute should be None. -+ self.assertIsNone(pw) -+ -+ # We use LDAP_MATCHING_RULE_TRANSITIVE_EVAL to create a search -+ # expression that takes a long time to execute, by setting off another -+ # search each time it is evaluated. It makes no difference that the -+ # object on which we're searching has no 'member' attribute. -+ dummy_dn = 'cn=user,cn=users,dc=samba,dc=example,dc=com' -+ slow_subexpr = f'(member:1.2.840.113556.1.4.1941:={dummy_dn})' -+ slow_expr = f'(|{slow_subexpr * 100})' -+ -+ # The full search expression. It comprises a match on the confidential -+ # attribute joined by an AND to our slow search expression, The AND -+ # operator is short-circuiting, so if our first subexpression fails to -+ # match, we'll bail out of the search early. Otherwise, we'll evaluate -+ # the slow part; as its subexpressions are joined by ORs, and will all -+ # fail to match, every one of them will need to be evaluated. By -+ # measuring how long the search takes, we'll be able to infer whether -+ # the confidential attribute matched or not. -+ -+ # This is bad if we are not an administrator, and are able to use this -+ # to determine the values of confidential attributes. Therefore we need -+ # to ensure we can't observe any difference in timing. -+ correct_expr = f'(&({conf_attr}={secret_pw}){slow_expr})' -+ wrong_expr = f'(&({conf_attr}={not_secret_pw}){slow_expr})' -+ -+ def standard_uncertainty_bounds(times): -+ mean = statistics.mean(times) -+ stdev = statistics.stdev(times, mean) -+ -+ return (mean - stdev, mean + stdev) -+ -+ # Perform a number of searches with both correct and incorrect -+ # expressions, and return the uncertainty bounds for each. -+ def time_searches(samdb): -+ warmup_samples = 3 -+ samples = 10 -+ matching_times = [] -+ non_matching_times = [] -+ -+ for _ in range(warmup_samples): -+ samdb.search(recovery_dn, -+ attrs=attrs, -+ expression=correct_expr, -+ scope=SCOPE_BASE) -+ -+ for _ in range(samples): -+ # Measure the time taken for a search, for both a matching and -+ # a non-matching search expression. -+ -+ prev = time.time() -+ samdb.search(recovery_dn, -+ attrs=attrs, -+ expression=correct_expr, -+ scope=SCOPE_BASE) -+ now = time.time() -+ matching_times.append(now - prev) -+ -+ prev = time.time() -+ samdb.search(recovery_dn, -+ attrs=attrs, -+ expression=wrong_expr, -+ scope=SCOPE_BASE) -+ now = time.time() -+ non_matching_times.append(now - prev) -+ -+ matching = standard_uncertainty_bounds(matching_times) -+ non_matching = standard_uncertainty_bounds(non_matching_times) -+ return matching, non_matching -+ -+ def assertRangesDistinct(a, b): -+ a0, a1 = a -+ b0, b1 = b -+ self.assertLess(min(a1, b1), max(a0, b0)) -+ -+ def assertRangesOverlap(a, b): -+ a0, a1 = a -+ b0, b1 = b -+ self.assertGreaterEqual(min(a1, b1), max(a0, b0)) -+ -+ # For an administrator, the uncertainty bounds for matching and -+ # non-matching searches should be distinct. This shows that the two -+ # cases are distinguishable, and therefore that confidential attributes -+ # are visible. -+ admin_matching, admin_non_matching = time_searches(self.ldb_admin) -+ assertRangesDistinct(admin_matching, admin_non_matching) -+ -+ # The user cannot view the confidential attribute, so the uncertainty -+ # bounds for matching and non-matching searches must overlap. The two -+ # cases must be indistinguishable. -+ user_matching, user_non_matching = time_searches(self.ldb_user) -+ assertRangesOverlap(user_matching, user_non_matching) -+ -+ - TestProgram(module=__name__, opts=subunitopts) --- -2.25.1 \ No newline at end of file diff --git a/backport-0022-CVE-2023-0614.patch b/backport-0022-CVE-2023-0614.patch deleted file mode 100644 index 228cd21ced3301e37239fcc8cdadbdb4ccc484e6..0000000000000000000000000000000000000000 --- a/backport-0022-CVE-2023-0614.patch +++ /dev/null @@ -1,66 +0,0 @@ -From b23fb132e63a6d3d791469614593c43906686ac9 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_parse.c | 25 +++++++++++++++++++++++++ - lib/ldb/include/ldb_module.h | 3 +++ - 2 files changed, 28 insertions(+) - -diff --git a/lib/ldb/common/ldb_parse.c b/lib/ldb/common/ldb_parse.c -index f0045ad2093..2d102ff750e 100644 ---- a/lib/ldb/common/ldb_parse.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index 4ae381ba5be..bd369ed9512 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0023-CVE-2023-0614.patch b/backport-0023-CVE-2023-0614.patch deleted file mode 100644 index 2be9e01114e592858bf8f768f2a738448529856d..0000000000000000000000000000000000000000 --- a/backport-0023-CVE-2023-0614.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 3127ba92bf91fa6f666552ac31cb06ffdc6d7e63 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Mon, 27 Feb 2023 13:40:33 +1300 -Subject: [PATCH 21/34] CVE-2023-0614 s4-acl: Split out logic to remove access - checking attributes - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 58 ++++++++++++++--------- - 1 file changed, 35 insertions(+), 23 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 8814a816797..3980c44345e 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -545,6 +545,39 @@ static int check_search_ops_access(struct aclread_context *ac, - return ret; - } - -+/* -+ * Whether this attribute was added to perform access checks and must be -+ * removed. -+ */ -+static bool should_remove_attr(const char *attr, const struct aclread_context *ac) -+{ -+ if (ac->added_nTSecurityDescriptor && -+ ldb_attr_cmp("nTSecurityDescriptor", attr) == 0) -+ { -+ return true; -+ } -+ -+ if (ac->added_objectSid && -+ ldb_attr_cmp("objectSid", attr) == 0) -+ { -+ return true; -+ } -+ -+ if (ac->added_instanceType && -+ ldb_attr_cmp("instanceType", attr) == 0) -+ { -+ return true; -+ } -+ -+ if (ac->added_objectClass && -+ ldb_attr_cmp("objectClass", attr) == 0) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ - static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - { - struct ldb_context *ldb; -@@ -619,7 +652,6 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - /* for every element in the message check RP */ - for (i=0; i < msg->num_elements; i++) { - const struct dsdb_attribute *attr; -- bool is_sd, is_objectsid, is_instancetype, is_objectclass; - uint32_t access_mask; - attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, - msg->elements[i].name); -@@ -631,28 +663,8 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - ret = LDB_ERR_OPERATIONS_ERROR; - goto fail; - } -- is_sd = ldb_attr_cmp("nTSecurityDescriptor", -- msg->elements[i].name) == 0; -- is_objectsid = ldb_attr_cmp("objectSid", -- msg->elements[i].name) == 0; -- is_instancetype = ldb_attr_cmp("instanceType", -- msg->elements[i].name) == 0; -- is_objectclass = ldb_attr_cmp("objectClass", -- msg->elements[i].name) == 0; -- /* these attributes were added to perform access checks and must be removed */ -- if (is_objectsid && ac->added_objectSid) { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -- continue; -- } -- if (is_instancetype && ac->added_instanceType) { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -- continue; -- } -- if (is_objectclass && ac->added_objectClass) { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -- continue; -- } -- if (is_sd && ac->added_nTSecurityDescriptor) { -+ /* Remove attributes added to perform access checks. */ -+ if (should_remove_attr(msg->elements[i].name, ac)) { - ldb_msg_element_mark_inaccessible(&msg->elements[i]); - continue; - } --- -2.25.1 \ No newline at end of file diff --git a/backport-0024-CVE-2023-0614.patch b/backport-0024-CVE-2023-0614.patch deleted file mode 100644 index 247eb143727c26ee5907d8ffa31344075fbe4af1..0000000000000000000000000000000000000000 --- a/backport-0024-CVE-2023-0614.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 652fecd7d037992b89ed1a4eb17f9f467c2aadf7 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Mon, 27 Feb 2023 12:19:08 +1300 -Subject: [PATCH 22/34] CVE-2023-0614 s4-dsdb: Add samdb_result_dom_sid_buf() - -This function parses a SID from an ldb_message, similar to -samdb_result_dom_sid(), but does it without allocating anything. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/common/util.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c -index a30ae662c1e..b556f06cb63 100644 ---- a/source4/dsdb/common/util.c -+++ b/source4/dsdb/common/util.c -@@ -365,6 +365,26 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_messa - return sid; - } - -+/* -+ pull a dom_sid structure from a objectSid in a result set. -+*/ -+int samdb_result_dom_sid_buf(const struct ldb_message *msg, -+ const char *attr, -+ struct dom_sid *sid) -+{ -+ ssize_t ret; -+ const struct ldb_val *v = NULL; -+ v = ldb_msg_find_ldb_val(msg, attr); -+ if (v == NULL) { -+ return LDB_ERR_NO_SUCH_ATTRIBUTE; -+ } -+ ret = sid_parse(v->data, v->length, sid); -+ if (ret == -1) { -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ return LDB_SUCCESS; -+} -+ - /* - pull a guid structure from a objectGUID in a result set. - */ --- -2.25.1 \ No newline at end of file diff --git a/backport-0025-CVE-2023-0614.patch b/backport-0025-CVE-2023-0614.patch deleted file mode 100644 index 78069a2eb93b169c1c05681aa7f0c74317723080..0000000000000000000000000000000000000000 --- a/backport-0025-CVE-2023-0614.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 3ebfe8666c02ab2de823457c68a922d0b0437cec Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Mon, 27 Feb 2023 13:55:36 +1300 -Subject: [PATCH 23/34] CVE-2023-0614 s4-acl: Split out function to set up - access checking variables - -These variables are often used together, and it is useful to have the -setup code in one place. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -[abartlet@samba.org adapted to the use of - acl_check_access_on_attribute as - acl_check_access_on_attribute_implicit_owner is - only in Samba 4.18 and newer] - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 113 +++++++++++++++------- - 1 file changed, 80 insertions(+), 33 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 3980c44345e..6659c71c965 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -70,6 +70,13 @@ struct aclread_private { - struct ldb_val sd_cached_blob; - }; - -+struct access_check_context { -+ struct security_descriptor *sd; -+ struct dom_sid sid_buf; -+ const struct dom_sid *sid; -+ const struct dsdb_class *objectclass; -+}; -+ - /* - * the object has a parent, so we have to check for visibility - * -@@ -254,7 +261,7 @@ static int aclread_check_object_visible(struct aclread_context *ac, - */ - - static int aclread_get_sd_from_ldb_message(struct aclread_context *ac, -- struct ldb_message *acl_res, -+ const struct ldb_message *acl_res, - struct security_descriptor **sd) - { - struct ldb_message_element *sd_element; -@@ -358,7 +365,7 @@ static uint32_t get_attr_access_mask(const struct dsdb_attribute *attr, - struct parse_tree_aclread_ctx { - struct aclread_context *ac; - TALLOC_CTX *mem_ctx; -- struct dom_sid *sid; -+ const struct dom_sid *sid; - struct ldb_dn *dn; - struct security_descriptor *sd; - const struct dsdb_class *objectclass; -@@ -372,7 +379,7 @@ static int check_attr_access_rights(TALLOC_CTX *mem_ctx, const char *attr_name, - struct aclread_context *ac, - struct security_descriptor *sd, - const struct dsdb_class *objectclass, -- struct dom_sid *sid, struct ldb_dn *dn) -+ const struct dom_sid *sid, struct ldb_dn *dn) - { - int ret; - const struct dsdb_attribute *attr = NULL; -@@ -448,6 +455,69 @@ static const char * parse_tree_get_attr(struct ldb_parse_tree *tree) - return attr; - } - -+static int setup_access_check_context(struct aclread_context *ac, -+ const struct ldb_message *msg, -+ struct access_check_context *ctx) -+{ -+ int ret; -+ -+ /* -+ * Fetch the schema so we can check which attributes are -+ * considered confidential. -+ */ -+ if (ac->schema == NULL) { -+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module); -+ -+ /* Cache the schema for later use. */ -+ ac->schema = dsdb_get_schema(ldb, ac); -+ -+ if (ac->schema == NULL) { -+ return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, -+ "aclread_callback: Error obtaining schema."); -+ } -+ } -+ -+ /* Fetch the object's security descriptor. */ -+ ret = aclread_get_sd_from_ldb_message(ac, msg, &ctx->sd); -+ if (ret != LDB_SUCCESS) { -+ ldb_debug_set(ldb_module_get_ctx(ac->module), LDB_DEBUG_FATAL, -+ "acl_read: cannot get descriptor of %s: %s\n", -+ ldb_dn_get_linearized(msg->dn), ldb_strerror(ret)); -+ return LDB_ERR_OPERATIONS_ERROR; -+ } else if (ctx->sd == NULL) { -+ ldb_debug_set(ldb_module_get_ctx(ac->module), LDB_DEBUG_FATAL, -+ "acl_read: cannot get descriptor of %s (attribute not found)\n", -+ ldb_dn_get_linearized(msg->dn)); -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ /* -+ * Get the most specific structural object class for the ACL check -+ */ -+ ctx->objectclass = dsdb_get_structural_oc_from_msg(ac->schema, msg); -+ if (ctx->objectclass == NULL) { -+ ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), -+ "acl_read: Failed to find a structural class for %s", -+ ldb_dn_get_linearized(msg->dn)); -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ -+ /* Fetch the object's SID. */ -+ ret = samdb_result_dom_sid_buf(msg, "objectSid", &ctx->sid_buf); -+ if (ret == LDB_SUCCESS) { -+ ctx->sid = &ctx->sid_buf; -+ } else if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { -+ /* This is expected. */ -+ ctx->sid = NULL; -+ } else { -+ ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), -+ "acl_read: Failed to parse objectSid as dom_sid for %s", -+ ldb_dn_get_linearized(msg->dn)); -+ return ret; -+ } -+ -+ return LDB_SUCCESS; -+} -+ - /* - * Checks a single attribute in the search parse-tree to make sure the user has - * sufficient rights to view it. -@@ -522,7 +592,7 @@ static int check_search_ops_access(struct aclread_context *ac, - TALLOC_CTX *mem_ctx, - struct security_descriptor *sd, - const struct dsdb_class *objectclass, -- struct dom_sid *sid, struct ldb_dn *dn, -+ const struct dom_sid *sid, struct ldb_dn *dn, - bool *suppress_result) - { - int ret; -@@ -585,10 +655,8 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - struct ldb_message *msg; - int ret; - unsigned int i; -- struct security_descriptor *sd = NULL; -- struct dom_sid *sid = NULL; -+ struct access_check_context acl_ctx; - TALLOC_CTX *tmp_ctx; -- const struct dsdb_class *objectclass; - bool suppress_result = false; - - ac = talloc_get_type_abort(req->context, struct aclread_context); -@@ -604,32 +672,11 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - switch (ares->type) { - case LDB_REPLY_ENTRY: - msg = ares->message; -- ret = aclread_get_sd_from_ldb_message(ac, msg, &sd); -+ ret = setup_access_check_context(ac, msg, &acl_ctx); - if (ret != LDB_SUCCESS) { -- ldb_debug_set(ldb, LDB_DEBUG_FATAL, -- "acl_read: cannot get descriptor of %s: %s\n", -- ldb_dn_get_linearized(msg->dn), ldb_strerror(ret)); -- ret = LDB_ERR_OPERATIONS_ERROR; -- goto fail; -- } else if (sd == NULL) { -- ldb_debug_set(ldb, LDB_DEBUG_FATAL, -- "acl_read: cannot get descriptor of %s (attribute not found)\n", -- ldb_dn_get_linearized(msg->dn)); -- ret = LDB_ERR_OPERATIONS_ERROR; -- goto fail; -- } -- /* -- * Get the most specific structural object class for the ACL check -- */ -- objectclass = dsdb_get_structural_oc_from_msg(ac->schema, msg); -- if (objectclass == NULL) { -- ldb_asprintf_errstring(ldb, "acl_read: Failed to find a structural class for %s", -- ldb_dn_get_linearized(msg->dn)); -- ret = LDB_ERR_OPERATIONS_ERROR; -- goto fail; -+ return ret; - } - -- sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); - if (!ldb_dn_is_null(msg->dn)) { - /* - * this is a real object, so we have -@@ -678,8 +725,8 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - - ret = acl_check_access_on_attribute(ac->module, - tmp_ctx, -- sd, -- sid, -+ acl_ctx.sd, -+ acl_ctx.sid, - access_mask, - attr, - objectclass); -@@ -733,7 +780,7 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - * check access rights for the search attributes, as well as the - * attribute values actually being returned - */ -- ret = check_search_ops_access(ac, tmp_ctx, sd, objectclass, sid, -+ ret = check_search_ops_access(ac, tmp_ctx, acl_ctx.sd, acl_ctx.objectclass, acl_ctx.sid, - msg->dn, &suppress_result); - if (ret != LDB_SUCCESS) { - ldb_debug_set(ldb, LDB_DEBUG_FATAL, --- -2.25.1 \ No newline at end of file diff --git a/backport-0026-CVE-2023-0614.patch b/backport-0026-CVE-2023-0614.patch deleted file mode 100644 index 1fa10f617b9e58c0f533cf3518b202ac4bbec116..0000000000000000000000000000000000000000 --- a/backport-0026-CVE-2023-0614.patch +++ /dev/null @@ -1,1711 +0,0 @@ -From f87af853e2db99269acea572dcc109bc6f797aa9 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 - -Signed-off-by: Joseph Sutton -Signed-off-by: Andrew Bartlett -Reviewed-by: Andrew Bartlett - -[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 ---- - lib/ldb-samba/ldb_matching_rules.c | 15 + - lib/ldb/common/ldb_match.c | 37 + - lib/ldb/include/ldb_module.h | 11 + - lib/ldb/include/ldb_private.h | 5 + - lib/ldb/ldb_key_value/ldb_kv_index.c | 8 + - lib/ldb/ldb_key_value/ldb_kv_search.c | 15 + - selftest/knownfail.d/confidential-attr-timing | 1 - - source4/dsdb/samdb/ldb_modules/acl.c | 183 +--- - source4/dsdb/samdb/ldb_modules/acl_read.c | 837 ++++++++++++------ - source4/dsdb/samdb/samdb.h | 2 + - .../dsdb/tests/python/confidential_attr.py | 12 +- - source4/setup/schema_samba4.ldif | 1 + - 12 files changed, 672 insertions(+), 455 deletions(-) - delete mode 100644 selftest/knownfail.d/confidential-attr-timing - -diff --git a/lib/ldb-samba/ldb_matching_rules.c b/lib/ldb-samba/ldb_matching_rules.c -index 827f3920ae8..0c4c31e49f9 100644 ---- a/lib/ldb-samba/ldb_matching_rules.c -+++ b/lib/ldb-samba/ldb_matching_rules.c -@@ -87,6 +87,11 @@ static int ldb_eval_transitive_filter_helper(TALLOC_CTX *mem_ctx, - return LDB_SUCCESS; - } - -+ if (ldb_msg_element_is_inaccessible(el)) { -+ *matched = false; -+ return LDB_SUCCESS; -+ } -+ - /* - * If the value to match is present in the attribute values of the - * current entry being visited, set matched to true and return OK -@@ -370,6 +375,11 @@ static int dsdb_match_for_dns_to_tombstone_time(struct ldb_context *ldb, - return LDB_SUCCESS; - } - -+ if (ldb_msg_element_is_inaccessible(el)) { -+ *matched = false; -+ return LDB_SUCCESS; -+ } -+ - session_info = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), - struct auth_session_info); - if (session_info == NULL) { -@@ -489,6 +499,11 @@ static int dsdb_match_for_expunge(struct ldb_context *ldb, - return LDB_SUCCESS; - } - -+ if (ldb_msg_element_is_inaccessible(el)) { -+ *matched = false; -+ return LDB_SUCCESS; -+ } -+ - session_info - = talloc_get_type(ldb_get_opaque(ldb, DSDB_SESSION_INFO), - struct auth_session_info); -diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c -index 2f4d41f3441..17314f1b9ca 100644 ---- a/lib/ldb/common/ldb_match.c -+++ b/lib/ldb/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;inum_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/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h -index bd369ed9512..0f14b1ad346 100644 ---- a/lib/ldb/include/ldb_module.h -+++ b/lib/ldb/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/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h -index ca43817d07a..b0a42f6421c 100644 ---- a/lib/ldb/include/ldb_private.h -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c -index 203266ea8c9..163052fecf7 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_index.c -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c -index f3333510eab..d187ba223e1 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_search.c -+++ b/lib/ldb/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 -diff --git a/selftest/knownfail.d/confidential-attr-timing b/selftest/knownfail.d/confidential-attr-timing -deleted file mode 100644 -index e213cdb16d3..00000000000 ---- a/selftest/knownfail.d/confidential-attr-timing -+++ /dev/null -@@ -1 +0,0 @@ --^samba4.ldap.confidential_attr.python\(ad_dc_slowtests\).__main__.ConfidentialAttrTestDirsync.test_timing_attack\(ad_dc_slowtests\) -diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c -index 4098ae2d671..5c57dd25faa 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl.c -+++ b/source4/dsdb/samdb/ldb_modules/acl.c -@@ -46,11 +46,6 @@ - #undef strcasecmp - #undef strncasecmp - --struct extended_access_check_attribute { -- const char *oa_name; -- const uint32_t requires_rights; --}; -- - struct acl_private { - bool acl_search; - const char **password_attrs; -@@ -58,7 +53,6 @@ struct acl_private { - uint64_t cached_schema_metadata_usn; - uint64_t cached_schema_loaded_usn; - const char **confidential_attrs; -- bool userPassword_support; - }; - - struct acl_context { -@@ -66,15 +60,12 @@ struct acl_context { - struct ldb_request *req; - bool am_system; - bool am_administrator; -- bool modify_search; - bool constructed_attrs; - bool allowedAttributes; - bool allowedAttributesEffective; - bool allowedChildClasses; - bool allowedChildClassesEffective; - bool sDRightsEffective; -- bool userPassword; -- const char * const *attrs; - struct dsdb_schema *schema; - }; - -@@ -83,25 +74,9 @@ static int acl_module_init(struct ldb_module *module) - struct ldb_context *ldb; - struct acl_private *data; - int ret; -- unsigned int i, n, j; -- TALLOC_CTX *mem_ctx; -- static const char * const attrs[] = { "passwordAttribute", NULL }; -- static const char * const secret_attrs[] = { -- DSDB_SECRET_ATTRIBUTES -- }; -- struct ldb_result *res; -- struct ldb_message *msg; -- struct ldb_message_element *password_attributes; - - ldb = ldb_module_get_ctx(module); - -- ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); -- if (ret != LDB_SUCCESS) { -- ldb_debug(ldb, LDB_DEBUG_ERROR, -- "acl_module_init: Unable to register control with rootdse!\n"); -- return ldb_operr(ldb); -- } -- - data = talloc_zero(module, struct acl_private); - if (data == NULL) { - return ldb_oom(ldb); -@@ -111,91 +86,14 @@ static int acl_module_init(struct ldb_module *module) - NULL, "acl", "search", true); - ldb_module_set_private(module, data); - -- mem_ctx = talloc_new(module); -- if (!mem_ctx) { -- return ldb_oom(ldb); -- } -- -- ret = dsdb_module_search_dn(module, mem_ctx, &res, -- ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"), -- attrs, -- DSDB_FLAG_NEXT_MODULE | -- DSDB_FLAG_AS_SYSTEM, -- NULL); -- if (ret != LDB_SUCCESS) { -- goto done; -- } -- if (res->count == 0) { -- goto done; -- } -- -- if (res->count > 1) { -- talloc_free(mem_ctx); -- return LDB_ERR_CONSTRAINT_VIOLATION; -- } -- -- msg = res->msgs[0]; -- -- password_attributes = ldb_msg_find_element(msg, "passwordAttribute"); -- if (!password_attributes) { -- goto done; -- } -- data->password_attrs = talloc_array(data, const char *, -- password_attributes->num_values + -- ARRAY_SIZE(secret_attrs) + 1); -- if (!data->password_attrs) { -- talloc_free(mem_ctx); -- return ldb_oom(ldb); -- } -- -- n = 0; -- for (i=0; i < password_attributes->num_values; i++) { -- data->password_attrs[n] = (const char *)password_attributes->values[i].data; -- talloc_steal(data->password_attrs, password_attributes->values[i].data); -- n++; -- } -- -- for (i=0; i < ARRAY_SIZE(secret_attrs); i++) { -- bool found = false; -- -- for (j=0; j < n; j++) { -- if (strcasecmp(data->password_attrs[j], secret_attrs[i]) == 0) { -- found = true; -- break; -- } -- } -- -- if (found) { -- continue; -- } -- -- data->password_attrs[n] = talloc_strdup(data->password_attrs, -- secret_attrs[i]); -- if (data->password_attrs[n] == NULL) { -- talloc_free(mem_ctx); -- return ldb_oom(ldb); -- } -- n++; -- } -- data->password_attrs[n] = NULL; -- --done: -- talloc_free(mem_ctx); -- ret = ldb_next_init(module); -- -+ ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); - if (ret != LDB_SUCCESS) { -- return ret; -+ ldb_debug(ldb, LDB_DEBUG_ERROR, -+ "acl_module_init: Unable to register control with rootdse!\n"); -+ return ldb_operr(ldb); - } - -- /* -- * Check this after the modules have be initialised so we -- * can actually read the backend DB. -- */ -- data->userPassword_support -- = dsdb_user_password_support(module, -- module, -- NULL); -- return ret; -+ return ldb_next_init(module); - } - - static int acl_allowedAttributes(struct ldb_module *module, -@@ -2522,29 +2420,11 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) - ares->controls); - } - -- if (data->password_attrs != NULL) { -- for (i = 0; data->password_attrs[i]; i++) { -- if ((!ac->userPassword) && -- (ldb_attr_cmp(data->password_attrs[i], -- "userPassword") == 0)) -- { -- continue; -- } -- -- ldb_msg_remove_attr(ares->message, data->password_attrs[i]); -- } -- } -- - if (ac->am_administrator) { - return ldb_module_send_entry(ac->req, ares->message, - ares->controls); - } - -- ret = acl_search_update_confidential_attrs(ac, data); -- if (ret != LDB_SUCCESS) { -- return ret; -- } -- - if (data->confidential_attrs != NULL) { - for (i = 0; data->confidential_attrs[i]; i++) { - ldb_msg_remove_attr(ares->message, -@@ -2569,11 +2449,12 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) - { - struct ldb_context *ldb; - struct acl_context *ac; -- struct ldb_parse_tree *down_tree; -+ struct ldb_parse_tree *down_tree = req->op.search.tree; - struct ldb_request *down_req; - struct acl_private *data; - int ret; - unsigned int i; -+ bool modify_search = true; - - if (ldb_dn_is_special(req->op.search.base)) { - return ldb_next_request(module, req); -@@ -2592,13 +2473,11 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) - ac->am_system = dsdb_module_am_system(module); - ac->am_administrator = dsdb_module_am_administrator(module); - ac->constructed_attrs = false; -- ac->modify_search = true; - ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes"); - ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective"); - ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses"); - ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective"); - ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, "sDRightsEffective"); -- ac->userPassword = true; - ac->schema = dsdb_get_schema(ldb, ac); - - ac->constructed_attrs |= ac->allowedAttributes; -@@ -2608,13 +2487,13 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) - ac->constructed_attrs |= ac->sDRightsEffective; - - if (data == NULL) { -- ac->modify_search = false; -+ modify_search = false; - } - if (ac->am_system) { -- ac->modify_search = false; -+ modify_search = false; - } - -- if (!ac->constructed_attrs && !ac->modify_search) { -+ if (!ac->constructed_attrs && !modify_search) { - talloc_free(ac); - return ldb_next_request(module, req); - } -@@ -2624,38 +2503,24 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) - return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, - "acl_private data is missing"); - } -- ac->userPassword = data->userPassword_support; -- -- ret = acl_search_update_confidential_attrs(ac, data); -- if (ret != LDB_SUCCESS) { -- return ret; -- } - -- down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); -- if (down_tree == NULL) { -- return ldb_oom(ldb); -- } -+ if (!ac->am_system && !ac->am_administrator) { -+ ret = acl_search_update_confidential_attrs(ac, data); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } - -- if (!ac->am_system && data->password_attrs) { -- for (i = 0; data->password_attrs[i]; i++) { -- if ((!ac->userPassword) && -- (ldb_attr_cmp(data->password_attrs[i], -- "userPassword") == 0)) -- { -- continue; -+ if (data->confidential_attrs != NULL) { -+ down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); -+ if (down_tree == NULL) { -+ return ldb_oom(ldb); - } - -- ldb_parse_tree_attr_replace(down_tree, -- data->password_attrs[i], -- "kludgeACLredactedattribute"); -- } -- } -- -- if (!ac->am_system && !ac->am_administrator && data->confidential_attrs) { -- for (i = 0; data->confidential_attrs[i]; i++) { -- ldb_parse_tree_attr_replace(down_tree, -- data->confidential_attrs[i], -- "kludgeACLredactedattribute"); -+ for (i = 0; data->confidential_attrs[i]; i++) { -+ ldb_parse_tree_attr_replace(down_tree, -+ data->confidential_attrs[i], -+ "kludgeACLredactedattribute"); -+ } - } - } - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 6659c71c965..8ca8607b925 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -37,20 +37,25 @@ - #include "librpc/gen_ndr/ndr_security.h" - #include "param/param.h" - #include "dsdb/samdb/ldb_modules/util.h" -+#include "lib/util/binsearch.h" - - #undef strcasecmp - -+struct ldb_attr_vec { -+ const char** attrs; -+ size_t len; -+ size_t capacity; -+}; -+ - struct aclread_context { - struct ldb_module *module; - struct ldb_request *req; -- const char * const *attrs; - const struct dsdb_schema *schema; - uint32_t sd_flags; - bool added_nTSecurityDescriptor; - bool added_instanceType; - bool added_objectSid; - bool added_objectClass; -- bool indirsync; - - bool do_list_object_initialized; - bool do_list_object; -@@ -60,6 +65,11 @@ struct aclread_context { - /* cache on the last parent we checked in this search */ - struct ldb_dn *last_parent_dn; - int last_parent_check_ret; -+ -+ bool am_administrator; -+ -+ bool got_tree_attrs; -+ struct ldb_attr_vec tree_attrs; - }; - - struct aclread_private { -@@ -68,6 +78,7 @@ struct aclread_private { - /* cache of the last SD we read during any search */ - struct security_descriptor *sd_cached; - struct ldb_val sd_cached_blob; -+ const char **password_attrs; - }; - - struct access_check_context { -@@ -77,6 +88,183 @@ struct access_check_context { - const struct dsdb_class *objectclass; - }; - -+static void acl_element_mark_access_checked(struct ldb_message_element *el) -+{ -+ el->flags |= LDB_FLAG_INTERNAL_ACCESS_CHECKED; -+} -+ -+static bool acl_element_is_access_checked(const struct ldb_message_element *el) -+{ -+ return (el->flags & LDB_FLAG_INTERNAL_ACCESS_CHECKED) != 0; -+} -+ -+static bool attr_in_vec(const struct ldb_attr_vec *vec, const char *attr) -+{ -+ const char **found = NULL; -+ -+ if (vec == NULL) { -+ return false; -+ } -+ -+ BINARY_ARRAY_SEARCH_V(vec->attrs, -+ vec->len, -+ attr, -+ ldb_attr_cmp, -+ found); -+ return found != NULL; -+} -+ -+static int acl_attr_cmp_fn(const char *a, const char **b) -+{ -+ return ldb_attr_cmp(a, *b); -+} -+ -+static int attr_vec_add_unique(TALLOC_CTX *mem_ctx, -+ struct ldb_attr_vec *vec, -+ const char *attr) -+{ -+ const char **exact = NULL; -+ const char **next = NULL; -+ size_t next_idx = 0; -+ -+ BINARY_ARRAY_SEARCH_GTE(vec->attrs, -+ vec->len, -+ attr, -+ acl_attr_cmp_fn, -+ exact, -+ next); -+ if (exact != NULL) { -+ return LDB_SUCCESS; -+ } -+ -+ if (vec->len == SIZE_MAX) { -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ -+ if (next != NULL) { -+ next_idx = next - vec->attrs; -+ } -+ -+ if (vec->len >= vec->capacity) { -+ const char **attrs = NULL; -+ -+ if (vec->capacity == 0) { -+ vec->capacity = 4; -+ } else { -+ if (vec->capacity > SIZE_MAX / 2) { -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ vec->capacity *= 2; -+ } -+ -+ attrs = talloc_realloc(mem_ctx, vec->attrs, const char *, vec->capacity); -+ if (attrs == NULL) { -+ return LDB_ERR_OPERATIONS_ERROR; -+ } -+ -+ vec->attrs = attrs; -+ } -+ SMB_ASSERT(vec->len < vec->capacity); -+ -+ if (next == NULL) { -+ vec->attrs[vec->len++] = attr; -+ } else { -+ size_t count = (vec->len - next_idx) * sizeof (vec->attrs[0]); -+ memmove(&vec->attrs[next_idx + 1], -+ &vec->attrs[next_idx], -+ count); -+ -+ vec->attrs[next_idx] = attr; -+ ++vec->len; -+ } -+ -+ return LDB_SUCCESS; -+} -+ -+static bool ldb_attr_always_present(const char *attr) -+{ -+ static const char * const attrs_always_present[] = { -+ "objectClass", -+ "distinguishedName", -+ "name", -+ "objectGUID", -+ NULL -+ }; -+ -+ return ldb_attr_in_list(attrs_always_present, attr); -+} -+ -+static bool ldb_attr_always_visible(const char *attr) -+{ -+ static const char * const attrs_always_visible[] = { -+ "isDeleted", -+ "isRecycled", -+ NULL -+ }; -+ -+ return ldb_attr_in_list(attrs_always_visible, attr); -+} -+ -+/* Collect a list of attributes required to match a given parse tree. */ -+static int ldb_parse_tree_collect_acl_attrs(struct ldb_module *module, -+ TALLOC_CTX *mem_ctx, -+ struct ldb_attr_vec *attrs, -+ const struct ldb_parse_tree *tree) -+{ -+ const char *attr = NULL; -+ unsigned int i; -+ int ret; -+ -+ if (tree == NULL) { -+ return 0; -+ } -+ -+ switch (tree->operation) { -+ case LDB_OP_OR: -+ case LDB_OP_AND: /* attributes stored in list of subtrees */ -+ for (i = 0; i < tree->u.list.num_elements; i++) { -+ ret = ldb_parse_tree_collect_acl_attrs(module, mem_ctx, -+ attrs, tree->u.list.elements[i]); -+ if (ret) { -+ return ret; -+ } -+ } -+ return 0; -+ -+ case LDB_OP_NOT: /* attributes stored in single subtree */ -+ return ldb_parse_tree_collect_acl_attrs(module, mem_ctx, attrs, tree->u.isnot.child); -+ -+ case LDB_OP_PRESENT: -+ /* -+ * If the search filter is checking for an attribute's presence, -+ * and the attribute is always present, we can skip access -+ * rights checks. Every object has these attributes, and so -+ * there's no security reason to hide their presence. -+ * Note: the acl.py tests (e.g. test_search1()) rely on this -+ * exception. I.e. even if we lack Read Property (RP) rights -+ * for a child object, it should still appear as a visible -+ * object in 'objectClass=*' searches, so long as we have List -+ * Contents (LC) rights for the object. -+ */ -+ if (ldb_attr_always_present(tree->u.present.attr)) { -+ /* No need to check this attribute. */ -+ return 0; -+ } -+ -+ FALL_THROUGH; -+ case LDB_OP_EQUALITY: -+ if (ldb_attr_always_visible(tree->u.present.attr)) { -+ /* No need to check this attribute. */ -+ return 0; -+ } -+ -+ FALL_THROUGH; -+ default: /* single attribute in tree */ -+ attr = ldb_parse_tree_get_attr(tree); -+ return attr_vec_add_unique(mem_ctx, attrs, attr); -+ } -+} -+ - /* - * the object has a parent, so we have to check for visibility - * -@@ -308,16 +496,11 @@ static int aclread_get_sd_from_ldb_message(struct aclread_context *ac, - } - - talloc_unlink(private_data, private_data->sd_cached_blob.data); -- if (ac->added_nTSecurityDescriptor) { -- private_data->sd_cached_blob = sd_element->values[0]; -- talloc_steal(private_data, sd_element->values[0].data); -- } else { -- private_data->sd_cached_blob = ldb_val_dup(private_data, -- &sd_element->values[0]); -- if (private_data->sd_cached_blob.data == NULL) { -- TALLOC_FREE(*sd); -- return ldb_operr(ldb); -- } -+ private_data->sd_cached_blob = ldb_val_dup(private_data, -+ &sd_element->values[0]); -+ if (private_data->sd_cached_blob.data == NULL) { -+ TALLOC_FREE(*sd); -+ return ldb_operr(ldb); - } - - talloc_unlink(private_data, private_data->sd_cached); -@@ -326,6 +509,27 @@ static int aclread_get_sd_from_ldb_message(struct aclread_context *ac, - return LDB_SUCCESS; - } - -+/* Check whether the attribute is a password attribute. */ -+static bool attr_is_secret(const char *attr, const struct aclread_private *private_data) -+{ -+ unsigned i; -+ -+ if (private_data->password_attrs == NULL) { -+ return false; -+ } -+ -+ for (i = 0; private_data->password_attrs[i] != NULL; ++i) { -+ const char *password_attr = private_data->password_attrs[i]; -+ if (ldb_attr_cmp(attr, password_attr) != 0) { -+ continue; -+ } -+ -+ return true; -+ } -+ -+ return false; -+} -+ - /* - * Returns the access mask required to read a given attribute - */ -@@ -361,61 +565,59 @@ static uint32_t get_attr_access_mask(const struct dsdb_attribute *attr, - return access_mask; - } - --/* helper struct for traversing the attributes in the search-tree */ --struct parse_tree_aclread_ctx { -- struct aclread_context *ac; -- TALLOC_CTX *mem_ctx; -- const struct dom_sid *sid; -- struct ldb_dn *dn; -- struct security_descriptor *sd; -- const struct dsdb_class *objectclass; -- bool suppress_result; --}; -- - /* -- * Checks that the user has sufficient access rights to view an attribute -+ * Checks that the user has sufficient access rights to view an attribute, else -+ * marks it as inaccessible. - */ --static int check_attr_access_rights(TALLOC_CTX *mem_ctx, const char *attr_name, -- struct aclread_context *ac, -- struct security_descriptor *sd, -- const struct dsdb_class *objectclass, -- const struct dom_sid *sid, struct ldb_dn *dn) -+static int acl_redact_attr(TALLOC_CTX *mem_ctx, -+ struct ldb_message_element *el, -+ struct aclread_context *ac, -+ const struct aclread_private *private_data, -+ const struct ldb_message *msg, -+ const struct dsdb_schema *schema, -+ const struct security_descriptor *sd, -+ const struct dom_sid *sid, -+ const struct dsdb_class *objectclass) - { - int ret; - const struct dsdb_attribute *attr = NULL; - uint32_t access_mask; - struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - -- attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, attr_name); -+ if (attr_is_secret(el->name, private_data)) { -+ ldb_msg_element_mark_inaccessible(el); -+ return LDB_SUCCESS; -+ } -+ -+ /* Look up the attribute in the schema. */ -+ attr = dsdb_attribute_by_lDAPDisplayName(schema, el->name); - if (!attr) { - ldb_debug_set(ldb, -- LDB_DEBUG_TRACE, -- "acl_read: %s cannot find attr[%s] in schema," -- "ignoring\n", -- ldb_dn_get_linearized(dn), attr_name); -- return LDB_SUCCESS; -+ LDB_DEBUG_FATAL, -+ "acl_read: %s cannot find attr[%s] in schema\n", -+ ldb_dn_get_linearized(msg->dn), el->name); -+ return LDB_ERR_OPERATIONS_ERROR; - } - - access_mask = get_attr_access_mask(attr, ac->sd_flags); -- -- /* the access-mask should be non-zero. Skip attribute otherwise */ - if (access_mask == 0) { - DBG_ERR("Could not determine access mask for attribute %s\n", -- attr_name); -+ el->name); -+ ldb_msg_element_mark_inaccessible(el); - return LDB_SUCCESS; - } - -+ /* We must check whether the user has rights to view the attribute. */ -+ - ret = acl_check_access_on_attribute(ac->module, mem_ctx, sd, sid, - access_mask, attr, objectclass); - - if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { -- return ret; -- } -- -- if (ret != LDB_SUCCESS) { -+ ldb_msg_element_mark_inaccessible(el); -+ } else if (ret != LDB_SUCCESS) { - ldb_debug_set(ldb, LDB_DEBUG_FATAL, - "acl_read: %s check attr[%s] gives %s - %s\n", -- ldb_dn_get_linearized(dn), attr_name, -+ ldb_dn_get_linearized(msg->dn), el->name, - ldb_strerror(ret), ldb_errstring(ldb)); - return ret; - } -@@ -423,38 +625,6 @@ static int check_attr_access_rights(TALLOC_CTX *mem_ctx, const char *attr_name, - return LDB_SUCCESS; - } - --/* -- * Returns the attribute name for this particular level of a search operation -- * parse-tree. -- */ --static const char * parse_tree_get_attr(struct ldb_parse_tree *tree) --{ -- const char *attr = NULL; -- -- switch (tree->operation) { -- case LDB_OP_EQUALITY: -- case LDB_OP_GREATER: -- case LDB_OP_LESS: -- case LDB_OP_APPROX: -- attr = tree->u.equality.attr; -- break; -- case LDB_OP_SUBSTRING: -- attr = tree->u.substring.attr; -- break; -- case LDB_OP_PRESENT: -- attr = tree->u.present.attr; -- break; -- case LDB_OP_EXTENDED: -- attr = tree->u.extended.attr; -- break; -- -- /* we'll check LDB_OP_AND/_OR/_NOT children later on in the walk */ -- default: -- break; -- } -- return attr; --} -- - static int setup_access_check_context(struct aclread_context *ac, - const struct ldb_message *msg, - struct access_check_context *ctx) -@@ -518,103 +688,6 @@ static int setup_access_check_context(struct aclread_context *ac, - return LDB_SUCCESS; - } - --/* -- * Checks a single attribute in the search parse-tree to make sure the user has -- * sufficient rights to view it. -- */ --static int parse_tree_check_attr_access(struct ldb_parse_tree *tree, -- void *private_context) --{ -- struct parse_tree_aclread_ctx *ctx = NULL; -- const char *attr_name = NULL; -- int ret; -- static const char * const attrs_always_present[] = { -- "objectClass", -- "distinguishedName", -- "name", -- "objectGUID", -- NULL -- }; -- -- ctx = (struct parse_tree_aclread_ctx *)private_context; -- -- /* -- * we can skip any further checking if we already know that this object -- * shouldn't be visible in this user's search -- */ -- if (ctx->suppress_result) { -- return LDB_SUCCESS; -- } -- -- /* skip this level of the search-tree if it has no attribute to check */ -- attr_name = parse_tree_get_attr(tree); -- if (attr_name == NULL) { -- return LDB_SUCCESS; -- } -- -- /* -- * If the search filter is checking for an attribute's presence, and the -- * attribute is always present, we can skip access rights checks. Every -- * object has these attributes, and so there's no security reason to -- * hide their presence. -- * Note: the acl.py tests (e.g. test_search1()) rely on this exception. -- * I.e. even if we lack Read Property (RP) rights for a child object, it -- * should still appear as a visible object in 'objectClass=*' searches, -- * so long as we have List Contents (LC) rights for the object. -- */ -- if (tree->operation == LDB_OP_PRESENT && -- is_attr_in_list(attrs_always_present, attr_name)) { -- return LDB_SUCCESS; -- } -- -- ret = check_attr_access_rights(ctx->mem_ctx, attr_name, ctx->ac, -- ctx->sd, ctx->objectclass, ctx->sid, -- ctx->dn); -- -- /* -- * if the user does not have the rights to view this attribute, then we -- * should not return the object as a search result, i.e. act as if the -- * object doesn't exist (for this particular user, at least) -- */ -- if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { -- ctx->suppress_result = true; -- return LDB_SUCCESS; -- } -- -- return ret; --} -- --/* -- * Traverse the search-tree to check that the user has sufficient access rights -- * to view all the attributes. -- */ --static int check_search_ops_access(struct aclread_context *ac, -- TALLOC_CTX *mem_ctx, -- struct security_descriptor *sd, -- const struct dsdb_class *objectclass, -- const struct dom_sid *sid, struct ldb_dn *dn, -- bool *suppress_result) --{ -- int ret; -- struct parse_tree_aclread_ctx ctx = { 0 }; -- struct ldb_parse_tree *tree = ac->req->op.search.tree; -- -- ctx.ac = ac; -- ctx.mem_ctx = mem_ctx; -- ctx.suppress_result = false; -- ctx.sid = sid; -- ctx.dn = dn; -- ctx.sd = sd; -- ctx.objectclass = objectclass; -- -- /* walk the search tree, checking each attribute as we go */ -- ret = ldb_parse_tree_walk(tree, parse_tree_check_attr_access, &ctx); -- -- /* return whether this search result should be hidden to this user */ -- *suppress_result = ctx.suppress_result; -- return ret; --} -- - /* - * Whether this attribute was added to perform access checks and must be - * removed. -@@ -650,17 +723,14 @@ static bool should_remove_attr(const char *attr, const struct aclread_context *a - - static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - { -- struct ldb_context *ldb; - struct aclread_context *ac; -+ struct aclread_private *private_data = NULL; - struct ldb_message *msg; - int ret; - unsigned int i; - struct access_check_context acl_ctx; -- TALLOC_CTX *tmp_ctx; -- bool suppress_result = false; - - ac = talloc_get_type_abort(req->context, struct aclread_context); -- ldb = ldb_module_get_ctx(ac->module); - if (!ares) { - return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); - } -@@ -668,14 +738,9 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } -- tmp_ctx = talloc_new(ac); - switch (ares->type) { - case LDB_REPLY_ENTRY: - msg = ares->message; -- ret = setup_access_check_context(ac, msg, &acl_ctx); -- if (ret != LDB_SUCCESS) { -- return ret; -- } - - if (!ldb_dn_is_null(msg->dn)) { - /* -@@ -684,132 +749,88 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - */ - ret = aclread_check_object_visible(ac, msg, req); - if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { -- talloc_free(tmp_ctx); - return LDB_SUCCESS; - } else if (ret != LDB_SUCCESS) { -+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - ldb_debug_set(ldb, LDB_DEBUG_FATAL, - "acl_read: %s check parent %s - %s\n", - ldb_dn_get_linearized(msg->dn), - ldb_strerror(ret), - ldb_errstring(ldb)); -- goto fail; -+ return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - - /* for every element in the message check RP */ -- for (i=0; i < msg->num_elements; i++) { -- const struct dsdb_attribute *attr; -- uint32_t access_mask; -- attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, -- msg->elements[i].name); -- if (!attr) { -- ldb_debug_set(ldb, LDB_DEBUG_FATAL, -- "acl_read: %s cannot find attr[%s] in of schema\n", -- ldb_dn_get_linearized(msg->dn), -- msg->elements[i].name); -- ret = LDB_ERR_OPERATIONS_ERROR; -- goto fail; -- } -+ for (i = 0; i < msg->num_elements; ++i) { -+ struct ldb_message_element *el = &msg->elements[i]; -+ - /* Remove attributes added to perform access checks. */ -- if (should_remove_attr(msg->elements[i].name, ac)) { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -+ if (should_remove_attr(el->name, ac)) { -+ ldb_msg_element_mark_inaccessible(el); - continue; - } - -- access_mask = get_attr_access_mask(attr, ac->sd_flags); -- -- if (access_mask == 0) { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -+ if (acl_element_is_access_checked(el)) { -+ /* We will have already checked this attribute. */ - continue; - } - -- ret = acl_check_access_on_attribute(ac->module, -- tmp_ctx, -- acl_ctx.sd, -- acl_ctx.sid, -- access_mask, -- attr, -- objectclass); -- - /* -- * Dirsync control needs the replpropertymetadata attribute -- * so return it as it will be removed by the control -- * in anycase. -+ * We need to fetch the security descriptor to check -+ * this attribute. - */ -- if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { -- bool in_search_filter; -- -- /* check if attr is part of the search filter */ -- in_search_filter = dsdb_attr_in_parse_tree(ac->req->op.search.tree, -- msg->elements[i].name); -- -- if (in_search_filter) { -- -- /* -- * We are doing dirysnc answers -- * and the object shouldn't be returned (normally) -- * but we will return it without replPropertyMetaData -- * so that the dirysync module will do what is needed -- * (remove the object if it is not deleted, or return -- * just the objectGUID if it's deleted). -- */ -- if (ac->indirsync) { -- ldb_msg_remove_attr(msg, "replPropertyMetaData"); -- break; -- } else { -- -- /* do not return this entry */ -- talloc_free(tmp_ctx); -- return LDB_SUCCESS; -- } -- } else { -- ldb_msg_element_mark_inaccessible(&msg->elements[i]); -- } -- } else if (ret != LDB_SUCCESS) { -- ldb_debug_set(ldb, LDB_DEBUG_FATAL, -- "acl_read: %s check attr[%s] gives %s - %s\n", -- ldb_dn_get_linearized(msg->dn), -- msg->elements[i].name, -- ldb_strerror(ret), -- ldb_errstring(ldb)); -- goto fail; -- } -+ break; - } - -- /* -- * check access rights for the search attributes, as well as the -- * attribute values actually being returned -- */ -- ret = check_search_ops_access(ac, tmp_ctx, acl_ctx.sd, acl_ctx.objectclass, acl_ctx.sid, -- msg->dn, &suppress_result); -+ if (i == msg->num_elements) { -+ /* All elements have been checked. */ -+ goto reply_entry_done; -+ } -+ -+ ret = setup_access_check_context(ac, msg, &acl_ctx); - if (ret != LDB_SUCCESS) { -- ldb_debug_set(ldb, LDB_DEBUG_FATAL, -- "acl_read: %s check search ops %s - %s\n", -- ldb_dn_get_linearized(msg->dn), -- ldb_strerror(ret), ldb_errstring(ldb)); -- goto fail; -+ return ret; - } - -- if (suppress_result) { -+ private_data = talloc_get_type_abort(ldb_module_get_private(ac->module), -+ struct aclread_private); -+ -+ for (/* begin where we left off */; i < msg->num_elements; ++i) { -+ struct ldb_message_element *el = &msg->elements[i]; -+ -+ /* Remove attributes added to perform access checks. */ -+ if (should_remove_attr(el->name, ac)) { -+ ldb_msg_element_mark_inaccessible(el); -+ continue; -+ } -+ -+ if (acl_element_is_access_checked(el)) { -+ /* We will have already checked this attribute. */ -+ continue; -+ } - - /* -- * As per the above logic, we strip replPropertyMetaData -- * out of the msg so that the dirysync module will do -- * what is needed (return just the objectGUID if it's, -- * deleted, or remove the object if it is not). -+ * We need to check whether the attribute is secret, -+ * confidential, or access-controlled. - */ -- if (ac->indirsync) { -- ldb_msg_remove_attr(msg, "replPropertyMetaData"); -- } else { -- talloc_free(tmp_ctx); -- return LDB_SUCCESS; -+ ret = acl_redact_attr(ac, -+ el, -+ ac, -+ private_data, -+ msg, -+ ac->schema, -+ acl_ctx.sd, -+ acl_ctx.sid, -+ acl_ctx.objectclass); -+ if (ret != LDB_SUCCESS) { -+ return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - -+ reply_entry_done: - ldb_msg_remove_inaccessible(msg); - -- talloc_free(tmp_ctx); -- - ac->num_entries++; - return ldb_module_send_entry(ac->req, msg, ares->controls); - case LDB_REPLY_REFERRAL: -@@ -830,9 +851,6 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) - - } - return LDB_SUCCESS; --fail: -- talloc_free(tmp_ctx); -- return ldb_module_done(ac->req, NULL, NULL, ret); - } - - -@@ -843,7 +861,6 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - struct aclread_context *ac; - struct ldb_request *down_req; - struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); -- uint32_t flags = ldb_req_get_custom_flags(req); - struct ldb_result *res; - struct aclread_private *p; - bool need_sd = false; -@@ -878,15 +895,6 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - } - ac->module = module; - ac->req = req; -- ac->schema = dsdb_get_schema(ldb, req); -- if (flags & DSDB_ACL_CHECKS_DIRSYNC_FLAG) { -- ac->indirsync = true; -- } else { -- ac->indirsync = false; -- } -- if (!ac->schema) { -- return ldb_operr(ldb); -- } - - attrs = req->op.search.attrs; - if (attrs == NULL) { -@@ -943,7 +951,7 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - ac->added_nTSecurityDescriptor = true; - } - -- ac->attrs = req->op.search.attrs; -+ ac->am_administrator = dsdb_module_am_administrator(module); - - /* check accessibility of base */ - if (!ldb_dn_is_null(req->op.search.base)) { -@@ -987,19 +995,270 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - return LDB_ERR_OPERATIONS_ERROR; - } - -+ /* -+ * We provide 'ac' as the control value, which is then used by the -+ * callback to avoid double-work. -+ */ -+ ret = ldb_request_add_control(down_req, DSDB_CONTROL_ACL_READ_OID, false, ac); -+ if (ret != LDB_SUCCESS) { -+ return ldb_error(ldb, ret, -+ "acl_read: Error adding acl_read control."); -+ } -+ - return ldb_next_request(module, down_req); - } - -+/* -+ * Here we mark inaccessible attributes known to be looked for in the -+ * filter. This only redacts attributes found in the search expression. If any -+ * extended attribute match rules examine different attributes without their own -+ * access control checks, a security bypass is possible. -+ */ -+static int acl_redact_msg_for_filter(struct ldb_module *module, struct ldb_request *req, struct ldb_message *msg) -+{ -+ struct ldb_context *ldb = ldb_module_get_ctx(module); -+ const struct aclread_private *private_data = NULL; -+ struct ldb_control *control = NULL; -+ struct aclread_context *ac = NULL; -+ struct access_check_context acl_ctx; -+ int ret; -+ unsigned i; -+ -+ /* -+ * The private data contains a list of attributes which are to be -+ * considered secret. -+ */ -+ private_data = talloc_get_type(ldb_module_get_private(module), struct aclread_private); -+ if (private_data == NULL) { -+ return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, -+ "aclread_private data is missing"); -+ } -+ if (!private_data->enabled) { -+ return LDB_SUCCESS; -+ } -+ -+ control = ldb_request_get_control(req, DSDB_CONTROL_ACL_READ_OID); -+ if (control == NULL) { -+ /* -+ * We've bypassed the acl_read module for this request, and -+ * should skip redaction in this case. -+ */ -+ return LDB_SUCCESS; -+ } -+ -+ ac = talloc_get_type_abort(control->data, struct aclread_context); -+ -+ if (!ac->got_tree_attrs) { -+ ret = ldb_parse_tree_collect_acl_attrs(module, ac, &ac->tree_attrs, req->op.search.tree); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ ac->got_tree_attrs = true; -+ } -+ -+ for (i = 0; i < msg->num_elements; ++i) { -+ struct ldb_message_element *el = &msg->elements[i]; -+ -+ /* Is the attribute mentioned in the search expression? */ -+ if (attr_in_vec(&ac->tree_attrs, el->name)) { -+ /* -+ * We need to fetch the security descriptor to check -+ * this element. -+ */ -+ break; -+ } -+ -+ /* -+ * This attribute is not in the search filter, so we can leave -+ * handling it till aclread_callback(), by which time we know -+ * this object is a match. This saves work checking ACLs if the -+ * search is unindexed and most objects don't match the filter. -+ */ -+ } -+ -+ if (i == msg->num_elements) { -+ /* All elements have been checked. */ -+ return LDB_SUCCESS; -+ } -+ -+ ret = setup_access_check_context(ac, msg, &acl_ctx); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ -+ /* For every element in the message and the parse tree, check RP. */ -+ -+ for (/* begin where we left off */; i < msg->num_elements; ++i) { -+ struct ldb_message_element *el = &msg->elements[i]; -+ -+ /* Is the attribute mentioned in the search expression? */ -+ if (!attr_in_vec(&ac->tree_attrs, el->name)) { -+ /* -+ * If not, leave it for later and check the next -+ * attribute. -+ */ -+ continue; -+ } -+ -+ /* -+ * We need to check whether the attribute is secret, -+ * confidential, or access-controlled. -+ */ -+ ret = acl_redact_attr(ac, -+ el, -+ ac, -+ private_data, -+ msg, -+ ac->schema, -+ acl_ctx.sd, -+ acl_ctx.sid, -+ acl_ctx.objectclass); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ -+ acl_element_mark_access_checked(el); -+ } -+ -+ return LDB_SUCCESS; -+} -+ - static int aclread_init(struct ldb_module *module) - { - struct ldb_context *ldb = ldb_module_get_ctx(module); -+ unsigned int i, n, j; -+ TALLOC_CTX *mem_ctx = NULL; -+ int ret; -+ bool userPassword_support; -+ static const char * const attrs[] = { "passwordAttribute", NULL }; -+ static const char * const secret_attrs[] = { -+ DSDB_SECRET_ATTRIBUTES -+ }; -+ struct ldb_result *res; -+ struct ldb_message *msg; -+ struct ldb_message_element *password_attributes; - struct aclread_private *p = talloc_zero(module, struct aclread_private); - if (p == NULL) { - return ldb_module_oom(module); - } - p->enabled = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), NULL, "acl", "search", true); -+ -+ ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); -+ if (ret != LDB_SUCCESS) { -+ ldb_debug(ldb, LDB_DEBUG_ERROR, -+ "acl_module_init: Unable to register sd_flags control with rootdse!\n"); -+ return ldb_operr(ldb); -+ } -+ - ldb_module_set_private(module, p); -- return ldb_next_init(module); -+ -+ mem_ctx = talloc_new(module); -+ if (!mem_ctx) { -+ return ldb_oom(ldb); -+ } -+ -+ ret = dsdb_module_search_dn(module, mem_ctx, &res, -+ ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"), -+ attrs, -+ DSDB_FLAG_NEXT_MODULE | -+ DSDB_FLAG_AS_SYSTEM, -+ NULL); -+ if (ret != LDB_SUCCESS) { -+ goto done; -+ } -+ if (res->count == 0) { -+ goto done; -+ } -+ -+ if (res->count > 1) { -+ talloc_free(mem_ctx); -+ return LDB_ERR_CONSTRAINT_VIOLATION; -+ } -+ -+ msg = res->msgs[0]; -+ -+ password_attributes = ldb_msg_find_element(msg, "passwordAttribute"); -+ if (!password_attributes) { -+ goto done; -+ } -+ p->password_attrs = talloc_array(p, const char *, -+ password_attributes->num_values + -+ ARRAY_SIZE(secret_attrs) + 1); -+ if (!p->password_attrs) { -+ talloc_free(mem_ctx); -+ return ldb_oom(ldb); -+ } -+ -+ n = 0; -+ for (i=0; i < password_attributes->num_values; i++) { -+ p->password_attrs[n] = (const char *)password_attributes->values[i].data; -+ talloc_steal(p->password_attrs, password_attributes->values[i].data); -+ n++; -+ } -+ -+ for (i=0; i < ARRAY_SIZE(secret_attrs); i++) { -+ bool found = false; -+ -+ for (j=0; j < n; j++) { -+ if (strcasecmp(p->password_attrs[j], secret_attrs[i]) == 0) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (found) { -+ continue; -+ } -+ -+ p->password_attrs[n] = talloc_strdup(p->password_attrs, -+ secret_attrs[i]); -+ if (p->password_attrs[n] == NULL) { -+ talloc_free(mem_ctx); -+ return ldb_oom(ldb); -+ } -+ n++; -+ } -+ p->password_attrs[n] = NULL; -+ -+ ret = ldb_register_redact_callback(ldb, acl_redact_msg_for_filter, module); -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ -+done: -+ talloc_free(mem_ctx); -+ ret = ldb_next_init(module); -+ -+ if (ret != LDB_SUCCESS) { -+ return ret; -+ } -+ -+ if (p->password_attrs != NULL) { -+ /* -+ * Check this after the modules have be initialised so we can -+ * actually read the backend DB. -+ */ -+ userPassword_support = dsdb_user_password_support(module, -+ module, -+ NULL); -+ if (!userPassword_support) { -+ /* -+ * Remove the userPassword attribute, as it is not -+ * considered secret. -+ */ -+ for (i = 0; p->password_attrs[i] != NULL; ++i) { -+ if (ldb_attr_cmp(p->password_attrs[i], "userPassword") == 0) { -+ break; -+ } -+ } -+ -+ /* Shift following elements backwards by one. */ -+ for (; p->password_attrs[i] != NULL; ++i) { -+ p->password_attrs[i] = p->password_attrs[i + 1]; -+ } -+ } -+ } -+ return ret; - } - - static const struct ldb_module_ops ldb_aclread_module_ops = { -diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h -index 3db7704307f..f22b4d99972 100644 ---- a/source4/dsdb/samdb/samdb.h -+++ b/source4/dsdb/samdb/samdb.h -@@ -232,6 +232,8 @@ struct dsdb_control_transaction_identifier { - */ - #define DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID "1.3.6.1.4.1.7165.4.3.35" - -+#define DSDB_CONTROL_ACL_READ_OID "1.3.6.1.4.1.7165.4.3.37" -+ - #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1" - struct dsdb_extended_replicated_object { - struct ldb_message *msg; -diff --git a/source4/dsdb/tests/python/confidential_attr.py b/source4/dsdb/tests/python/confidential_attr.py -index 031c9690ba6..6889d5a5560 100755 ---- a/source4/dsdb/tests/python/confidential_attr.py -+++ b/source4/dsdb/tests/python/confidential_attr.py -@@ -490,7 +490,7 @@ class ConfidentialAttrTest(ConfidentialAttrCommon): - self.make_attr_confidential() - - self.assert_conf_attr_searches(has_rights_to=0) -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - self.assert_attr_visible(expect_attr=False) - -@@ -503,7 +503,7 @@ class ConfidentialAttrTest(ConfidentialAttrCommon): - self.make_attr_confidential() - - self.assert_conf_attr_searches(has_rights_to=0) -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - self.assert_attr_visible(expect_attr=False) - -@@ -566,7 +566,7 @@ class ConfidentialAttrTest(ConfidentialAttrCommon): - self.make_attr_confidential() - - self.assert_conf_attr_searches(has_rights_to=0) -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - self.assert_attr_visible(expect_attr=False) - -@@ -741,7 +741,7 @@ class ConfidentialAttrTestDenyAcl(ConfidentialAttrCommon): - - # the user shouldn't be able to see the attribute anymore - self.assert_conf_attr_searches(has_rights_to="deny-one") -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to="deny-one", - dc_mode=dc_mode) - self.assert_attr_visible(expect_attr=False) -@@ -917,7 +917,7 @@ class ConfidentialAttrTestDirsync(ConfidentialAttrCommon): - - self.assert_conf_attr_searches(has_rights_to=0) - self.assert_attr_visible(expect_attr=False) -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - - # as a final sanity-check, make sure the admin can still see the attr -@@ -1012,7 +1012,7 @@ class ConfidentialAttrTestDirsync(ConfidentialAttrCommon): - # check we can't see the objects now, even with using dirsync controls - self.assert_conf_attr_searches(has_rights_to=0) - self.assert_attr_visible(expect_attr=False) -- dc_mode = self.guess_dc_mode() -+ dc_mode = DC_MODE_RETURN_ALL - self.assert_negative_searches(has_rights_to=0, dc_mode=dc_mode) - - # now delete the users (except for the user whose LDB connection -diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif -index 79800bfd6df..27c7e9dbb47 100644 ---- a/source4/setup/schema_samba4.ldif -+++ b/source4/setup/schema_samba4.ldif -@@ -233,6 +233,7 @@ - #Allocated: DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID 1.3.6.1.4.1.7165.4.3.34 - #Allocated: DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID 1.3.6.1.4.1.7165.4.3.35 - #Allocated: DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID 1.3.6.1.4.1.7165.4.3.36 -+#Allocated: DSDB_CONTROL_ACL_READ_OID 1.3.6.1.4.1.7165.4.3.37 - - - # Extended 1.3.6.1.4.1.7165.4.4.x --- -2.25.1 \ No newline at end of file diff --git a/backport-0027-CVE-2023-0614.patch b/backport-0027-CVE-2023-0614.patch deleted file mode 100644 index dffacf7c4110f3eeb4340527b123787b4ad151b6..0000000000000000000000000000000000000000 --- a/backport-0027-CVE-2023-0614.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 976b0c37d82daf1269664a1fce8dfcca5770456b Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Mon, 27 Feb 2023 13:31:44 +1300 -Subject: [PATCH 25/34] CVE-2023-0614 s4-acl: Avoid calling - dsdb_module_am_system() if we can help it - -If the AS_SYSTEM control is present, we know we have system privileges, -and have no need to call dsdb_module_am_system(). - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 8ca8607b925..6dcc3c9b36e 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -860,7 +860,7 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - int ret; - struct aclread_context *ac; - struct ldb_request *down_req; -- struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); -+ bool am_system; - struct ldb_result *res; - struct aclread_private *p; - bool need_sd = false; -@@ -877,11 +877,16 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) - ldb = ldb_module_get_ctx(module); - p = talloc_get_type(ldb_module_get_private(module), struct aclread_private); - -+ am_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID) != NULL; -+ if (!am_system) { -+ am_system = dsdb_module_am_system(module); -+ } -+ - /* skip access checks if we are system or system control is supplied - * or this is not LDAP server request */ - if (!p || !p->enabled || -- dsdb_module_am_system(module) -- || as_system || !is_untrusted) { -+ am_system || -+ !is_untrusted) { - return ldb_next_request(module, req); - } - /* no checks on special dn */ --- -2.25.1 \ No newline at end of file diff --git a/backport-0028-CVE-2023-0614.patch b/backport-0028-CVE-2023-0614.patch deleted file mode 100644 index 4ced8ae00513820ef96768b1442b79643ae9a45b..0000000000000000000000000000000000000000 --- a/backport-0028-CVE-2023-0614.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 8cf6c358e27a3926397e0d5fbb562e76926589d9 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Thu, 16 Feb 2023 12:35:34 +1300 -Subject: [PATCH 26/34] CVE-2023-0614 ldb: Use binary search to check whether - attribute is secret - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/acl_read.c | 56 ++++++++++++++--------- - 1 file changed, 35 insertions(+), 21 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c -index 6dcc3c9b36e..21f72fbe720 100644 ---- a/source4/dsdb/samdb/ldb_modules/acl_read.c -+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c -@@ -79,6 +79,7 @@ struct aclread_private { - struct security_descriptor *sd_cached; - struct ldb_val sd_cached_blob; - const char **password_attrs; -+ size_t num_password_attrs; - }; - - struct access_check_context { -@@ -512,22 +513,18 @@ static int aclread_get_sd_from_ldb_message(struct aclread_context *ac, - /* Check whether the attribute is a password attribute. */ - static bool attr_is_secret(const char *attr, const struct aclread_private *private_data) - { -- unsigned i; -+ const char **found = NULL; - - if (private_data->password_attrs == NULL) { - return false; - } - -- for (i = 0; private_data->password_attrs[i] != NULL; ++i) { -- const char *password_attr = private_data->password_attrs[i]; -- if (ldb_attr_cmp(attr, password_attr) != 0) { -- continue; -- } -- -- return true; -- } -- -- return false; -+ BINARY_ARRAY_SEARCH_V(private_data->password_attrs, -+ private_data->num_password_attrs, -+ attr, -+ ldb_attr_cmp, -+ found); -+ return found != NULL; - } - - /* -@@ -1128,6 +1125,14 @@ static int acl_redact_msg_for_filter(struct ldb_module *module, struct ldb_reque - return LDB_SUCCESS; - } - -+static int ldb_attr_cmp_fn(const void *_a, const void *_b) -+{ -+ const char * const *a = _a; -+ const char * const *b = _b; -+ -+ return ldb_attr_cmp(*a, *b); -+} -+ - static int aclread_init(struct ldb_module *module) - { - struct ldb_context *ldb = ldb_module_get_ctx(module); -@@ -1188,7 +1193,7 @@ static int aclread_init(struct ldb_module *module) - } - p->password_attrs = talloc_array(p, const char *, - password_attributes->num_values + -- ARRAY_SIZE(secret_attrs) + 1); -+ ARRAY_SIZE(secret_attrs)); - if (!p->password_attrs) { - talloc_free(mem_ctx); - return ldb_oom(ldb); -@@ -1223,7 +1228,10 @@ static int aclread_init(struct ldb_module *module) - } - n++; - } -- p->password_attrs[n] = NULL; -+ p->num_password_attrs = n; -+ -+ /* Sort the password attributes so we can use binary search. */ -+ TYPESAFE_QSORT(p->password_attrs, p->num_password_attrs, ldb_attr_cmp_fn); - - ret = ldb_register_redact_callback(ldb, acl_redact_msg_for_filter, module); - if (ret != LDB_SUCCESS) { -@@ -1247,19 +1255,25 @@ done: - module, - NULL); - if (!userPassword_support) { -+ const char **found = NULL; -+ - /* - * Remove the userPassword attribute, as it is not - * considered secret. - */ -- for (i = 0; p->password_attrs[i] != NULL; ++i) { -- if (ldb_attr_cmp(p->password_attrs[i], "userPassword") == 0) { -- break; -+ BINARY_ARRAY_SEARCH_V(p->password_attrs, -+ p->num_password_attrs, -+ "userPassword", -+ ldb_attr_cmp, -+ found); -+ if (found != NULL) { -+ size_t found_idx = found - p->password_attrs; -+ -+ /* Shift following elements backwards by one. */ -+ for (i = found_idx; i < p->num_password_attrs - 1; ++i) { -+ p->password_attrs[i] = p->password_attrs[i + 1]; - } -- } -- -- /* Shift following elements backwards by one. */ -- for (; p->password_attrs[i] != NULL; ++i) { -- p->password_attrs[i] = p->password_attrs[i + 1]; -+ --p->num_password_attrs; - } - } - } --- -2.25.1 \ No newline at end of file diff --git a/backport-0029-CVE-2023-0614.patch b/backport-0029-CVE-2023-0614.patch deleted file mode 100644 index bdd885b4904822bc2c8d884ecc4a64041b8b50b2..0000000000000000000000000000000000000000 --- a/backport-0029-CVE-2023-0614.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 94efa3fc3053a623a7a5c3a4a6428356bc334152 Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb-samba/ldb_matching_rules.c | 5 --- - lib/ldb/common/ldb_match.c | 56 +++++++++++++++++------------- - 2 files changed, 31 insertions(+), 30 deletions(-) - -diff --git a/lib/ldb-samba/ldb_matching_rules.c b/lib/ldb-samba/ldb_matching_rules.c -index 0c4c31e49f9..b86594c1823 100644 ---- a/lib/ldb-samba/ldb_matching_rules.c -+++ b/lib/ldb-samba/ldb_matching_rules.c -@@ -87,11 +87,6 @@ static int ldb_eval_transitive_filter_helper(TALLOC_CTX *mem_ctx, - return LDB_SUCCESS; - } - -- if (ldb_msg_element_is_inaccessible(el)) { -- *matched = false; -- return LDB_SUCCESS; -- } -- - /* - * If the value to match is present in the attribute values of the - * current entry being visited, set matched to true and return OK -diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c -index 17314f1b9ca..645cb695ef1 100644 ---- a/lib/ldb/common/ldb_match.c -+++ b/lib/ldb/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;inum_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;iu.list.num_elements;i++) { --- -2.25.1 \ No newline at end of file diff --git a/backport-0030-CVE-2023-0614.patch b/backport-0030-CVE-2023-0614.patch deleted file mode 100644 index 8534930bf509805dbd504083b6d0aa5e72261a30..0000000000000000000000000000000000000000 --- a/backport-0030-CVE-2023-0614.patch +++ /dev/null @@ -1,155 +0,0 @@ -From a0c888bd0ed2ec5b4d84f9df241bebd5d428818c Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -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 -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb/common/ldb_match.c | 8 +++--- - lib/ldb/include/ldb_private.h | 8 ++++++ - lib/ldb/ldb_key_value/ldb_kv_index.c | 40 +++++++++++++++------------ - lib/ldb/ldb_key_value/ldb_kv_search.c | 14 ++++++++-- - 4 files changed, 47 insertions(+), 23 deletions(-) - -diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c -index 645cb695ef1..8e27ecbe723 100644 ---- a/lib/ldb/common/ldb_match.c -+++ b/lib/ldb/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/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h -index b0a42f6421c..5e29de34f79 100644 ---- a/lib/ldb/include/ldb_private.h -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c -index 163052fecf7..aac0913f431 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_index.c -+++ b/lib/ldb/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/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c -index d187ba223e1..27f68caef01 100644 ---- a/lib/ldb/ldb_key_value/ldb_kv_search.c -+++ b/lib/ldb/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 \ No newline at end of file diff --git a/backport-0031-CVE-2023-0614.patch b/backport-0031-CVE-2023-0614.patch deleted file mode 100644 index 6d808bc278ec0a939631795ee3648421da9216e3..0000000000000000000000000000000000000000 --- a/backport-0031-CVE-2023-0614.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 62d100b64a25c740187f687dd058a543d43984ec Mon Sep 17 00:00:00 2001 -From: Joseph Sutton -Date: Fri, 24 Feb 2023 10:03:25 +1300 -Subject: [PATCH 29/34] CVE-2023-0614 s4-dsdb: Treat confidential attributes as - unindexed - -In the unlikely case that someone adds a confidential indexed attribute -to the schema, LDAP search expressions on that attribute could disclose -information via timing differences. Let's not use the index for searches -on confidential attributes. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Joseph Sutton -Reviewed-by: Andrew Bartlett - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/samdb/ldb_modules/extended_dn_in.c | 10 +++++++++- - source4/dsdb/schema/schema_description.c | 7 +++++++ - source4/dsdb/schema/schema_init.c | 11 +++++++++-- - source4/dsdb/schema/schema_set.c | 9 ++++++++- - 4 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -index 1dc1e1f2d42..248bb66f039 100644 ---- a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c -@@ -423,7 +423,15 @@ static int extended_dn_filter_callback(struct ldb_parse_tree *tree, void *privat - guid_val = ldb_dn_get_extended_component(dn, "GUID"); - sid_val = ldb_dn_get_extended_component(dn, "SID"); - -- if (!guid_val && !sid_val && (attribute->searchFlags & SEARCH_FLAG_ATTINDEX)) { -+ /* -+ * Is the attribute indexed? By treating confidential attributes -+ * as unindexed, we force searches to go through the unindexed -+ * search path, avoiding observable timing differences. -+ */ -+ if (!guid_val && !sid_val && -+ (attribute->searchFlags & SEARCH_FLAG_ATTINDEX) && -+ !(attribute->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) -+ { - /* if it is indexed, then fixing the string DN will do - no good here, as we will not find the attribute in - the index. So for now fall through to a standard DN -diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c -index 243a02a15f3..5fc70154bf8 100644 ---- a/source4/dsdb/schema/schema_description.c -+++ b/source4/dsdb/schema/schema_description.c -@@ -160,6 +160,13 @@ char *schema_attribute_to_extendedInfo(TALLOC_CTX *mem_ctx, const struct dsdb_at - attribute->rangeUpper, - GUID_hexstring(tmp_ctx, &attribute->schemaIDGUID), - GUID_hexstring(tmp_ctx, &attribute->attributeSecurityGUID), -+ /* -+ * We actually ignore the indexed -+ * flag for confidential -+ * attributes, but we'll include -+ * it for the purposes of -+ * description. -+ */ - (attribute->searchFlags & SEARCH_FLAG_ATTINDEX), - attribute->systemOnly); - talloc_free(tmp_ctx); -diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c -index a3b00497b6b..c8197b86306 100644 ---- a/source4/dsdb/schema/schema_init.c -+++ b/source4/dsdb/schema/schema_init.c -@@ -514,8 +514,15 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, - if (attr->isSingleValued) { - a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE; - } -- -- if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) { -+ -+ /* -+ * Is the attribute indexed? By treating confidential attributes as -+ * unindexed, we force searches to go through the unindexed search path, -+ * avoiding observable timing differences. -+ */ -+ if (attr->searchFlags & SEARCH_FLAG_ATTINDEX && -+ !(attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) -+ { - a->flags |= LDB_ATTR_FLAG_INDEXED; - } - -diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c -index 45faa0912ec..03cf2405595 100644 ---- a/source4/dsdb/schema/schema_set.c -+++ b/source4/dsdb/schema/schema_set.c -@@ -221,7 +221,14 @@ int dsdb_schema_set_indices_and_attributes(struct ldb_context *ldb, - break; - } - -- if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) { -+ /* -+ * Is the attribute indexed? By treating confidential attributes -+ * as unindexed, we force searches to go through the unindexed -+ * search path, avoiding observable timing differences. -+ */ -+ if (attr->searchFlags & SEARCH_FLAG_ATTINDEX && -+ !(attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) -+ { - /* - * When preparing to downgrade Samba, we need to write - * out an LDB without the new key word ORDERED_INTEGER. --- -2.25.1 \ No newline at end of file diff --git a/backport-0032-CVE-2023-0614.patch b/backport-0032-CVE-2023-0614.patch deleted file mode 100644 index c37f48e21a09cfb1228b44196fbf0f46b0cd3f59..0000000000000000000000000000000000000000 --- a/backport-0032-CVE-2023-0614.patch +++ /dev/null @@ -1,49 +0,0 @@ -From d857b406e44254b37aa91d0c8d226e417ce123ce Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Thu, 2 Mar 2023 16:31:17 +1300 -Subject: [PATCH 30/34] CVE-2023-0614 dsdb: Add DSDB_MARK_REQ_UNTRUSTED - -This will allow our dsdb helper search functions to mark the new -request as untrusted, forcing read ACL evaluation (per current behaviour). - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - source4/dsdb/common/util.c | 4 ++++ - source4/dsdb/common/util.h | 1 + - 2 files changed, 5 insertions(+) - -diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c -index b556f06cb63..39b29cd2a0c 100644 ---- a/source4/dsdb/common/util.c -+++ b/source4/dsdb/common/util.c -@@ -4878,6 +4878,10 @@ int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags) - } - } - -+ if (dsdb_flags & DSDB_MARK_REQ_UNTRUSTED) { -+ ldb_req_mark_untrusted(req); -+ } -+ - return LDB_SUCCESS; - } - -diff --git a/source4/dsdb/common/util.h b/source4/dsdb/common/util.h -index e1854644d53..5bb96d60b3c 100644 ---- a/source4/dsdb/common/util.h -+++ b/source4/dsdb/common/util.h -@@ -43,6 +43,7 @@ - #define DSDB_MODIFY_PARTIAL_REPLICA 0x04000 - #define DSDB_PASSWORD_BYPASS_LAST_SET 0x08000 - #define DSDB_REPLMD_VANISH_LINKS 0x10000 -+#define DSDB_MARK_REQ_UNTRUSTED 0x20000 - - bool is_attr_in_list(const char * const * attrs, const char *attr); - --- -2.25.1 \ No newline at end of file diff --git a/backport-0033-CVE-2023-0614.patch b/backport-0033-CVE-2023-0614.patch deleted file mode 100644 index 409473fbb98c8455e97a76933c151a4ef3b1197f..0000000000000000000000000000000000000000 --- a/backport-0033-CVE-2023-0614.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0151a2a4c4cea64b0d931aa0e227b187abf28280 Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Fri, 3 Mar 2023 16:49:00 +1300 -Subject: [PATCH 31/34] CVE-2023-0614 dsdb: Add pre-cleanup and - self.addCleanup() of OU created in match_rules tests - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb-samba/tests/match_rules.py | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/lib/ldb-samba/tests/match_rules.py b/lib/ldb-samba/tests/match_rules.py -index abf485c9eab..2af1dd6a070 100755 ---- a/lib/ldb-samba/tests/match_rules.py -+++ b/lib/ldb-samba/tests/match_rules.py -@@ -31,11 +31,19 @@ class MatchRulesTests(samba.tests.TestCase): - self.ou_groups = "OU=groups,%s" % self.ou - self.ou_computers = "OU=computers,%s" % self.ou - -+ try: -+ self.ldb.delete(self.ou, ["tree_delete:1"]) -+ except LdbError as e: -+ pass -+ - # Add a organizational unit to create objects - self.ldb.add({ - "dn": self.ou, - "objectclass": "organizationalUnit"}) - -+ self.addCleanup(self.ldb.delete, self.ou, controls=['tree_delete:0']) -+ -+ - # Add the following OU hierarchy and set otherWellKnownObjects, - # which has BinaryDN syntax: - # --- -2.25.1 \ No newline at end of file diff --git a/backport-0034-CVE-2023-0614.patch b/backport-0034-CVE-2023-0614.patch deleted file mode 100644 index 0665c5d5d67a81565748669bbe557cdb581ab0a8..0000000000000000000000000000000000000000 --- a/backport-0034-CVE-2023-0614.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 91ecb27e706ac4500fb0d5242cf412173f8a5e7a Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Thu, 2 Mar 2023 16:51:25 +1300 -Subject: [PATCH 32/34] CVE-2023-0614 lib/ldb-samba: Add test for - SAMBA_LDAP_MATCH_RULE_TRANSITIVE_EVAL / LDAP_MATCHING_RULE_IN_CHAIN with and - ACL hidden attributes - -The chain for transitive evaluation does consider ACLs, avoiding the disclosure of -confidential information. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb-samba/tests/match_rules.py | 127 ++++++++++++---------- - lib/ldb-samba/tests/match_rules_remote.py | 104 ++++++++++++++++++ - source4/selftest/tests.py | 1 + - 3 files changed, 175 insertions(+), 57 deletions(-) - create mode 100755 lib/ldb-samba/tests/match_rules_remote.py - -diff --git a/lib/ldb-samba/tests/match_rules.py b/lib/ldb-samba/tests/match_rules.py -index 2af1dd6a070..2fe6c3e2264 100755 ---- a/lib/ldb-samba/tests/match_rules.py -+++ b/lib/ldb-samba/tests/match_rules.py -@@ -20,13 +20,18 @@ from ldb import SCOPE_BASE, SCOPE_SUBTREE, SCOPE_ONELEVEL - # Windows appear to preserve casing of the RDN and uppercase the other keys. - - --class MatchRulesTests(samba.tests.TestCase): -+class MatchRulesTestsBase(samba.tests.TestCase): - def setUp(self): -- super(MatchRulesTests, self).setUp() -- self.lp = lp -- self.ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp) -+ super().setUp() -+ self.lp = self.sambaopts.get_loadparm() -+ self.creds = self.credopts.get_credentials(self.lp) -+ -+ self.ldb = SamDB(self.host, credentials=self.creds, -+ session_info=system_session(self.lp), -+ lp=self.lp) - self.base_dn = self.ldb.domain_dn() -- self.ou = "OU=matchrulestest,%s" % self.base_dn -+ self.ou_rdn = "OU=matchrulestest" -+ self.ou = self.ou_rdn + "," + self.base_dn - self.ou_users = "OU=users,%s" % self.ou - self.ou_groups = "OU=groups,%s" % self.ou - self.ou_computers = "OU=computers,%s" % self.ou -@@ -212,6 +217,39 @@ class MatchRulesTests(samba.tests.TestCase): - FLAG_MOD_ADD, "member") - self.ldb.modify(m) - -+ # Add a couple of ms-Exch-Configuration-Container to test forward-link -+ # attributes without backward link (addressBookRoots2) -+ # e1 -+ # |--> e2 -+ # | |--> c1 -+ self.ldb.add({ -+ "dn": "cn=e1,%s" % self.ou, -+ "objectclass": "msExchConfigurationContainer"}) -+ self.ldb.add({ -+ "dn": "cn=e2,%s" % self.ou, -+ "objectclass": "msExchConfigurationContainer"}) -+ -+ m = Message() -+ m.dn = Dn(self.ldb, "cn=e2,%s" % self.ou) -+ m["e1"] = MessageElement("cn=c1,%s" % self.ou_computers, -+ FLAG_MOD_ADD, "addressBookRoots2") -+ self.ldb.modify(m) -+ -+ m = Message() -+ m.dn = Dn(self.ldb, "cn=e1,%s" % self.ou) -+ m["e1"] = MessageElement("cn=e2,%s" % self.ou, -+ FLAG_MOD_ADD, "addressBookRoots2") -+ self.ldb.modify(m) -+ -+ -+ -+class MatchRulesTests(MatchRulesTestsBase): -+ def setUp(self): -+ self.sambaopts = sambaopts -+ self.credopts = credopts -+ self.host = host -+ super().setUp() -+ - # The msDS-RevealedUsers is owned by system and cannot be modified - # directly. Set the schemaUpgradeInProgress flag as workaround - # and create this hierarchy: -@@ -251,33 +289,6 @@ class MatchRulesTests(samba.tests.TestCase): - m["e1"] = MessageElement("0", FLAG_MOD_REPLACE, "schemaUpgradeInProgress") - self.ldb.modify(m) - -- # Add a couple of ms-Exch-Configuration-Container to test forward-link -- # attributes without backward link (addressBookRoots2) -- # e1 -- # |--> e2 -- # | |--> c1 -- self.ldb.add({ -- "dn": "cn=e1,%s" % self.ou, -- "objectclass": "msExchConfigurationContainer"}) -- self.ldb.add({ -- "dn": "cn=e2,%s" % self.ou, -- "objectclass": "msExchConfigurationContainer"}) -- -- m = Message() -- m.dn = Dn(self.ldb, "cn=e2,%s" % self.ou) -- m["e1"] = MessageElement("cn=c1,%s" % self.ou_computers, -- FLAG_MOD_ADD, "addressBookRoots2") -- self.ldb.modify(m) -- -- m = Message() -- m.dn = Dn(self.ldb, "cn=e1,%s" % self.ou) -- m["e1"] = MessageElement("cn=e2,%s" % self.ou, -- FLAG_MOD_ADD, "addressBookRoots2") -- self.ldb.modify(m) -- -- def tearDown(self): -- super(MatchRulesTests, self).tearDown() -- self.ldb.delete(self.ou, controls=['tree_delete:0']) - - def test_u1_member_of_g4(self): - # Search without transitive match must return 0 results -@@ -953,8 +964,12 @@ class MatchRulesTests(samba.tests.TestCase): - class MatchRuleConditionTests(samba.tests.TestCase): - def setUp(self): - super(MatchRuleConditionTests, self).setUp() -- self.lp = lp -- self.ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp) -+ self.lp = sambaopts.get_loadparm() -+ self.creds = credopts.get_credentials(self.lp) -+ -+ self.ldb = SamDB(host, credentials=self.creds, -+ session_info=system_session(self.lp), -+ lp=self.lp) - self.base_dn = self.ldb.domain_dn() - self.ou = "OU=matchruleconditiontests,%s" % self.base_dn - self.ou_users = "OU=users,%s" % self.ou -@@ -1753,32 +1768,30 @@ class MatchRuleConditionTests(samba.tests.TestCase): - self.ou_groups, self.ou_computers)) - self.assertEqual(len(res1), 0) - -+if __name__ == "__main__": - --parser = optparse.OptionParser("match_rules.py [options] ") --sambaopts = options.SambaOptions(parser) --parser.add_option_group(sambaopts) --parser.add_option_group(options.VersionOptions(parser)) -- --# use command line creds if available --credopts = options.CredentialsOptions(parser) --parser.add_option_group(credopts) --opts, args = parser.parse_args() --subunitopts = SubunitOptions(parser) --parser.add_option_group(subunitopts) -+ parser = optparse.OptionParser("match_rules.py [options] ") -+ sambaopts = options.SambaOptions(parser) -+ parser.add_option_group(sambaopts) -+ parser.add_option_group(options.VersionOptions(parser)) - --if len(args) < 1: -- parser.print_usage() -- sys.exit(1) -+ # use command line creds if available -+ credopts = options.CredentialsOptions(parser) -+ parser.add_option_group(credopts) -+ opts, args = parser.parse_args() -+ subunitopts = SubunitOptions(parser) -+ parser.add_option_group(subunitopts) - --host = args[0] -+ if len(args) < 1: -+ parser.print_usage() -+ sys.exit(1) - --lp = sambaopts.get_loadparm() --creds = credopts.get_credentials(lp) -+ host = args[0] - --if "://" not in host: -- if os.path.isfile(host): -- host = "tdb://%s" % host -- else: -- host = "ldap://%s" % host -+ if "://" not in host: -+ if os.path.isfile(host): -+ host = "tdb://%s" % host -+ else: -+ host = "ldap://%s" % host - --TestProgram(module=__name__, opts=subunitopts) -+ TestProgram(module=__name__, opts=subunitopts) -diff --git a/lib/ldb-samba/tests/match_rules_remote.py b/lib/ldb-samba/tests/match_rules_remote.py -new file mode 100755 -index 00000000000..122231f2a60 ---- /dev/null -+++ b/lib/ldb-samba/tests/match_rules_remote.py -@@ -0,0 +1,104 @@ -+#!/usr/bin/env python3 -+ -+import optparse -+import sys -+import os -+import samba -+import samba.getopt as options -+ -+from samba.tests.subunitrun import SubunitOptions, TestProgram -+ -+from samba.samdb import SamDB -+from samba.auth import system_session -+from samba import sd_utils -+from samba.ndr import ndr_unpack -+from ldb import Message, MessageElement, Dn, LdbError -+from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE -+from ldb import SCOPE_BASE, SCOPE_SUBTREE, SCOPE_ONELEVEL -+ -+from match_rules import MatchRulesTestsBase -+ -+ -+class MatchRulesTestsUser(MatchRulesTestsBase): -+ def setUp(self): -+ self.sambaopts = sambaopts -+ self.credopts = credopts -+ self.host = host -+ super().setUp() -+ self.sd_utils = sd_utils.SDUtils(self.ldb) -+ -+ self.user_pass = "samba123@" -+ self.match_test_user = "matchtestuser" -+ self.ldb.newuser(self.match_test_user, -+ self.user_pass, -+ userou=self.ou_rdn) -+ user_creds = self.insta_creds(template=self.creds, -+ username=self.match_test_user, -+ userpass=self.user_pass) -+ self.user_ldb = SamDB(host, credentials=user_creds, lp=self.lp) -+ token_res = self.user_ldb.search(scope=SCOPE_BASE, -+ base="", -+ attrs=["tokenGroups"]) -+ self.user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, -+ token_res[0]["tokenGroups"][0]) -+ -+ self.member_attr_guid = "bf9679c0-0de6-11d0-a285-00aa003049e2" -+ -+ def test_with_denied_link(self): -+ -+ # add an ACE that denies the user Read Property (RP) access to -+ # the member attr (which is similar to making the attribute -+ # confidential) -+ ace = "(OD;;RP;{0};;{1})".format(self.member_attr_guid, -+ self.user_sid) -+ g2_dn = Dn(self.ldb, "CN=g2,%s" % self.ou_groups) -+ -+ # add the ACE that denies access to the attr under test -+ self.sd_utils.dacl_add_ace(g2_dn, ace) -+ -+ # Search without transitive match must return 0 results -+ res1 = self.ldb.search("cn=g4,%s" % self.ou_groups, -+ scope=SCOPE_BASE, -+ expression="member=cn=u1,%s" % self.ou_users) -+ self.assertEqual(len(res1), 0) -+ -+ # Search with transitive match must return 1 results -+ res1 = self.ldb.search("cn=g4,%s" % self.ou_groups, -+ scope=SCOPE_BASE, -+ expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users) -+ self.assertEqual(len(res1), 1) -+ self.assertEqual(str(res1[0].dn).lower(), ("CN=g4,%s" % self.ou_groups).lower()) -+ -+ # Search as a user match must return 0 results as the intermediate link can't be seen -+ res1 = self.user_ldb.search("cn=g4,%s" % self.ou_groups, -+ scope=SCOPE_BASE, -+ expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users) -+ self.assertEqual(len(res1), 0) -+ -+ -+ -+parser = optparse.OptionParser("match_rules_remote.py [options] ") -+sambaopts = options.SambaOptions(parser) -+parser.add_option_group(sambaopts) -+parser.add_option_group(options.VersionOptions(parser)) -+ -+# use command line creds if available -+credopts = options.CredentialsOptions(parser) -+parser.add_option_group(credopts) -+opts, args = parser.parse_args() -+subunitopts = SubunitOptions(parser) -+parser.add_option_group(subunitopts) -+ -+if len(args) < 1: -+ parser.print_usage() -+ sys.exit(1) -+ -+host = args[0] -+ -+if "://" not in host: -+ if os.path.isfile(host): -+ host = "tdb://%s" % host -+ else: -+ host = "ldap://%s" % host -+ -+TestProgram(module=__name__, opts=subunitopts) -diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py -index c6bf668aa9c..a09945f40da 100755 ---- a/source4/selftest/tests.py -+++ b/source4/selftest/tests.py -@@ -1322,6 +1322,7 @@ for env in ['ad_dc_default:local', 'schema_dc:local']: - plantestsuite_loadlist("samba4.urgent_replication.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(DSDB_PYTEST_DIR, "urgent_replication.py"), '$PREFIX_ABS/ad_dc_ntvfs/private/sam.ldb', '$LOADLIST', '$LISTOPT']) - plantestsuite_loadlist("samba4.ldap.dirsync.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(DSDB_PYTEST_DIR, "dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - plantestsuite_loadlist("samba4.ldap.match_rules.python", "ad_dc_ntvfs", [python, os.path.join(srcdir(), "lib/ldb-samba/tests/match_rules.py"), '$PREFIX_ABS/ad_dc_ntvfs/private/sam.ldb', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) -+plantestsuite_loadlist("samba4.ldap.match_rules.python", "ad_dc_ntvfs", [python, os.path.join(srcdir(), "lib/ldb-samba/tests/match_rules_remote.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - plantestsuite("samba4.ldap.index.python", "none", [python, os.path.join(srcdir(), "lib/ldb-samba/tests/index.py")]) - plantestsuite_loadlist("samba4.ldap.notification.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(DSDB_PYTEST_DIR, "notification.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - plantestsuite_loadlist("samba4.ldap.sites.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) --- -2.25.1 \ No newline at end of file diff --git a/backport-0035-CVE-2023-0614.patch b/backport-0035-CVE-2023-0614.patch deleted file mode 100644 index 1622cbd1fc1a57c3739ca4da86d65ac1067f6b90..0000000000000000000000000000000000000000 --- a/backport-0035-CVE-2023-0614.patch +++ /dev/null @@ -1,39 +0,0 @@ -From bb092fc576868e30edf78136894472f95c4b039d Mon Sep 17 00:00:00 2001 -From: Andrew Bartlett -Date: Thu, 2 Mar 2023 17:24:15 +1300 -Subject: [PATCH 33/34] CVE-2023-0614 lib/ldb-samba Ensure ACLs are evaluated - on SAMBA_LDAP_MATCH_RULE_TRANSITIVE_EVAL / LDAP_MATCHING_RULE_IN_CHAIN - -Setting the LDB_HANDLE_FLAG_UNTRUSTED tells the acl_read module to operate on this request. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 - -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17821 ---- - lib/ldb-samba/ldb_matching_rules.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/lib/ldb-samba/ldb_matching_rules.c b/lib/ldb-samba/ldb_matching_rules.c -index b86594c1823..59d1385f4e3 100644 ---- a/lib/ldb-samba/ldb_matching_rules.c -+++ b/lib/ldb-samba/ldb_matching_rules.c -@@ -67,7 +67,12 @@ static int ldb_eval_transitive_filter_helper(TALLOC_CTX *mem_ctx, - * Note also that we don't have the original request - * here, so we can not apply controls or timeouts here. - */ -- ret = dsdb_search_dn(ldb, tmp_ctx, &res, to_visit->dn, attrs, 0); -+ ret = dsdb_search_dn(ldb, -+ tmp_ctx, -+ &res, -+ to_visit->dn, -+ attrs, -+ DSDB_MARK_REQ_UNTRUSTED); - if (ret != LDB_SUCCESS) { - talloc_free(tmp_ctx); - return ret; --- -2.25.1 \ No newline at end of file diff --git a/backport-CVE-2023-0922.patch b/backport-CVE-2023-0922.patch deleted file mode 100644 index 9133496ebbfb585214e54e55763cd9a879654838..0000000000000000000000000000000000000000 --- a/backport-CVE-2023-0922.patch +++ /dev/null @@ -1,108 +0,0 @@ -From faa7babcd8db9ef14398848d0c398578d1a79d85 Mon Sep 17 00:00:00 2001 -From: Rob van der Linde -Date: Mon, 27 Feb 2023 14:06:23 +1300 -Subject: [PATCH] CVE-2023-0922 set default ldap client sasl wrapping to seal - -This avoids sending new or reset passwords in the clear -(integrity protected only) from samba-tool in particular. - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15315 - -Signed-off-by: Rob van der Linde -Signed-off-by: Andrew Bartlett -Reviewed-by: Joseph Sutton - -Conflict: NA -Reference: https://attachments.samba.org/attachment.cgi?id=17831 ---- - .../ldap/clientldapsaslwrapping.xml | 27 +++++++++---------- - lib/param/loadparm.c | 2 +- - python/samba/tests/auth_log.py | 2 +- - source3/param/loadparm.c | 2 +- - 4 files changed, 16 insertions(+), 17 deletions(-) - -diff --git a/docs-xml/smbdotconf/ldap/clientldapsaslwrapping.xml b/docs-xml/smbdotconf/ldap/clientldapsaslwrapping.xml -index 3152f0682dd..21bd2090057 100644 ---- a/docs-xml/smbdotconf/ldap/clientldapsaslwrapping.xml -+++ b/docs-xml/smbdotconf/ldap/clientldapsaslwrapping.xml -@@ -18,25 +18,24 @@ - - - -- This option is needed in the case of Domain Controllers enforcing -- the usage of signed LDAP connections (e.g. Windows 2000 SP3 or higher). -- LDAP sign and seal can be controlled with the registry key -- "HKLM\System\CurrentControlSet\Services\ -- NTDS\Parameters\LDAPServerIntegrity" -- on the Windows server side. -- -+ This option is needed firstly to secure the privacy of -+ administrative connections from samba-tool, -+ including in particular new or reset passwords for users. For -+ this reason the default is seal. - -- -- Depending on the used KRB5 library (MIT and older Heimdal versions) -- it is possible that the message "integrity only" is not supported. -- In this case, sign is just an alias for -- seal. -+ Additionally, winbindd and the -+ net tool can use LDAP to communicate with -+ Domain Controllers, so this option also controls the level of -+ privacy for those connections. All supported AD DC versions -+ will enforce the usage of at least signed LDAP connections by -+ default, so a value of at least sign is -+ required in practice. - - - -- The default value is sign. That implies synchronizing the time -+ The default value is seal. That implies synchronizing the time - with the KDC in the case of using Kerberos. - - --sign -+seal - -diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c -index 6ab7fa89db7..16cb0d47f31 100644 ---- a/lib/param/loadparm.c -+++ b/lib/param/loadparm.c -@@ -2990,7 +2990,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) - - lpcfg_do_global_parameter(lp_ctx, "ldap debug threshold", "10"); - -- lpcfg_do_global_parameter(lp_ctx, "client ldap sasl wrapping", "sign"); -+ lpcfg_do_global_parameter(lp_ctx, "client ldap sasl wrapping", "seal"); - - lpcfg_do_global_parameter(lp_ctx, "mdns name", "netbios"); - -diff --git a/python/samba/tests/auth_log.py b/python/samba/tests/auth_log.py -index d166b93d90a..8f9f487f82a 100644 ---- a/python/samba/tests/auth_log.py -+++ b/python/samba/tests/auth_log.py -@@ -470,7 +470,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): - def isLastExpectedMessage(msg): - return (msg["type"] == "Authorization" and - msg["Authorization"]["serviceDescription"] == "LDAP" and -- msg["Authorization"]["transportProtection"] == "SIGN" and -+ msg["Authorization"]["transportProtection"] == "SEAL" and - msg["Authorization"]["authType"] == "krb5") - - self.samdb = SamDB(url="ldap://%s" % os.environ["SERVER"], -diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c -index 05a5ae20abe..12718ced9e7 100644 ---- a/source3/param/loadparm.c -+++ b/source3/param/loadparm.c -@@ -756,7 +756,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) - Globals.ldap_debug_level = 0; - Globals.ldap_debug_threshold = 10; - -- Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SIGN; -+ Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SEAL; - - Globals.ldap_server_require_strong_auth = - LDAP_SERVER_REQUIRE_STRONG_AUTH_YES; --- -2.25.1 - diff --git a/samba-4.17.5.tar.asc b/samba-4.17.5.tar.asc deleted file mode 100644 index 6d0b732092ebf4680c154a2535e31267163f36ab..0000000000000000000000000000000000000000 --- a/samba-4.17.5.tar.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEgfXigyvSVFoYl7cTqplEL7aAtiAFAmPSvJEACgkQqplEL7aA -tiDXbA//bPY+2A4y8zPJLibWjRtmv76xTgj1EJMZoC5d7+5PXQfuVhVULGYrxriF -MIF4CtTnMDk20mihnQb03csGpZGvqfBKbZg6jYolqeTmwRDgKXf9dxLxYYBGswPN -JXiF/ZvDQzEorrsz24o7i9Pe44IXpdf7+3RjIXhKjCa2vFQibTndGRhYb0UYiR9S -DELp6V/rmV9/BrYWVhHVnuzROzNWsrXIyu1GPNRWdX6ptJmjq6f8wZUP0NODYsBP -e0+BpXwob795tDSAMBnbnp7ZsHRYgB2/iWDTe19MF5LjHCcPwRWmzfZjiWQuz11D -kg7RUmlTkpU0mrToM+Uyg3Lhc8sayojDTHkIuIPBTuirdKuyP5Zov1wCaPuvf8Ew -LCQlQsC2AVeko8xY7P5ieXrmsfncoKR23S0MaKM6oNXooMJcNFnemMvCsOGGeGCi -HJa1whPdI5Cj3zLB5X35UNMmauS7qWyyj3lS2horg8L/iIQ3R3q+0Xkd5VmX1BXz -EhVDvOnb1F7E9HFlxhZRJFufpnHrGZX6ZYe6BqP8oU092UUU5JMeIqe20wG/dAtX -B91QhITdPDnM4KrSbch9i+BKW1xD8srRXu4yqMTZp6X6dPh6lnzVn6vj4uKNCMwz -2qLa3Rl+cRON1uTeFJXSTHg/diHjKriu3+bCqm0RlHAFLMtvudk= -=gZl3 ------END PGP SIGNATURE----- diff --git a/samba-4.18.5.tar.asc b/samba-4.18.5.tar.asc new file mode 100644 index 0000000000000000000000000000000000000000..587859775ffbb90865d034e21cebf30359780edc --- /dev/null +++ b/samba-4.18.5.tar.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEgfXigyvSVFoYl7cTqplEL7aAtiAFAmS1oTwACgkQqplEL7aA +tiD7yw/9HHvKK8WaLkVptV2NO7MP4lMMYqDvZhi6H1/dU3c37RKLqgOD5DhCDVnG +w0E1d+CvGgzNxmMfaDx6/j+5k49HIsCCeaKZRK//lMEyiI1IO8NczH70COEglA07 +HPvwwUZnYiYZIOaiFyCSVc6L7ojAzQWkVdQQ4/Csz3FwKKZiJDYIgsyrQdeMCMVz +Vp4T8hvlKDzjdrZcx/UY1BcdhweTChpIBeG7OakGkPByjWBzDpkj13xbH5wDuV9i +9uec81DIrjAVErATYVYLStUzgIQ8r9q1DRZlVx201+Rm94BJyRADhXkx/UiHcj47 +YrvHnN7LWnyAiGnTunOMVbRh9divAhosAa3VzMkI6uLEKr6//3rn6bMloNJSf6iI +OeJXw4YkBL9Ukx8Wdz8BEHbr/6oIuN1235fQtkAq7pN4S9X9fkwKpIR3hIc7/STA +RogaoaCmuU7MoFiNcaJdhEWz7qMptE7Ph2V02JIqP5rAd8i0oxH9GV89lrPy7c5t +NQgqyuGojmscgtyi6xp/a0KXKEHeKAZkMohDOqP3vb3Q1FY6yb6xidlhRekZ0PmI +7ACCs2XbCVUtd3/IXrGSBPNOT4/7Crz7ciPGBIMN3PEpjhAFC0Wuzk+bvWcYFs89 +luFcdHDkFWo8y3WM6Q5PGk3i36QJuKV56/crv/rgGVkU+iWfJms= +=ZdTb +-----END PGP SIGNATURE----- diff --git a/samba-4.17.5.tar.gz b/samba-4.18.5.tar.gz similarity index 63% rename from samba-4.17.5.tar.gz rename to samba-4.18.5.tar.gz index 100c6f0cc19c874eaa5b90e01b1162d0f61b9099..e098a0e8bb6e68d83f30e15a11473ffce27e81c5 100644 Binary files a/samba-4.17.5.tar.gz and b/samba-4.18.5.tar.gz differ diff --git a/samba.logrotate b/samba.logrotate index 40f85aa002720e90a4b7331ac0014fbcd381aaf9..43bef68c18910bf920303b833fad87f710ad4514 100644 --- a/samba.logrotate +++ b/samba.logrotate @@ -1,4 +1,4 @@ -/var/log/samba/log.* { +/var/log/samba/*log* { compress dateext maxage 365 diff --git a/samba.spec b/samba.spec index 721074dd058469840d5acfed22992e855b2ea428..d5f88d5cc5cfd550534f433cfd58b14eb3507187 100644 --- a/samba.spec +++ b/samba.spec @@ -2,10 +2,10 @@ %bcond_without clustering %define samba_requires_eq() %(LC_ALL="C" echo '%*' | xargs -r rpm -q --qf 'Requires: %%{name} = %%{epoch}:%%{version}\\n' | sed -e 's/ (none):/ /' -e 's/ 0:/ /' | grep -v "is not") -%global talloc_version 2.3.4 -%global tdb_version 1.4.7 -%global tevent_version 0.13.0 -%global ldb_version 2.6.1-2 +%global talloc_version 2.4.0 +%global tdb_version 1.4.8 +%global tevent_version 0.14.1 +%global ldb_version 2.7.2 %undefine _strict_symbol_defs_build @@ -19,7 +19,7 @@ %global with_vfs_glusterfs 1 %endif -%global libwbc_alternatives_version 0.15 +%global libwbc_alternatives_version 0.16 %global libwbc_alternatives_suffix %nil %if 0%{?__isa_bits} == 64 %global libwbc_alternatives_suffix -64 @@ -39,6 +39,8 @@ %global with_clustering_support 1 %endif +%bcond_with ccache + %global with_winexe 0 %global with_vfs_io_uring 0 @@ -47,11 +49,11 @@ %global samba_depver %{version}-%{release} Name: samba -Version: 4.17.5 -Release: 6 +Version: 4.18.5 +Release: 1 Summary: A suite for Linux to interoperate with Windows -License: GPLv3+ and LGPLv3+ +License: GPL-3.0-or-later AND LGPL-3.0-or-later URL: https://www.samba.org Source0: https://download.samba.org/pub/samba/stable/%{name}-%{version}.tar.gz @@ -66,53 +68,11 @@ Source8: usershares.conf.vendor Source201: README.downgrade -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 -Patch0015: backport-0015-CVE-2023-0614.patch -Patch0016: backport-0016-CVE-2023-0614.patch -Patch0017: backport-0017-CVE-2023-0614.patch -Patch0018: backport-0018-CVE-2023-0614.patch -Patch0019: backport-0019-CVE-2023-0614.patch -Patch0020: backport-0020-CVE-2023-0614.patch -Patch0021: backport-0021-CVE-2023-0614.patch -Patch0022: backport-0022-CVE-2023-0614.patch -Patch0023: backport-0023-CVE-2023-0614.patch -Patch0024: backport-0024-CVE-2023-0614.patch -Patch0025: backport-0025-CVE-2023-0614.patch -Patch0026: backport-0026-CVE-2023-0614.patch -Patch0027: backport-0027-CVE-2023-0614.patch -Patch0028: backport-0028-CVE-2023-0614.patch -Patch0029: backport-0029-CVE-2023-0614.patch -Patch0030: backport-0030-CVE-2023-0614.patch -Patch0031: backport-0031-CVE-2023-0614.patch -Patch0032: backport-0032-CVE-2023-0614.patch -Patch0033: backport-0033-CVE-2023-0614.patch -Patch0034: backport-0034-CVE-2023-0614.patch -Patch0035: backport-0035-CVE-2023-0614.patch -Patch0036: backport-0001-CVE-2023-0225.patch -Patch0037: backport-0002-CVE-2023-0225.patch -Patch0038: backport-0003-CVE-2023-0225.patch -Patch0039: backport-0004-CVE-2023-0225.patch -Patch0040: backport-CVE-2023-0922.patch - - BuildRequires: avahi-devel bison dbus-devel docbook-style-xsl e2fsprogs-devel flex gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel BuildRequires: libcap-devel libicu-devel libcmocka-devel libtirpc-devel libuuid-devel libxslt lmdb ncurses-devel openldap-devel BuildRequires: pam-devel perl-interpreter perl-generators perl(Archive::Tar) perl(Test::More) popt-devel python3-devel python3-setuptools quota-devel -BuildRequires: readline-devel rpcgen rpcsvc-proto-devel sed libtasn1-devel libtasn1-tools xfsprogs-devel xz zlib-devel >= 1.2.3 python3-dns +BuildRequires: readline-devel rpcgen rpcsvc-proto-devel sed libtasn1-devel libtasn1-tools xfsprogs-devel xz zlib-devel >= 1.2.3 python3-dns python3-requests python3-cryptography BuildRequires: gcc make BuildRequires: chrpath %if %{?openEuler:1}0 @@ -135,7 +95,7 @@ BuildRequires: libcephfs-devel %endif %if %{with_dc} -BuildRequires: python3-iso8601 bind krb5-server >= %{required_mit_krb5} python3-pyasn1 >= 0.4.8 +BuildRequires: bind krb5-server >= %{required_mit_krb5} python3-pyasn1 >= 0.4.8 %endif BuildRequires: perl(ExtUtils::MakeMaker) perl(FindBin) perl(Parse::Yapp) libtalloc-devel >= %{talloc_version} python3-talloc-devel >= %{talloc_version} @@ -145,17 +105,13 @@ BuildRequires: libtdb-devel >= %{tdb_version} python3-tdb >= %{tdb_version} BuildRequires: libldb-devel >= %{ldb_version} python3-ldb-devel >= %{ldb_version} %if %{with testsuite} || %{with_dc} -BuildRequires: ldb-tools tdb-tools python3-gpg python3-markdown python3-cryptography +BuildRequires: ldb-tools tdb-tools python3-dateutil python3-gpg python3-markdown %endif %if %{with_vfs_io_uring} BuildRequires: liburing-devel >= 0.4 %endif -%if %{with_dc} -BuildRequires: krb5-server >= %{required_mit_krb5} bind -%endif - Requires: systemd shadow-utils pam %{name}-common = %{samba_depver} Requires: %{name}-common = %{samba_depver} %{name}-common-tools = %{samba_depver} Requires: %{name}-client-libs = %{samba_depver} @@ -385,6 +341,7 @@ This package provides developer tools for the wbclient library. %package -n libwbclient Summary: The winbind client library for %{name} Requires: %{name}-client-libs = %{samba_depver} +Conflicts: sssd-libwbclient < 2.5.1 %description -n libwbclient This package contains the winbind client library from the Samba. @@ -394,6 +351,7 @@ Summary: The development package for the winbind library Requires: libwbclient = %{samba_depver} Provides: samba-winbind-devel = %{samba_depver} Obsoletes: samba-winbind-devel < %{samba_depver} +Conflicts: sssd-libwbclient-devel < 2.5.1 %description -n libwbclient-devel This package provides developer tools for the wbclient library. @@ -404,7 +362,7 @@ This package provides developer tools for the wbclient library. %package -n python3-%{name} Summary: Python3 library package for %{name} Requires: %{name}-client-libs = %{samba_depver} %{name}-common = %{samba_depver} -Requires: python3-talloc python3-tevent python3-tdb python3-ldb python3-dns +Requires: python3-talloc python3-tevent python3-tdb python3-ldb python3-dns python3-requests python3-cryptography Requires: %{name}-libs = %{samba_depver} Obsoletes: python2-samba @@ -552,7 +510,7 @@ necessary to communicate to the Winbind Daemon %if %{with_winexe} %package winexe Summary: Samba Winexe Windows Binary -License: GPLv3 +License: GPL-3.0-only %description winexe Winexe is a Remote Windows®-command executor @@ -644,6 +602,15 @@ export LDFLAGS="%{__global_ldflags} -fuse-ld=gold" export LDFLAGS="%{__global_ldflags} -fuse-ld=bfd" %endif +%if %{with ccache} +# Add support for mock ccache plugin +CCACHE="$(command -v ccache)" +if [ -n "${CCACHE}" ];then + ${CCACHE} -s + export CC="${CCACHE} gcc" +fi +%endif + %configure \ --enable-fhs \ %if %{?openEuler:1}0 @@ -727,16 +694,6 @@ install -d -m 0755 %{buildroot}/%{_libdir}/samba install -d -m 0755 %{buildroot}/%{_libdir}/samba/ldb install -d -m 0755 %{buildroot}/%{_libdir}/pkgconfig -# Move libwbclient.so* into private directory, it cannot be just libdir/samba -# because samba uses rpath with this directory. -install -d -m 0755 %{buildroot}/%{_libdir}/samba/wbclient -mv %{buildroot}/%{_libdir}/libwbclient.so* %{buildroot}/%{_libdir}/samba/wbclient -if [ ! -f %{buildroot}/%{_libdir}/samba/wbclient/libwbclient.so.%{libwbc_alternatives_version} ] -then - echo "Expected libwbclient version not found, please check if version has changed." - exit -1 -fi - %if %{?openEuler:1}0 touch %{buildroot}%{_libexecdir}/samba/cups_backend_smb %endif @@ -800,7 +757,6 @@ chrpath -d %{buildroot}%{_libdir}/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/pdb/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/vfs/*.so* -chrpath -d %{buildroot}%{_libdir}/%{name}/wbclient/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/auth/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/nss_info/*.so* chrpath -d %{buildroot}%{_libdir}/%{name}/idmap/*.so* @@ -924,12 +880,6 @@ for i in \ %{python3_sitearch}/samba/remove_dc.py \ %{python3_sitearch}/samba/samdb.py \ %{python3_sitearch}/samba/schema.py \ - %{python3_sitearch}/samba/third_party/iso8601/__init__.py \ - %{python3_sitearch}/samba/third_party/iso8601/__pycache__/__init__.*.pyc \ - %{python3_sitearch}/samba/third_party/iso8601/__pycache__/iso8601.*.pyc \ - %{python3_sitearch}/samba/third_party/iso8601/__pycache__/test_iso8601.*.pyc \ - %{python3_sitearch}/samba/third_party/iso8601/iso8601.py \ - %{python3_sitearch}/samba/third_party/iso8601/test_iso8601.py \ %{python3_sitearch}/samba/uptodateness.py \ %{_sbindir}/samba-gpupdate \ ; do @@ -1065,51 +1015,13 @@ fi %endif %if %with_libwbclient -%posttrans -n libwbclient -# It has to be posttrans here to make sure all files of a previous version -# without alternatives support are removed -%{_sbindir}/update-alternatives \ - --install \ - %{_libdir}/libwbclient.so.%{libwbc_alternatives_version} \ - libwbclient.so.%{libwbc_alternatives_version}%{libwbc_alternatives_suffix} \ - %{_libdir}/samba/wbclient/libwbclient.so.%{libwbc_alternatives_version} \ - 10 -%{?ldconfig} - -%preun -n libwbclient -if [ $1 -eq 0 ]; then - %{_sbindir}/update-alternatives \ - --remove \ - libwbclient.so.%{libwbc_alternatives_version}%{libwbc_alternatives_suffix} \ - %{_libdir}/samba/wbclient/libwbclient.so.%{libwbc_alternatives_version} -fi -/sbin/ldconfig - -%posttrans -n libwbclient-devel -%{_sbindir}/update-alternatives \ - --install %{_libdir}/libwbclient.so \ - libwbclient.so%{libwbc_alternatives_suffix} \ - %{_libdir}/samba/wbclient/libwbclient.so \ - 10 - -%preun -n libwbclient-devel -# alternatives checks if the file which should be removed is a link or not, but -# not if it points to the /etc/alternatives directory or to some other place. -# When downgrading to a version where alternatives is not used and -# libwbclient.so is a link and not a file it will be removed. The following -# check removes the alternatives files manually if that is the case. -if [ $1 -eq 0 ]; then - if [ "`readlink %{_libdir}/libwbclient.so`" == "libwbclient.so.%{libwbc_alternatives_version}" ]; then - /bin/rm -f \ - /etc/alternatives/libwbclient.so%{libwbc_alternatives_suffix} \ - /var/lib/alternatives/libwbclient.so%{libwbc_alternatives_suffix} 2> /dev/null - else - %{_sbindir}/update-alternatives \ - --remove \ - libwbclient.so%{libwbc_alternatives_suffix} \ - %{_libdir}/samba/wbclient/libwbclient.so - fi +%pre -n libwbclient +if [ $1 -gt 1 ];then + rm -rf %{_libdir}/samba/wbclient/ + rm -rf /etc/alternatives/libwbclient.so* + rm -rf /var/lib/alternatives/libwbclient.so* fi +%{?ldconfig} %ldconfig_scriptlets -n libwbclient #endif with_libwbclient @@ -1267,7 +1179,6 @@ fi %files libs %{_libdir}/libdcerpc-samr.so.* -%{_libdir}/libdcerpc-server-core.so.* %{_libdir}/samba/libLIBWBCLIENT-OLD-samba4.so %{_libdir}/samba/libauth-unix-token-samba4.so @@ -1313,21 +1224,22 @@ fi %files client-libs %{_libdir}/libdcerpc-binding.so.* -%{_libdir}/libndr.so.* +%{_libdir}/libdcerpc-server-core.so.* +%{_libdir}/libdcerpc.so.* %{_libdir}/libndr-krb5pac.so.* %{_libdir}/libndr-nbt.so.* %{_libdir}/libndr-standard.so.* +%{_libdir}/libndr.so.* %{_libdir}/libnetapi.so.* %{_libdir}/libsamba-credentials.so.* %{_libdir}/libsamba-errors.so.* +%{_libdir}/libsamba-hostconfig.so.* %{_libdir}/libsamba-passdb.so.* %{_libdir}/libsamba-util.so.* -%{_libdir}/libsamba-hostconfig.so.* %{_libdir}/libsamdb.so.* %{_libdir}/libsmbconf.so.* %{_libdir}/libsmbldap.so.* %{_libdir}/libtevent-util.so.* -%{_libdir}/libdcerpc.so.* %dir %{_libdir}/samba %{_libdir}/samba/libCHARSET3-samba4.so @@ -1398,6 +1310,7 @@ fi %{_libdir}/samba/libsmbd-base-samba4.so %{_libdir}/samba/libsmbd-shim-samba4.so %{_libdir}/samba/libsmbldaphelper-samba4.so +%{_libdir}/samba/libstable-sort-samba4.so %{_libdir}/samba/libsys-rw-samba4.so %{_libdir}/samba/libsocket-blocking-samba4.so %{_libdir}/samba/libtalloc-report-printf-samba4.so @@ -1589,6 +1502,7 @@ fi %{_includedir}/samba-4.0/domain_credentials.h %{_includedir}/samba-4.0/gen_ndr/atsvc.h %{_includedir}/samba-4.0/gen_ndr/auth.h +%{_includedir}/samba-4.0/gen_ndr/claims.h %{_includedir}/samba-4.0/gen_ndr/dcerpc.h %{_includedir}/samba-4.0/gen_ndr/krb5pac.h %{_includedir}/samba-4.0/gen_ndr/lsa.h @@ -1733,12 +1647,12 @@ fi %if %with_libwbclient %files -n libwbclient -%{_libdir}/samba/wbclient/libwbclient.so.* +%{_libdir}/libwbclient.so.* %config(noreplace) /etc/ld.so.conf.d/* %files -n libwbclient-devel %{_includedir}/samba-4.0/wbclient.h -%{_libdir}/samba/wbclient/libwbclient.so +%{_libdir}/libwbclient.so %{_libdir}/pkgconfig/wbclient.pc #endif with_libwbclient %endif @@ -1805,6 +1719,7 @@ fi %{python3_sitearch}/samba/__pycache__/ms_schema.*.pyc %{python3_sitearch}/samba/__pycache__/ndr.*.pyc %{python3_sitearch}/samba/__pycache__/ntacls.*.pyc +%{python3_sitearch}/samba/__pycache__/safe_tarfile.*.pyc %{python3_sitearch}/samba/__pycache__/sd_utils.*.pyc %{python3_sitearch}/samba/__pycache__/sites.*.pyc %{python3_sitearch}/samba/__pycache__/subnets.*.pyc @@ -1820,6 +1735,7 @@ fi %{python3_sitearch}/samba/dbchecker.py %{python3_sitearch}/samba/colour.py %{python3_sitearch}/samba/common.py +%{python3_sitearch}/samba/compression.*.so %{python3_sitearch}/samba/credentials.*.so %{python3_sitearch}/samba/crypto.*.so %dir %{python3_sitearch}/samba/dcerpc @@ -1829,6 +1745,7 @@ fi %{python3_sitearch}/samba/dcerpc/atsvc.*.so %{python3_sitearch}/samba/dcerpc/auth.*.so %{python3_sitearch}/samba/dcerpc/base.*.so +%{python3_sitearch}/samba/dcerpc/claims.*.so %{python3_sitearch}/samba/dcerpc/dcerpc.*.so %{python3_sitearch}/samba/dcerpc/dfs.*.so %{python3_sitearch}/samba/dcerpc/dns.*.so @@ -2025,7 +1942,9 @@ fi %{python3_sitearch}/samba/param.*.so %{python3_sitearch}/samba/policy.*.so %{python3_sitearch}/samba/registry.*.so +%{python3_sitearch}/samba/reparse_symlink.*.so %{python3_sitearch}/samba/security.*.so +%{python3_sitearch}/samba/safe_tarfile.py %dir %{python3_sitearch}/samba/samba3 %{python3_sitearch}/samba/samba3/__init__.py %dir %{python3_sitearch}/samba/samba3/__pycache__ @@ -2143,6 +2062,7 @@ fi %{python3_sitearch}/samba/tests/__pycache__/auth_log_winbind.*.pyc %{python3_sitearch}/samba/tests/__pycache__/common.*.pyc %{python3_sitearch}/samba/tests/__pycache__/complex_expressions.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/compression.*.pyc %{python3_sitearch}/samba/tests/__pycache__/core.*.pyc %{python3_sitearch}/samba/tests/__pycache__/credentials.*.pyc %{python3_sitearch}/samba/tests/__pycache__/cred_opt.*.pyc @@ -2183,6 +2103,7 @@ fi %{python3_sitearch}/samba/tests/__pycache__/loadparm.*.pyc %{python3_sitearch}/samba/tests/__pycache__/logfiles.*.pyc %{python3_sitearch}/samba/tests/__pycache__/libsmb.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/libsmb-basic.*.pyc %{python3_sitearch}/samba/tests/__pycache__/lsa_string.*.pyc %{python3_sitearch}/samba/tests/__pycache__/messaging.*.pyc %{python3_sitearch}/samba/tests/__pycache__/ndr.*.pyc @@ -2217,12 +2138,14 @@ fi %{python3_sitearch}/samba/tests/__pycache__/pso.*.pyc %{python3_sitearch}/samba/tests/__pycache__/py_credentials.*.pyc %{python3_sitearch}/samba/tests/__pycache__/registry.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/reparsepoints.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3idmapdb.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3param.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3passdb.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3registry.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3windb.*.pyc %{python3_sitearch}/samba/tests/__pycache__/s3_net_join.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/safe_tarfile.*.pyc %{python3_sitearch}/samba/tests/__pycache__/samba3sam.*.pyc %{python3_sitearch}/samba/tests/__pycache__/samba_upgradedns_lmdb.*.pyc %{python3_sitearch}/samba/tests/__pycache__/samdb.*.pyc @@ -2232,6 +2155,9 @@ fi %{python3_sitearch}/samba/tests/__pycache__/segfault.*.pyc %{python3_sitearch}/samba/tests/__pycache__/sid_strings.*.pyc %{python3_sitearch}/samba/tests/__pycache__/smb.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/smb1posix.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/smb2symlink.*.pyc +%{python3_sitearch}/samba/tests/__pycache__/smb3unix.*.pyc %{python3_sitearch}/samba/tests/__pycache__/smbconf.*.pyc %{python3_sitearch}/samba/tests/__pycache__/smb-notify.*.pyc %{python3_sitearch}/samba/tests/__pycache__/smbd_base.*.pyc @@ -2297,6 +2223,7 @@ fi %{python3_sitearch}/samba/tests/blackbox/traffic_replay.py %{python3_sitearch}/samba/tests/blackbox/traffic_summary.py %{python3_sitearch}/samba/tests/common.py +%{python3_sitearch}/samba/tests/compression.py %{python3_sitearch}/samba/tests/complex_expressions.py %{python3_sitearch}/samba/tests/core.py %{python3_sitearch}/samba/tests/credentials.py @@ -2402,9 +2329,11 @@ fi %{python3_sitearch}/samba/tests/krb5/__pycache__/alias_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/as_canonicalization_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/as_req_tests.*.pyc +%{python3_sitearch}/samba/tests/krb5/__pycache__/claims_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/compatability_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/etype_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/fast_tests.*.pyc +%{python3_sitearch}/samba/tests/krb5/__pycache__/group_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/kcrypto.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/kdc_base_test.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/kdc_tests.*.pyc @@ -2433,9 +2362,11 @@ fi %{python3_sitearch}/samba/tests/krb5/alias_tests.py %{python3_sitearch}/samba/tests/krb5/as_canonicalization_tests.py %{python3_sitearch}/samba/tests/krb5/as_req_tests.py +%{python3_sitearch}/samba/tests/krb5/claims_tests.py %{python3_sitearch}/samba/tests/krb5/compatability_tests.py %{python3_sitearch}/samba/tests/krb5/etype_tests.py %{python3_sitearch}/samba/tests/krb5/fast_tests.py +%{python3_sitearch}/samba/tests/krb5/group_tests.py %{python3_sitearch}/samba/tests/krb5/kcrypto.py %{python3_sitearch}/samba/tests/krb5/kdc_base_test.py %{python3_sitearch}/samba/tests/krb5/kdc_tests.py @@ -2467,6 +2398,7 @@ fi %{python3_sitearch}/samba/tests/ldap_spn.py %{python3_sitearch}/samba/tests/ldap_upn_sam_account.py %{python3_sitearch}/samba/tests/libsmb.py +%{python3_sitearch}/samba/tests/libsmb-basic.py %{python3_sitearch}/samba/tests/loadparm.py %{python3_sitearch}/samba/tests/logfiles.py %{python3_sitearch}/samba/tests/lsa_string.py @@ -2503,12 +2435,14 @@ fi %{python3_sitearch}/samba/tests/pso.py %{python3_sitearch}/samba/tests/py_credentials.py %{python3_sitearch}/samba/tests/registry.py +%{python3_sitearch}/samba/tests/reparsepoints.py %{python3_sitearch}/samba/tests/s3idmapdb.py %{python3_sitearch}/samba/tests/s3param.py %{python3_sitearch}/samba/tests/s3passdb.py %{python3_sitearch}/samba/tests/s3registry.py %{python3_sitearch}/samba/tests/s3windb.py %{python3_sitearch}/samba/tests/s3_net_join.py +%{python3_sitearch}/samba/tests/safe_tarfile.py %{python3_sitearch}/samba/tests/samba3sam.py %{python3_sitearch}/samba/tests/samba_upgradedns_lmdb.py %dir %{python3_sitearch}/samba/tests/samba_tool @@ -2596,6 +2530,9 @@ fi %{python3_sitearch}/samba/tests/segfault.py %{python3_sitearch}/samba/tests/sid_strings.py %{python3_sitearch}/samba/tests/smb.py +%{python3_sitearch}/samba/tests/smb1posix.py +%{python3_sitearch}/samba/tests/smb2symlink.py +%{python3_sitearch}/samba/tests/smb3unix.py %{python3_sitearch}/samba/tests/smbconf.py %{python3_sitearch}/samba/tests/smb-notify.py %{python3_sitearch}/samba/tests/smbd_base.py @@ -3546,9 +3483,13 @@ fi %files help %{_mandir}/man* %dir %{_datadir}/samba/admx +%{_datadir}/samba/admx/GNOME_Settings.admx %{_datadir}/samba/admx/samba.admx %dir %{_datadir}/samba/admx/en-US +%{_datadir}/samba/admx/en-US/GNOME_Settings.adml %{_datadir}/samba/admx/en-US/samba.adml +%dir %{_datadir}/samba/admx/ru-RU +%{_datadir}/samba/admx/ru-RU/GNOME_Settings.adml %if %{with_winexe} ### WINEXE @@ -3557,6 +3498,12 @@ fi %endif %changelog +* Mon Jul 24 2023 gaihuiying - 4.18.5-1 +- Type:requirement +- ID:NA +- SUG:NA +- DESC:update samba to 4.18.5 + * Tue Jun 27 2023 yanglu - 4.17.5-6 - Type:bugfix - ID:NA