fix CVE-2020-10730 CVE-2020-10745 CVE-2020-10760 CVE-2020-14303
This commit is contained in:
parent
fc242f44e8
commit
c9fa0b846f
35
CVE-2020-10730-1.patch
Normal file
35
CVE-2020-10730-1.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From b8628cb44766ac4c4817b1a50f09ca316425bd8b Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Tue, 5 May 2020 12:54:59 +1200
|
||||
Subject: [PATCH 01/22] CVE-2020-10730: vlv: Use strcmp(), not strncmp()
|
||||
checking the NULL terminated control OIDs
|
||||
|
||||
The end result is the same, as sizeof() includes the trailing NUL, but this
|
||||
avoids having to think about that.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/samdb/ldb_modules/vlv_pagination.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
index 980177cb05e..31e64b4bd78 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
@@ -682,8 +682,8 @@ vlv_copy_down_controls(TALLOC_CTX *mem_ctx, struct ldb_control **controls)
|
||||
if (control->oid == NULL) {
|
||||
break;
|
||||
}
|
||||
- if (strncmp(control->oid, LDB_CONTROL_VLV_REQ_OID, sizeof(LDB_CONTROL_VLV_REQ_OID)) == 0 ||
|
||||
- strncmp(control->oid, LDB_CONTROL_SERVER_SORT_OID, sizeof(LDB_CONTROL_SERVER_SORT_OID)) == 0) {
|
||||
+ if (strcmp(control->oid, LDB_CONTROL_VLV_REQ_OID) == 0 ||
|
||||
+ strcmp(control->oid, LDB_CONTROL_SERVER_SORT_OID) == 0) {
|
||||
continue;
|
||||
}
|
||||
new_controls[j] = talloc_steal(new_controls, control);
|
||||
--
|
||||
2.17.1
|
||||
|
||||
49
CVE-2020-10730-10.patch
Normal file
49
CVE-2020-10730-10.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 303947c58abf9311a666fe63ebd4ce26655ff36e Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 13 May 2020 10:56:56 +1200
|
||||
Subject: [PATCH 10/22] CVE-2020-10730: lib ldb: Check if
|
||||
ldb_lock_backend_callback called twice
|
||||
|
||||
Prevent use after free issues if ldb_lock_backend_callback is called
|
||||
twice, usually due to ldb_module_done being called twice. This can happen if a
|
||||
module ignores the return value from function a function that calls
|
||||
ldb_module_done as part of it's error handling.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
lib/ldb/common/ldb.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
|
||||
index 95e9138a56b..2d0926ffaf9 100644
|
||||
--- a/lib/ldb/common/ldb.c
|
||||
+++ b/lib/ldb/common/ldb.c
|
||||
@@ -1018,6 +1018,13 @@ static int ldb_lock_backend_callback(struct ldb_request *req,
|
||||
struct ldb_db_lock_context *lock_context;
|
||||
int ret;
|
||||
|
||||
+ if (req->context == NULL) {
|
||||
+ /*
|
||||
+ * The usual way to get here is to ignore the return codes
|
||||
+ * and continuing processing after an error.
|
||||
+ */
|
||||
+ abort();
|
||||
+ }
|
||||
lock_context = talloc_get_type(req->context,
|
||||
struct ldb_db_lock_context);
|
||||
|
||||
@@ -1032,7 +1039,7 @@ static int ldb_lock_backend_callback(struct ldb_request *req,
|
||||
* If this is a LDB_REPLY_DONE or an error, unlock the
|
||||
* DB by calling the destructor on this context
|
||||
*/
|
||||
- talloc_free(lock_context);
|
||||
+ TALLOC_FREE(req->context);
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
46
CVE-2020-10730-2.patch
Normal file
46
CVE-2020-10730-2.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 2041c05d9b41fb0255c3492d118628c14a0c4b3d Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Tue, 5 May 2020 12:55:57 +1200
|
||||
Subject: [PATCH 02/22] CVE-2020-10730: vlv: Do not re-ASQ search the results
|
||||
of an ASQ search with VLV
|
||||
|
||||
This is a silly combination, but at least try and keep the results sensible
|
||||
and avoid a double-dereference.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/samdb/ldb_modules/vlv_pagination.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
index 31e64b4bd78..d58a62482c9 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
@@ -682,10 +682,21 @@ vlv_copy_down_controls(TALLOC_CTX *mem_ctx, struct ldb_control **controls)
|
||||
if (control->oid == NULL) {
|
||||
break;
|
||||
}
|
||||
+ /*
|
||||
+ * Do not re-use VLV, nor the server-sort, both are
|
||||
+ * already handled here.
|
||||
+ */
|
||||
if (strcmp(control->oid, LDB_CONTROL_VLV_REQ_OID) == 0 ||
|
||||
strcmp(control->oid, LDB_CONTROL_SERVER_SORT_OID) == 0) {
|
||||
continue;
|
||||
}
|
||||
+ /*
|
||||
+ * ASQ changes everything, do not copy it down for the
|
||||
+ * per-GUID search
|
||||
+ */
|
||||
+ if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
new_controls[j] = talloc_steal(new_controls, control);
|
||||
j++;
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
57
CVE-2020-10730-3.patch
Normal file
57
CVE-2020-10730-3.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From cf10f9b9a9a2f94afc526995a4034c1c6f05f5b4 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Tue, 5 May 2020 13:16:48 +1200
|
||||
Subject: [PATCH 03/22] CVE-2020-10730: selftest: Add test to confirm VLV
|
||||
interaction with ASQ
|
||||
|
||||
Tested against Windows 1709.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/tests/python/asq.py | 27 +++++++++++++++++++++++++++
|
||||
1 file changed, 27 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/tests/python/asq.py b/source4/dsdb/tests/python/asq.py
|
||||
index a32c9f40cd3..1c93a45f131 100644
|
||||
--- a/source4/dsdb/tests/python/asq.py
|
||||
+++ b/source4/dsdb/tests/python/asq.py
|
||||
@@ -162,6 +162,33 @@ class ASQLDAPTest(samba.tests.TestCase):
|
||||
self.assertIn(ldb.Dn(self.ldb, str(group)),
|
||||
self.members)
|
||||
|
||||
+ def test_asq_vlv(self):
|
||||
+ """Testing ASQ behaviour with VLV set.
|
||||
+
|
||||
+ ASQ is very strange, it turns a BASE search into a search for
|
||||
+ all the objects pointed to by the specified attribute,
|
||||
+ returning multiple entries!
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ sort_control = "server_sort:1:0:cn"
|
||||
+
|
||||
+ msgs = self.ldb.search(base=self.top_dn,
|
||||
+ scope=ldb.SCOPE_BASE,
|
||||
+ attrs=["objectGUID", "cn", "member"],
|
||||
+ controls=["asq:1:member",
|
||||
+ sort_control,
|
||||
+ "vlv:1:20:20:11:0"])
|
||||
+
|
||||
+ self.assertEqual(len(msgs), 20)
|
||||
+
|
||||
+ for msg in msgs:
|
||||
+ self.assertNotEqual(msg.dn, self.top_dn)
|
||||
+ self.assertIn(msg.dn, self.members2)
|
||||
+ for group in msg["member"]:
|
||||
+ self.assertIn(ldb.Dn(self.ldb, str(group)),
|
||||
+ self.members)
|
||||
+
|
||||
if "://" not in url:
|
||||
if os.path.isfile(url):
|
||||
url = "tdb://%s" % url
|
||||
--
|
||||
2.17.1
|
||||
|
||||
53
CVE-2020-10730-4.patch
Normal file
53
CVE-2020-10730-4.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From 3fd7ce69761fd2e21a85101772196aafc5ae57df Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Tue, 5 May 2020 16:34:11 +1200
|
||||
Subject: [PATCH 04/22] CVE-2020-10730: vlv: Another workaround for mixing ASQ
|
||||
and VLV
|
||||
|
||||
This is essentially an alternative patch, but without the correct
|
||||
behaviour. Instead this just avoids a segfault.
|
||||
|
||||
Included in case we have something simialr again in
|
||||
another module.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
.../dsdb/samdb/ldb_modules/vlv_pagination.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
index d58a62482c9..720b5e95638 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
@@ -442,10 +442,21 @@ static int vlv_results(struct vlv_context *ac)
|
||||
ret = vlv_search_by_dn_guid(ac->module, ac, &result, guid,
|
||||
ac->req->op.search.attrs);
|
||||
|
||||
- if (ret == LDAP_NO_SUCH_OBJECT) {
|
||||
- /* The thing isn't there, which we quietly
|
||||
- ignore and go on to send an extra one
|
||||
- instead. */
|
||||
+ if (ret == LDAP_NO_SUCH_OBJECT
|
||||
+ || result->count != 1) {
|
||||
+ /*
|
||||
+ * The thing isn't there, which we quietly
|
||||
+ * ignore and go on to send an extra one
|
||||
+ * instead.
|
||||
+ *
|
||||
+ * result->count == 0 or > 1 can only
|
||||
+ * happen if ASQ (which breaks all the
|
||||
+ * rules) is somehow invoked (as this
|
||||
+ * is a BASE search).
|
||||
+ *
|
||||
+ * (We skip the ASQ cookie for the
|
||||
+ * GUID searches)
|
||||
+ */
|
||||
if (last_i < ac->store->num_entries - 1) {
|
||||
last_i++;
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
92
CVE-2020-10730-5.patch
Normal file
92
CVE-2020-10730-5.patch
Normal file
@ -0,0 +1,92 @@
|
||||
From 01cce3d1fc69f04cdc237425b2f2ad1f2ac973d4 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Wed, 6 May 2020 16:19:01 +1200
|
||||
Subject: [PATCH 05/22] CVE-2020-10730: selftest: Add test to show that VLV and
|
||||
paged_results are incompatible
|
||||
|
||||
As tested against Windows Server 1709
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/tests/python/asq.py | 27 +++++++++++++++++++++++++++
|
||||
source4/dsdb/tests/python/vlv.py | 23 +++++++++++++++++++++++
|
||||
2 files changed, 50 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/tests/python/asq.py b/source4/dsdb/tests/python/asq.py
|
||||
index 1c93a45f131..33973d66c37 100644
|
||||
--- a/source4/dsdb/tests/python/asq.py
|
||||
+++ b/source4/dsdb/tests/python/asq.py
|
||||
@@ -189,6 +189,33 @@ class ASQLDAPTest(samba.tests.TestCase):
|
||||
self.assertIn(ldb.Dn(self.ldb, str(group)),
|
||||
self.members)
|
||||
|
||||
+ def test_asq_vlv_paged(self):
|
||||
+ """Testing ASQ behaviour with VLV and paged_results set.
|
||||
+
|
||||
+ ASQ is very strange, it turns a BASE search into a search for
|
||||
+ all the objects pointed to by the specified attribute,
|
||||
+ returning multiple entries!
|
||||
+
|
||||
+ Thankfully combining both of these gives
|
||||
+ unavailable-critical-extension against Windows 1709
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ sort_control = "server_sort:1:0:cn"
|
||||
+
|
||||
+ try:
|
||||
+ msgs = self.ldb.search(base=self.top_dn,
|
||||
+ scope=ldb.SCOPE_BASE,
|
||||
+ attrs=["objectGUID", "cn", "member"],
|
||||
+ controls=["asq:1:member",
|
||||
+ sort_control,
|
||||
+ "vlv:1:20:20:11:0",
|
||||
+ "paged_results:1:1024"])
|
||||
+ self.fail("should have failed with LDAP_UNAVAILABLE_CRITICAL_EXTENSION")
|
||||
+ except ldb.LdbError as e:
|
||||
+ (enum, estr) = e.args
|
||||
+ self.assertEqual(enum, ldb.ERR_UNSUPPORTED_CRITICAL_EXTENSION)
|
||||
+
|
||||
if "://" not in url:
|
||||
if os.path.isfile(url):
|
||||
url = "tdb://%s" % url
|
||||
diff --git a/source4/dsdb/tests/python/vlv.py b/source4/dsdb/tests/python/vlv.py
|
||||
index 2efcaa5e7a3..f3c603e3a39 100644
|
||||
--- a/source4/dsdb/tests/python/vlv.py
|
||||
+++ b/source4/dsdb/tests/python/vlv.py
|
||||
@@ -1644,6 +1644,29 @@ class PagedResultsTests(TestsWithUserOU):
|
||||
page_size=len(self.users))
|
||||
self.assertEqual(results, set_2[ps*2:])
|
||||
|
||||
+ def test_vlv_paged(self):
|
||||
+ """Testing behaviour with VLV and paged_results set.
|
||||
+
|
||||
+ A strange combination, certainly
|
||||
+
|
||||
+ Thankfully combining both of these gives
|
||||
+ unavailable-critical-extension against Windows 1709
|
||||
+
|
||||
+ """
|
||||
+ sort_control = "server_sort:1:0:cn"
|
||||
+
|
||||
+ try:
|
||||
+ msgs = self.ldb.search(base=self.base_dn,
|
||||
+ scope=ldb.SCOPE_SUBTREE,
|
||||
+ attrs=["objectGUID", "cn", "member"],
|
||||
+ controls=["vlv:1:20:20:11:0",
|
||||
+ sort_control,
|
||||
+ "paged_results:1:1024"])
|
||||
+ self.fail("should have failed with LDAP_UNAVAILABLE_CRITICAL_EXTENSION")
|
||||
+ except ldb.LdbError as e:
|
||||
+ (enum, estr) = e.args
|
||||
+ self.assertEqual(enum, ldb.ERR_UNSUPPORTED_CRITICAL_EXTENSION)
|
||||
+
|
||||
|
||||
if "://" not in host:
|
||||
if os.path.isfile(host):
|
||||
--
|
||||
2.17.1
|
||||
|
||||
35
CVE-2020-10730-6.patch
Normal file
35
CVE-2020-10730-6.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From c7608e43c933d9a33d94e32371080e64cc1d4fcb Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Wed, 6 May 2020 17:05:30 +1200
|
||||
Subject: [PATCH 06/22] CVE-2020-10730: dsdb: Fix crash when vlv and
|
||||
paged_results are combined
|
||||
|
||||
The GUID is not returned in the DN for some reason in this (to be banned)
|
||||
combination.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/samdb/ldb_modules/paged_results.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
index dc211dd18ce..f720a2e4337 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
@@ -416,6 +416,10 @@ static int paged_search_callback(struct ldb_request *req,
|
||||
|
||||
guid_blob = ldb_dn_get_extended_component(ares->message->dn,
|
||||
"GUID");
|
||||
+ if (guid_blob == NULL) {
|
||||
+ return ldb_module_done(ac->req, NULL, NULL,
|
||||
+ LDB_ERR_OPERATIONS_ERROR);
|
||||
+ }
|
||||
status = GUID_from_ndr_blob(guid_blob, &guid);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ldb_module_done(ac->req, NULL, NULL,
|
||||
--
|
||||
2.17.1
|
||||
|
||||
48
CVE-2020-10730-7.patch
Normal file
48
CVE-2020-10730-7.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 0c8cd0a9fbd9d17c1d7219f977ca35f88f0a2ea3 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Wed, 6 May 2020 16:18:19 +1200
|
||||
Subject: [PATCH 07/22] CVE-2020-10730: dsdb: Ban the combination of
|
||||
paged_results and VLV
|
||||
|
||||
This (two different paging controls) makes no sense and fails against
|
||||
Windows Server 1709.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
source4/dsdb/samdb/ldb_modules/paged_results.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
index f720a2e4337..aa49a6e4aa5 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
@@ -589,6 +589,7 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_control *control;
|
||||
+ struct ldb_control *vlv_control;
|
||||
struct private_data *private_data;
|
||||
struct ldb_paged_control *paged_ctrl;
|
||||
struct ldb_request *search_req;
|
||||
@@ -612,6 +613,15 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
|
||||
private_data = talloc_get_type(ldb_module_get_private(module),
|
||||
struct private_data);
|
||||
|
||||
+ vlv_control = ldb_request_get_control(req, LDB_CONTROL_VLV_REQ_OID);
|
||||
+ if (vlv_control != NULL) {
|
||||
+ /*
|
||||
+ * VLV and paged_results are not allowed at the same
|
||||
+ * time
|
||||
+ */
|
||||
+ return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
|
||||
+ }
|
||||
+
|
||||
ac = talloc_zero(req, struct paged_context);
|
||||
if (ac == NULL) {
|
||||
ldb_set_errstring(ldb, "Out of Memory");
|
||||
--
|
||||
2.17.1
|
||||
|
||||
138
CVE-2020-10730-8.patch
Normal file
138
CVE-2020-10730-8.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From dcf713038ff10e35a74ee255f1634be81103e360 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Mon, 18 May 2020 12:36:57 +1200
|
||||
Subject: [PATCH 08/22] CVE-2020-10730: s4 dsdb paged_results: Prevent repeat
|
||||
call of ldb_module_done
|
||||
|
||||
Check the return code from paged_results, if it is not LDB_SUCCESS
|
||||
ldb_module_done has already been called, and SHOULD NOT be called again.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
.../dsdb/samdb/ldb_modules/paged_results.c | 43 +++++++++++++++----
|
||||
1 file changed, 34 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
index aa49a6e4aa5..735883e8802 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
@@ -237,14 +237,16 @@ static int paged_search_by_dn_guid(struct ldb_module *module,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int paged_results(struct paged_context *ac)
|
||||
+static int paged_results(struct paged_context *ac, struct ldb_reply *ares)
|
||||
{
|
||||
struct ldb_paged_control *paged;
|
||||
unsigned int i, num_ctrls;
|
||||
int ret;
|
||||
|
||||
if (ac->store == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
while (ac->store->last_i < ac->store->num_entries && ac->size > 0) {
|
||||
@@ -273,12 +275,17 @@ static int paged_results(struct paged_context *ac)
|
||||
instead. */
|
||||
continue;
|
||||
} else if (ret != LDB_SUCCESS) {
|
||||
- return ret;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ret = ldb_module_send_entry(ac->req, result->msgs[0],
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
+ /*
|
||||
+ * ldb_module_send_entry will have called
|
||||
+ * ldb_module_done if an error occurred.
|
||||
+ */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -289,6 +296,10 @@ static int paged_results(struct paged_context *ac)
|
||||
*/
|
||||
ret = send_referrals(ac->store, ac->req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
+ /*
|
||||
+ * send_referrals will have called ldb_module_done
|
||||
+ * if an error occurred.
|
||||
+ */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -305,7 +316,9 @@ static int paged_results(struct paged_context *ac)
|
||||
|
||||
ac->controls = talloc_array(ac, struct ldb_control *, num_ctrls +1);
|
||||
if (ac->controls == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
ac->controls[num_ctrls] = NULL;
|
||||
|
||||
@@ -316,20 +329,26 @@ static int paged_results(struct paged_context *ac)
|
||||
|
||||
ac->controls[i] = talloc(ac->controls, struct ldb_control);
|
||||
if (ac->controls[i] == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ac->controls[i]->oid = talloc_strdup(ac->controls[i],
|
||||
LDB_CONTROL_PAGED_RESULTS_OID);
|
||||
if (ac->controls[i]->oid == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ac->controls[i]->critical = 0;
|
||||
|
||||
paged = talloc(ac->controls[i], struct ldb_paged_control);
|
||||
if (paged == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ac->controls[i]->data = paged;
|
||||
@@ -456,7 +475,13 @@ static int paged_search_callback(struct ldb_request *req,
|
||||
store->result_array_size = store->num_entries;
|
||||
|
||||
ac->store->controls = talloc_move(ac->store, &ares->controls);
|
||||
- ret = paged_results(ac);
|
||||
+ ret = paged_results(ac, ares);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ /* paged_results will have called ldb_module_done
|
||||
+ * if an error occurred
|
||||
+ */
|
||||
+ return ret;
|
||||
+ }
|
||||
return ldb_module_done(ac->req, ac->controls,
|
||||
ares->response, ret);
|
||||
}
|
||||
@@ -768,7 +793,7 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
|
||||
LDB_SUCCESS);
|
||||
}
|
||||
|
||||
- ret = paged_results(ac);
|
||||
+ ret = paged_results(ac, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ldb_module_done(req, NULL, NULL, ret);
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
171
CVE-2020-10730-9.patch
Normal file
171
CVE-2020-10730-9.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From ae6e9445ac8bf8f6870a8caa24406153cd2ee2bf Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Mon, 18 May 2020 12:37:39 +1200
|
||||
Subject: [PATCH 09/22] CVE-2020-10730: s4 dsdb vlv_pagination: Prevent repeat
|
||||
call of ldb_module_done
|
||||
|
||||
Check the return code from vlv_results, if it is not LDB_SUCCESS
|
||||
ldb_module_done has already been called, and SHOULD NOT be called again.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14364
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
.../dsdb/samdb/ldb_modules/vlv_pagination.c | 61 +++++++++++++++----
|
||||
1 file changed, 49 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
index 720b5e95638..b103bda5f52 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
@@ -387,7 +387,7 @@ static int vlv_calc_real_offset(int offset, int denominator, int n_entries)
|
||||
has been prepared earlier and saved -- or by vlv_search_callback() when a
|
||||
search has just been completed. */
|
||||
|
||||
-static int vlv_results(struct vlv_context *ac)
|
||||
+static int vlv_results(struct vlv_context *ac, struct ldb_reply *ares)
|
||||
{
|
||||
struct ldb_vlv_resp_control *vlv;
|
||||
unsigned int num_ctrls;
|
||||
@@ -397,7 +397,9 @@ static int vlv_results(struct vlv_context *ac)
|
||||
int target = 0;
|
||||
|
||||
if (ac->store == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
if (ac->store->first_ref) {
|
||||
@@ -406,6 +408,10 @@ static int vlv_results(struct vlv_context *ac)
|
||||
*/
|
||||
ret = send_referrals(ac->store, ac->req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
+ /*
|
||||
+ * send_referrals will have called ldb_module_done
|
||||
+ * if there was an error.
|
||||
+ */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -419,14 +425,23 @@ static int vlv_results(struct vlv_context *ac)
|
||||
vlv_details,
|
||||
sort_details, &ret);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
- return ret;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req,
|
||||
+ ac->controls,
|
||||
+ ares->response,
|
||||
+ ret);
|
||||
}
|
||||
} else {
|
||||
target = vlv_calc_real_offset(vlv_details->match.byOffset.offset,
|
||||
vlv_details->match.byOffset.contentCount,
|
||||
ac->store->num_entries);
|
||||
if (target == -1) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req,
|
||||
+ ac->controls,
|
||||
+ ares->response,
|
||||
+ ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,12 +477,20 @@ static int vlv_results(struct vlv_context *ac)
|
||||
}
|
||||
continue;
|
||||
} else if (ret != LDB_SUCCESS) {
|
||||
- return ret;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req,
|
||||
+ ac->controls,
|
||||
+ ares->response,
|
||||
+ ret);
|
||||
}
|
||||
|
||||
ret = ldb_module_send_entry(ac->req, result->msgs[0],
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
+ /*
|
||||
+ * ldb_module_send_entry will have called
|
||||
+ * ldb_module_done if there was an error
|
||||
+ */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -488,7 +511,9 @@ static int vlv_results(struct vlv_context *ac)
|
||||
|
||||
ac->controls = talloc_array(ac, struct ldb_control *, num_ctrls + 1);
|
||||
if (ac->controls == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
ac->controls[num_ctrls] = NULL;
|
||||
|
||||
@@ -498,20 +523,26 @@ static int vlv_results(struct vlv_context *ac)
|
||||
|
||||
ac->controls[i] = talloc(ac->controls, struct ldb_control);
|
||||
if (ac->controls[i] == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ac->controls[i]->oid = talloc_strdup(ac->controls[i],
|
||||
LDB_CONTROL_VLV_RESP_OID);
|
||||
if (ac->controls[i]->oid == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
|
||||
ac->controls[i]->critical = 0;
|
||||
|
||||
vlv = talloc(ac->controls[i], struct ldb_vlv_resp_control);
|
||||
if (vlv == NULL) {
|
||||
- return LDB_ERR_OPERATIONS_ERROR;
|
||||
+ ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
+ return ldb_module_done(
|
||||
+ ac->req, ac->controls, ares->response, ret);
|
||||
}
|
||||
ac->controls[i]->data = vlv;
|
||||
|
||||
@@ -600,7 +631,13 @@ static int vlv_search_callback(struct ldb_request *req, struct ldb_reply *ares)
|
||||
store->result_array_size = store->num_entries;
|
||||
|
||||
ac->store->controls = talloc_move(ac->store, &ares->controls);
|
||||
- ret = vlv_results(ac);
|
||||
+ ret = vlv_results(ac, ares);
|
||||
+ if (ret != LDB_SUCCESS) {
|
||||
+ /* vlv_results will have called ldb_module_done
|
||||
+ * if there was an error.
|
||||
+ */
|
||||
+ return ret;
|
||||
+ }
|
||||
return ldb_module_done(ac->req, ac->controls,
|
||||
ares->response, ret);
|
||||
}
|
||||
@@ -845,9 +882,9 @@ static int vlv_search(struct ldb_module *module, struct ldb_request *req)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = vlv_results(ac);
|
||||
+ ret = vlv_results(ac, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
- return ldb_module_done(req, NULL, NULL, ret);
|
||||
+ return ret;
|
||||
}
|
||||
return ldb_module_done(req, ac->controls, NULL,
|
||||
LDB_SUCCESS);
|
||||
--
|
||||
2.17.1
|
||||
|
||||
272
CVE-2020-10745-1.patch
Normal file
272
CVE-2020-10745-1.patch
Normal file
@ -0,0 +1,272 @@
|
||||
From ddd3ed7ce2e2776839c463010bd975f01dd0977d Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Thu, 11 Jun 2020 17:38:51 +1200
|
||||
Subject: [PATCH 12/22] CVE-2020-10745: pytests: hand-rolled invalid dns/nbt
|
||||
packet tests
|
||||
|
||||
The client libraries don't allow us to make packets that are broken in
|
||||
certain ways, so we need to construct them as byte strings.
|
||||
|
||||
These tests all fail at present, proving the server is rendered
|
||||
unresponsive, which is the crux of CVE-2020-10745.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
python/samba/tests/dns_packet.py | 211 +++++++++++++++++++++++++++++++
|
||||
selftest/knownfail.d/dns_packet | 2 +
|
||||
source4/selftest/tests.py | 10 ++
|
||||
3 files changed, 223 insertions(+)
|
||||
create mode 100644 python/samba/tests/dns_packet.py
|
||||
create mode 100644 selftest/knownfail.d/dns_packet
|
||||
|
||||
diff --git a/python/samba/tests/dns_packet.py b/python/samba/tests/dns_packet.py
|
||||
new file mode 100644
|
||||
index 00000000000..c4f843eb613
|
||||
--- /dev/null
|
||||
+++ b/python/samba/tests/dns_packet.py
|
||||
@@ -0,0 +1,211 @@
|
||||
+# Tests of malformed DNS packets
|
||||
+# Copyright (C) Catalyst.NET ltd
|
||||
+#
|
||||
+# written by Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
+#
|
||||
+# 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 <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+"""Sanity tests for DNS and NBT server parsing.
|
||||
+
|
||||
+We don't use a proper client library so we can make improper packets.
|
||||
+"""
|
||||
+
|
||||
+import os
|
||||
+import struct
|
||||
+import socket
|
||||
+import select
|
||||
+from samba.dcerpc import dns, nbt
|
||||
+
|
||||
+from samba.tests import TestCase
|
||||
+
|
||||
+
|
||||
+def _msg_id():
|
||||
+ while True:
|
||||
+ for i in range(1, 0xffff):
|
||||
+ yield i
|
||||
+
|
||||
+
|
||||
+SERVER = os.environ['SERVER_IP']
|
||||
+SERVER_NAME = f"{os.environ['SERVER']}.{os.environ['REALM']}"
|
||||
+TIMEOUT = 0.5
|
||||
+
|
||||
+
|
||||
+def encode_netbios_bytes(chars):
|
||||
+ """Even RFC 1002 uses distancing quotes when calling this "compression"."""
|
||||
+ out = []
|
||||
+ chars = (chars + b' ')[:16]
|
||||
+ for c in chars:
|
||||
+ out.append((c >> 4) + 65)
|
||||
+ out.append((c & 15) + 65)
|
||||
+ return bytes(out)
|
||||
+
|
||||
+
|
||||
+class TestDnsPacketBase(TestCase):
|
||||
+ msg_id = _msg_id()
|
||||
+
|
||||
+ def tearDown(self):
|
||||
+ # we need to ensure the DNS server is responsive before
|
||||
+ # continuing.
|
||||
+ for i in range(40):
|
||||
+ ok = self._known_good_query()
|
||||
+ if ok:
|
||||
+ return
|
||||
+ print(f"the server is STILL unresponsive after {40 * TIMEOUT} seconds")
|
||||
+
|
||||
+ def decode_reply(self, data):
|
||||
+ header = data[:12]
|
||||
+ id, flags, n_q, n_a, n_rec, n_exta = struct.unpack('!6H',
|
||||
+ header)
|
||||
+ return {
|
||||
+ 'rcode': flags & 0xf
|
||||
+ }
|
||||
+
|
||||
+ def construct_query(self, names):
|
||||
+ """Create a query packet containing one query record.
|
||||
+
|
||||
+ *names* is either a single string name in the usual dotted
|
||||
+ form, or a list of names. In the latter case, each name can
|
||||
+ be a dotted string or a list of byte components, which allows
|
||||
+ dots in components. Where I say list, I mean non-string
|
||||
+ iterable.
|
||||
+
|
||||
+ Examples:
|
||||
+
|
||||
+ # these 3 are all the same
|
||||
+ "example.com"
|
||||
+ ["example.com"]
|
||||
+ [[b"example", b"com"]]
|
||||
+
|
||||
+ # this is three names in the same request
|
||||
+ ["example.com",
|
||||
+ [b"example", b"com", b"..!"],
|
||||
+ (b"first component", b" 2nd component")]
|
||||
+ """
|
||||
+ header = struct.pack('!6H',
|
||||
+ next(self.msg_id),
|
||||
+ 0x0100, # query, with recursion
|
||||
+ len(names), # number of queries
|
||||
+ 0x0000, # no answers
|
||||
+ 0x0000, # no records
|
||||
+ 0x0000, # no extra records
|
||||
+ )
|
||||
+ tail = struct.pack('!BHH',
|
||||
+ 0x00, # root node
|
||||
+ self.qtype,
|
||||
+ 0x0001, # class IN-ternet
|
||||
+ )
|
||||
+ encoded_bits = []
|
||||
+ for name in names:
|
||||
+ if isinstance(name, str):
|
||||
+ bits = name.encode('utf8').split(b'.')
|
||||
+ else:
|
||||
+ bits = name
|
||||
+
|
||||
+ for b in bits:
|
||||
+ encoded_bits.append(b'%c%s' % (len(b), b))
|
||||
+ encoded_bits.append(tail)
|
||||
+
|
||||
+ return header + b''.join(encoded_bits)
|
||||
+
|
||||
+ def _test_query(self, names=(), expected_rcode=None):
|
||||
+
|
||||
+ if isinstance(names, str):
|
||||
+ names = [names]
|
||||
+
|
||||
+ packet = self.construct_query(names)
|
||||
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
+ s.sendto(packet, self.server)
|
||||
+ r, _, _ = select.select([s], [], [], TIMEOUT)
|
||||
+ s.close()
|
||||
+ # It is reasonable to not reply to these packets (Windows
|
||||
+ # doesn't), but it is not reasonable to render the server
|
||||
+ # unresponsive.
|
||||
+ if r != [s]:
|
||||
+ ok = self._known_good_query()
|
||||
+ self.assertTrue(ok, f"the server is unresponsive")
|
||||
+
|
||||
+ def _known_good_query(self):
|
||||
+ if self.server[1] == 53:
|
||||
+ name = SERVER_NAME
|
||||
+ expected_rcode = dns.DNS_RCODE_OK
|
||||
+ else:
|
||||
+ name = [encode_netbios_bytes(b'nxdomain'), b'nxdomain']
|
||||
+ expected_rcode = nbt.NBT_RCODE_NAM
|
||||
+
|
||||
+ packet = self.construct_query([name])
|
||||
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
+ s.sendto(packet, self.server)
|
||||
+ r, _, _ = select.select([s], [], [], TIMEOUT)
|
||||
+ if r != [s]:
|
||||
+ s.close()
|
||||
+ return False
|
||||
+
|
||||
+ data, addr = s.recvfrom(4096)
|
||||
+ s.close()
|
||||
+ rcode = self.decode_reply(data)['rcode']
|
||||
+ return expected_rcode == rcode
|
||||
+
|
||||
+
|
||||
+class TestDnsPackets(TestDnsPacketBase):
|
||||
+ server = (SERVER, 53)
|
||||
+ qtype = 1 # dns type A
|
||||
+
|
||||
+ def _test_many_repeated_components(self, label, n, expected_rcode=None):
|
||||
+ name = [label] * n
|
||||
+ self._test_query([name],
|
||||
+ expected_rcode=expected_rcode)
|
||||
+
|
||||
+ def test_127_very_dotty_components(self):
|
||||
+ label = b'.' * 63
|
||||
+ self._test_many_repeated_components(label, 127)
|
||||
+
|
||||
+ def test_127_half_dotty_components(self):
|
||||
+ label = b'x.' * 31 + b'x'
|
||||
+ self._test_many_repeated_components(label, 127)
|
||||
+
|
||||
+
|
||||
+class TestNbtPackets(TestDnsPacketBase):
|
||||
+ server = (SERVER, 137)
|
||||
+ qtype = 0x20 # NBT_QTYPE_NETBIOS
|
||||
+
|
||||
+ def _test_nbt_encode_query(self, names, *args, **kwargs):
|
||||
+ if isinstance(names, str):
|
||||
+ names = [names]
|
||||
+
|
||||
+ nbt_names = []
|
||||
+ for name in names:
|
||||
+ if isinstance(name, str):
|
||||
+ bits = name.encode('utf8').split(b'.')
|
||||
+ else:
|
||||
+ bits = name
|
||||
+
|
||||
+ encoded = [encode_netbios_bytes(bits[0])]
|
||||
+ encoded.extend(bits[1:])
|
||||
+ nbt_names.append(encoded)
|
||||
+
|
||||
+ self._test_query(nbt_names, *args, **kwargs)
|
||||
+
|
||||
+ def _test_many_repeated_components(self, label, n, expected_rcode=None):
|
||||
+ name = [label] * n
|
||||
+ name[0] = encode_netbios_bytes(label)
|
||||
+ self._test_query([name],
|
||||
+ expected_rcode=expected_rcode)
|
||||
+
|
||||
+ def test_127_very_dotty_components(self):
|
||||
+ label = b'.' * 63
|
||||
+ self._test_many_repeated_components(label, 127)
|
||||
+
|
||||
+ def test_127_half_dotty_components(self):
|
||||
+ label = b'x.' * 31 + b'x'
|
||||
+ self._test_many_repeated_components(label, 127)
|
||||
diff --git a/selftest/knownfail.d/dns_packet b/selftest/knownfail.d/dns_packet
|
||||
new file mode 100644
|
||||
index 00000000000..6e2e5a699de
|
||||
--- /dev/null
|
||||
+++ b/selftest/knownfail.d/dns_packet
|
||||
@@ -0,0 +1,2 @@
|
||||
+samba.tests.dns_packet.samba.tests.dns_packet.TestDnsPackets.test_127_very_dotty_components
|
||||
+samba.tests.dns_packet.samba.tests.dns_packet.TestNbtPackets.test_127_very_dotty_components
|
||||
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
|
||||
index f7645365384..6281b7e8f12 100755
|
||||
--- a/source4/selftest/tests.py
|
||||
+++ b/source4/selftest/tests.py
|
||||
@@ -421,6 +421,16 @@ plantestsuite_loadlist("samba.tests.dns_wildcard", "ad_dc", [python, os.path.joi
|
||||
|
||||
plantestsuite_loadlist("samba.tests.dns_invalid", "ad_dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_invalid.py"), '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
|
||||
|
||||
+plantestsuite_loadlist("samba.tests.dns_packet",
|
||||
+ "ad_dc",
|
||||
+ [python,
|
||||
+ '-msamba.subunit.run',
|
||||
+ '$LOADLIST',
|
||||
+ "$LISTOPT"
|
||||
+ "samba.tests.dns_packet"
|
||||
+ ])
|
||||
+
|
||||
+
|
||||
for t in smbtorture4_testsuites("dns_internal."):
|
||||
plansmbtorture4testsuite(t, "ad_dc_default:local", '//$SERVER/whavever')
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
316
CVE-2020-10745-2.patch
Normal file
316
CVE-2020-10745-2.patch
Normal file
@ -0,0 +1,316 @@
|
||||
From ddeabf87957ce73e12030977948418c93436a05c Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Fri, 12 Jun 2020 14:26:38 +1200
|
||||
Subject: [PATCH 13/22] CVE-2020-10745: librpc/tests: cmocka tests of dns and
|
||||
ndr strings
|
||||
|
||||
These time the push and pull function in isolation.
|
||||
|
||||
Timing should be under 0.0001 seconds on even quite old hardware; we
|
||||
assert it must be under 0.2 seconds.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
(backported from master commit)
|
||||
[abartlet@samba.org: backported due to differences in pre-existing
|
||||
tests - eg test_ndr - mentioned in wscript_build and tests.py]
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/tests/test_ndr_dns_nbt.c | 236 +++++++++++++++++++++++++++++++
|
||||
librpc/wscript_build | 13 ++
|
||||
selftest/knownfail.d/ndr_dns_nbt | 4 +
|
||||
source4/selftest/tests.py | 2 +
|
||||
4 files changed, 255 insertions(+)
|
||||
create mode 100644 librpc/tests/test_ndr_dns_nbt.c
|
||||
create mode 100644 selftest/knownfail.d/ndr_dns_nbt
|
||||
|
||||
diff --git a/librpc/tests/test_ndr_dns_nbt.c b/librpc/tests/test_ndr_dns_nbt.c
|
||||
new file mode 100644
|
||||
index 00000000000..1e2ef45c10d
|
||||
--- /dev/null
|
||||
+++ b/librpc/tests/test_ndr_dns_nbt.c
|
||||
@@ -0,0 +1,236 @@
|
||||
+/*
|
||||
+ * Tests for librpc ndr functions
|
||||
+ *
|
||||
+ * Copyright (C) Catalyst.NET Ltd 2020
|
||||
+ *
|
||||
+ * 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 <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include "replace.h"
|
||||
+#include <setjmp.h>
|
||||
+#include <cmocka.h>
|
||||
+
|
||||
+#include "includes.h"
|
||||
+#include "librpc/ndr/libndr.h"
|
||||
+#include "librpc/gen_ndr/ndr_dns.h"
|
||||
+#include "librpc/gen_ndr/ndr_nbt.h"
|
||||
+#include "lib/util/time.h"
|
||||
+
|
||||
+#define NBT_NAME "EOGFGLGPCACACACACACACACACACACACA" /* "neko" */
|
||||
+
|
||||
+
|
||||
+static DATA_BLOB generate_obnoxious_dns_name(TALLOC_CTX *mem_ctx,
|
||||
+ size_t n_labels,
|
||||
+ size_t dot_every,
|
||||
+ bool is_nbt)
|
||||
+{
|
||||
+ size_t i, j;
|
||||
+ char *s;
|
||||
+ DATA_BLOB name = data_blob_talloc(mem_ctx, NULL, 64 * n_labels + 1);
|
||||
+ assert_non_null(name.data);
|
||||
+
|
||||
+ s = (char*)name.data;
|
||||
+ if (is_nbt) {
|
||||
+ size_t len = strlen(NBT_NAME);
|
||||
+ *s = len;
|
||||
+ s++;
|
||||
+ memcpy(s, NBT_NAME, len);
|
||||
+ s += len;
|
||||
+ n_labels--;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < n_labels; i++) {
|
||||
+ *s = 63;
|
||||
+ s++;
|
||||
+ for (j = 0; j < 63; j++) {
|
||||
+ if (j % dot_every == (dot_every - 1)) {
|
||||
+ *s = '.';
|
||||
+ } else {
|
||||
+ *s = 'x';
|
||||
+ }
|
||||
+ s++;
|
||||
+ }
|
||||
+ }
|
||||
+ *s = 0;
|
||||
+ s++;
|
||||
+ name.length = s - (char*)name.data;
|
||||
+ return name;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static char *_test_ndr_pull_dns_string_list(TALLOC_CTX *mem_ctx,
|
||||
+ size_t n_labels,
|
||||
+ size_t dot_every,
|
||||
+ bool is_nbt)
|
||||
+{
|
||||
+ enum ndr_err_code ndr_err;
|
||||
+ DATA_BLOB blob = generate_obnoxious_dns_name(mem_ctx,
|
||||
+ n_labels,
|
||||
+ dot_every,
|
||||
+ is_nbt);
|
||||
+
|
||||
+ char *name;
|
||||
+ ndr_pull_flags_fn_t fn;
|
||||
+
|
||||
+ if (is_nbt) {
|
||||
+ fn = (ndr_pull_flags_fn_t)ndr_pull_nbt_string;
|
||||
+ } else {
|
||||
+ fn = (ndr_pull_flags_fn_t)ndr_pull_dns_string;
|
||||
+ }
|
||||
+
|
||||
+ ndr_err = ndr_pull_struct_blob(&blob,
|
||||
+ mem_ctx,
|
||||
+ &name,
|
||||
+ fn);
|
||||
+ /* Success here is not expected, but we let it go to measure timing. */
|
||||
+ if (ndr_err == NDR_ERR_SUCCESS) {
|
||||
+ printf("pull succeed\n");
|
||||
+ } else {
|
||||
+ assert_int_equal(ndr_err, NDR_ERR_STRING);
|
||||
+ }
|
||||
+
|
||||
+ TALLOC_FREE(blob.data);
|
||||
+ return name;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void _test_ndr_push_dns_string_list(TALLOC_CTX *mem_ctx,
|
||||
+ char *name,
|
||||
+ bool is_nbt)
|
||||
+{
|
||||
+ DATA_BLOB blob;
|
||||
+ enum ndr_err_code ndr_err;
|
||||
+ ndr_push_flags_fn_t fn;
|
||||
+
|
||||
+ if (is_nbt) {
|
||||
+ fn = (ndr_push_flags_fn_t)ndr_push_nbt_string;
|
||||
+ } else {
|
||||
+ fn = (ndr_push_flags_fn_t)ndr_push_dns_string;
|
||||
+ }
|
||||
+
|
||||
+ ndr_err = ndr_push_struct_blob(&blob,
|
||||
+ mem_ctx,
|
||||
+ name,
|
||||
+ fn);
|
||||
+
|
||||
+ /* Success here is not expected, but we let it go to measure timing. */
|
||||
+ if (ndr_err == NDR_ERR_SUCCESS) {
|
||||
+ printf("push succeed\n");
|
||||
+ } else {
|
||||
+ assert_int_equal(ndr_err, NDR_ERR_STRING);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static uint64_t elapsed_time(struct timespec start, const char *print)
|
||||
+{
|
||||
+ struct timespec end;
|
||||
+ unsigned long long microsecs;
|
||||
+ clock_gettime_mono(&end);
|
||||
+ end.tv_sec -= start.tv_sec;
|
||||
+ if (end.tv_nsec < start.tv_nsec) {
|
||||
+ /* we need to borrow */
|
||||
+ end.tv_nsec += 1000 * 1000 * 1000;
|
||||
+ end.tv_sec -= 1;
|
||||
+ }
|
||||
+ end.tv_nsec -= start.tv_nsec;
|
||||
+ microsecs = end.tv_sec * 1000000;
|
||||
+ microsecs += end.tv_nsec / 1000;
|
||||
+
|
||||
+ if (print != NULL) {
|
||||
+ printf(" %s: %llu microseconds\n", print, microsecs);
|
||||
+ }
|
||||
+ return microsecs;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void test_ndr_dns_string_half_dots(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
+ char *name;
|
||||
+ struct timespec start;
|
||||
+ uint64_t elapsed;
|
||||
+
|
||||
+ clock_gettime_mono(&start);
|
||||
+ name =_test_ndr_pull_dns_string_list(mem_ctx, 127, 2, false);
|
||||
+ elapsed_time(start, "pull");
|
||||
+ _test_ndr_push_dns_string_list(mem_ctx, name, false);
|
||||
+ elapsed = elapsed_time(start, "total");
|
||||
+ assert_in_range(elapsed, 0, 200000);
|
||||
+ talloc_free(mem_ctx);
|
||||
+}
|
||||
+
|
||||
+static void test_ndr_nbt_string_half_dots(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
+ char *name;
|
||||
+ struct timespec start;
|
||||
+ uint64_t elapsed;
|
||||
+
|
||||
+ clock_gettime_mono(&start);
|
||||
+ name =_test_ndr_pull_dns_string_list(mem_ctx, 127, 2, true);
|
||||
+ elapsed_time(start, "pull");
|
||||
+ _test_ndr_push_dns_string_list(mem_ctx, name, true);
|
||||
+ elapsed = elapsed_time(start, "total");
|
||||
+ assert_in_range(elapsed, 0, 200000);
|
||||
+ talloc_free(mem_ctx);
|
||||
+}
|
||||
+
|
||||
+static void test_ndr_dns_string_all_dots(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
+ char *name;
|
||||
+ struct timespec start;
|
||||
+ uint64_t elapsed;
|
||||
+
|
||||
+ clock_gettime_mono(&start);
|
||||
+ name =_test_ndr_pull_dns_string_list(mem_ctx, 127, 1, false);
|
||||
+ elapsed_time(start, "pull");
|
||||
+ _test_ndr_push_dns_string_list(mem_ctx, name, false);
|
||||
+ elapsed = elapsed_time(start, "total");
|
||||
+ assert_in_range(elapsed, 0, 200000);
|
||||
+ talloc_free(mem_ctx);
|
||||
+}
|
||||
+
|
||||
+static void test_ndr_nbt_string_all_dots(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
+ char *name;
|
||||
+ struct timespec start;
|
||||
+ uint64_t elapsed;
|
||||
+
|
||||
+ clock_gettime_mono(&start);
|
||||
+ name =_test_ndr_pull_dns_string_list(mem_ctx, 127, 1, true);
|
||||
+ elapsed_time(start, "pull");
|
||||
+ _test_ndr_push_dns_string_list(mem_ctx, name, true);
|
||||
+ elapsed = elapsed_time(start, "total");
|
||||
+ assert_in_range(elapsed, 0, 200000);
|
||||
+ talloc_free(mem_ctx);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+int main(int argc, const char **argv)
|
||||
+{
|
||||
+ const struct CMUnitTest tests[] = {
|
||||
+ cmocka_unit_test(test_ndr_nbt_string_half_dots),
|
||||
+ cmocka_unit_test(test_ndr_dns_string_half_dots),
|
||||
+ cmocka_unit_test(test_ndr_nbt_string_all_dots),
|
||||
+ cmocka_unit_test(test_ndr_dns_string_all_dots),
|
||||
+ };
|
||||
+
|
||||
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
|
||||
+ return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
+}
|
||||
diff --git a/librpc/wscript_build b/librpc/wscript_build
|
||||
index 70fe8c2f7fe..e3be298c725 100644
|
||||
--- a/librpc/wscript_build
|
||||
+++ b/librpc/wscript_build
|
||||
@@ -656,3 +656,16 @@ bld.SAMBA_SUBSYSTEM('NDR_FSRVP_STATE',
|
||||
source='gen_ndr/ndr_fsrvp_state.c',
|
||||
public_deps='ndr'
|
||||
)
|
||||
+#
|
||||
+# Cmocka tests
|
||||
+#
|
||||
+
|
||||
+bld.SAMBA_BINARY('test_ndr_dns_nbt',
|
||||
+ source='tests/test_ndr_dns_nbt.c',
|
||||
+ deps='''
|
||||
+ cmocka
|
||||
+ ndr
|
||||
+ ndr_nbt
|
||||
+ NDR_DNS
|
||||
+ ''',
|
||||
+ install=False)
|
||||
diff --git a/selftest/knownfail.d/ndr_dns_nbt b/selftest/knownfail.d/ndr_dns_nbt
|
||||
new file mode 100644
|
||||
index 00000000000..f30217c4033
|
||||
--- /dev/null
|
||||
+++ b/selftest/knownfail.d/ndr_dns_nbt
|
||||
@@ -0,0 +1,4 @@
|
||||
+librpc.ndr.ndr_dns_nbt.test_ndr_dns_string_all_dots
|
||||
+librpc.ndr.ndr_dns_nbt.test_ndr_dns_string_half_dots
|
||||
+librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_all_dots
|
||||
+librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_half_dots
|
||||
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
|
||||
index 6281b7e8f12..e8dbed71a18 100755
|
||||
--- a/source4/selftest/tests.py
|
||||
+++ b/source4/selftest/tests.py
|
||||
@@ -1337,6 +1337,8 @@ plantestsuite("samba4.dcerpc.dnsserver.dnsutils", "none",
|
||||
[os.path.join(bindir(), "test_rpc_dns_server_dnsutils")])
|
||||
plantestsuite("libcli.drsuapi.repl_decrypt", "none",
|
||||
[os.path.join(bindir(), "test_repl_decrypt")])
|
||||
+plantestsuite("librpc.ndr.ndr_dns_nbt", "none",
|
||||
+ [os.path.join(bindir(), "test_ndr_dns_nbt")])
|
||||
|
||||
# process restart and limit tests, these break the environment so need to run
|
||||
# in their own specific environment
|
||||
--
|
||||
2.17.1
|
||||
|
||||
241
CVE-2020-10745-3.patch
Normal file
241
CVE-2020-10745-3.patch
Normal file
@ -0,0 +1,241 @@
|
||||
From 37cacb8f41b9b2ea19a9c1bbfade4ea250dced46 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Sat, 25 Apr 2020 11:02:08 +1200
|
||||
Subject: [PATCH 14/22] CVE-2020-10745: ndr_dns: move ndr_push_dns_string core
|
||||
into sharable function
|
||||
|
||||
This is because ndr_nbt.c does almost exactly the same thing with
|
||||
almost exactly the same code, and they both do it wrong. Soon they
|
||||
will both be using the better version that this will become. Though in
|
||||
this patch we just move the code, not fix it.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/ndr/ndr_dns.c | 79 +++-------------------------------
|
||||
librpc/ndr/ndr_dns_utils.c | 88 ++++++++++++++++++++++++++++++++++++++
|
||||
librpc/ndr/ndr_dns_utils.h | 5 +++
|
||||
librpc/wscript_build | 2 +-
|
||||
4 files changed, 99 insertions(+), 75 deletions(-)
|
||||
create mode 100644 librpc/ndr/ndr_dns_utils.c
|
||||
create mode 100644 librpc/ndr/ndr_dns_utils.h
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
|
||||
index d37c8cc2ece..68a3c9de782 100644
|
||||
--- a/librpc/ndr/ndr_dns.c
|
||||
+++ b/librpc/ndr/ndr_dns.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "librpc/gen_ndr/ndr_dnsp.h"
|
||||
#include "system/locale.h"
|
||||
#include "lib/util/util_net.h"
|
||||
+#include "ndr_dns_utils.h"
|
||||
|
||||
/* don't allow an unlimited number of name components */
|
||||
#define MAX_COMPONENTS 128
|
||||
@@ -159,80 +160,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
|
||||
int ndr_flags,
|
||||
const char *s)
|
||||
{
|
||||
- if (!(ndr_flags & NDR_SCALARS)) {
|
||||
- return NDR_ERR_SUCCESS;
|
||||
- }
|
||||
-
|
||||
- while (s && *s) {
|
||||
- enum ndr_err_code ndr_err;
|
||||
- char *compname;
|
||||
- size_t complen;
|
||||
- uint32_t offset;
|
||||
-
|
||||
- if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
- /* see if we have pushed the remaining string already,
|
||||
- * if so we use a label pointer to this string
|
||||
- */
|
||||
- ndr_err = ndr_token_retrieve_cmp_fn(&ndr->dns_string_list, s,
|
||||
- &offset,
|
||||
- (comparison_fn_t)strcmp,
|
||||
- false);
|
||||
- if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
- uint8_t b[2];
|
||||
-
|
||||
- if (offset > 0x3FFF) {
|
||||
- return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
- "offset for dns string " \
|
||||
- "label pointer " \
|
||||
- "%u[%08X] > 0x00003FFF",
|
||||
- offset, offset);
|
||||
- }
|
||||
-
|
||||
- b[0] = 0xC0 | (offset>>8);
|
||||
- b[1] = (offset & 0xFF);
|
||||
-
|
||||
- return ndr_push_bytes(ndr, b, 2);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- complen = strcspn(s, ".");
|
||||
-
|
||||
- /* we need to make sure the length fits into 6 bytes */
|
||||
- if (complen > 0x3F) {
|
||||
- return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
- "component length %u[%08X] > " \
|
||||
- "0x0000003F",
|
||||
- (unsigned)complen,
|
||||
- (unsigned)complen);
|
||||
- }
|
||||
-
|
||||
- compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
- (unsigned char)complen,
|
||||
- (unsigned char)complen,
|
||||
- (unsigned char)complen, s);
|
||||
- NDR_ERR_HAVE_NO_MEMORY(compname);
|
||||
-
|
||||
- /* remember the current component + the rest of the string
|
||||
- * so it can be reused later
|
||||
- */
|
||||
- if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
- NDR_CHECK(ndr_token_store(ndr, &ndr->dns_string_list, s,
|
||||
- ndr->offset));
|
||||
- }
|
||||
-
|
||||
- /* push just this component into the blob */
|
||||
- NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname,
|
||||
- complen+1));
|
||||
- talloc_free(compname);
|
||||
-
|
||||
- s += complen;
|
||||
- if (*s == '.') s++;
|
||||
- }
|
||||
-
|
||||
- /* if we reach the end of the string and have pushed the last component
|
||||
- * without using a label pointer, we need to terminate the string
|
||||
- */
|
||||
- return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
|
||||
+ return ndr_push_dns_string_list(ndr,
|
||||
+ &ndr->dns_string_list,
|
||||
+ ndr_flags,
|
||||
+ s);
|
||||
}
|
||||
|
||||
_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
|
||||
new file mode 100644
|
||||
index 00000000000..2d9b5f1bc1e
|
||||
--- /dev/null
|
||||
+++ b/librpc/ndr/ndr_dns_utils.c
|
||||
@@ -0,0 +1,88 @@
|
||||
+#include "includes.h"
|
||||
+#include "../librpc/ndr/libndr.h"
|
||||
+#include "ndr_dns_utils.h"
|
||||
+
|
||||
+
|
||||
+/**
|
||||
+ push a dns/nbt string list to the wire
|
||||
+*/
|
||||
+enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
+ struct ndr_token_list *string_list,
|
||||
+ int ndr_flags,
|
||||
+ const char *s)
|
||||
+{
|
||||
+ if (!(ndr_flags & NDR_SCALARS)) {
|
||||
+ return NDR_ERR_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ while (s && *s) {
|
||||
+ enum ndr_err_code ndr_err;
|
||||
+ char *compname;
|
||||
+ size_t complen;
|
||||
+ uint32_t offset;
|
||||
+
|
||||
+ if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
+ /* see if we have pushed the remaining string already,
|
||||
+ * if so we use a label pointer to this string
|
||||
+ */
|
||||
+ ndr_err = ndr_token_retrieve_cmp_fn(string_list, s,
|
||||
+ &offset,
|
||||
+ (comparison_fn_t)strcmp,
|
||||
+ false);
|
||||
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
+ uint8_t b[2];
|
||||
+
|
||||
+ if (offset > 0x3FFF) {
|
||||
+ return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
+ "offset for dns string " \
|
||||
+ "label pointer " \
|
||||
+ "%u[%08X] > 0x00003FFF",
|
||||
+ offset, offset);
|
||||
+ }
|
||||
+
|
||||
+ b[0] = 0xC0 | (offset>>8);
|
||||
+ b[1] = (offset & 0xFF);
|
||||
+
|
||||
+ return ndr_push_bytes(ndr, b, 2);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ complen = strcspn(s, ".");
|
||||
+
|
||||
+ /* we need to make sure the length fits into 6 bytes */
|
||||
+ if (complen > 0x3F) {
|
||||
+ return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
+ "component length %u[%08X] > " \
|
||||
+ "0x0000003F",
|
||||
+ (unsigned)complen,
|
||||
+ (unsigned)complen);
|
||||
+ }
|
||||
+
|
||||
+ compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
+ (unsigned char)complen,
|
||||
+ (unsigned char)complen,
|
||||
+ (unsigned char)complen, s);
|
||||
+ NDR_ERR_HAVE_NO_MEMORY(compname);
|
||||
+
|
||||
+ /* remember the current component + the rest of the string
|
||||
+ * so it can be reused later
|
||||
+ */
|
||||
+ if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
+ NDR_CHECK(ndr_token_store(ndr, string_list, s,
|
||||
+ ndr->offset));
|
||||
+ }
|
||||
+
|
||||
+ /* push just this component into the blob */
|
||||
+ NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname,
|
||||
+ complen+1));
|
||||
+ talloc_free(compname);
|
||||
+
|
||||
+ s += complen;
|
||||
+ if (*s == '.') s++;
|
||||
+ }
|
||||
+
|
||||
+ /* if we reach the end of the string and have pushed the last component
|
||||
+ * without using a label pointer, we need to terminate the string
|
||||
+ */
|
||||
+ return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
|
||||
+}
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.h b/librpc/ndr/ndr_dns_utils.h
|
||||
new file mode 100644
|
||||
index 00000000000..823e3201112
|
||||
--- /dev/null
|
||||
+++ b/librpc/ndr/ndr_dns_utils.h
|
||||
@@ -0,0 +1,5 @@
|
||||
+
|
||||
+enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
+ struct ndr_token_list *string_list,
|
||||
+ int ndr_flags,
|
||||
+ const char *s);
|
||||
diff --git a/librpc/wscript_build b/librpc/wscript_build
|
||||
index e3be298c725..c165500644b 100644
|
||||
--- a/librpc/wscript_build
|
||||
+++ b/librpc/wscript_build
|
||||
@@ -31,7 +31,7 @@ bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
|
||||
)
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('NDR_DNS',
|
||||
- source='gen_ndr/ndr_dns.c ndr/ndr_dns.c',
|
||||
+ source='gen_ndr/ndr_dns.c ndr/ndr_dns.c ndr/ndr_dns_utils.c',
|
||||
public_deps='ndr NDR_DNSP'
|
||||
)
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
28
CVE-2020-10745-4.patch
Normal file
28
CVE-2020-10745-4.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From b687813ac362ff71085d192a4b7821235345feea Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Sat, 25 Apr 2020 11:03:30 +1200
|
||||
Subject: [PATCH 15/22] CVE-2020-10745: ndr/dns_utils: correct a comment
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/ndr/ndr_dns_utils.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
|
||||
index 2d9b5f1bc1e..2ce300863bc 100644
|
||||
--- a/librpc/ndr/ndr_dns_utils.c
|
||||
+++ b/librpc/ndr/ndr_dns_utils.c
|
||||
@@ -49,7 +49,7 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
|
||||
complen = strcspn(s, ".");
|
||||
|
||||
- /* we need to make sure the length fits into 6 bytes */
|
||||
+ /* the length must fit into 6 bits (i.e. <= 63) */
|
||||
if (complen > 0x3F) {
|
||||
return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
"component length %u[%08X] > " \
|
||||
--
|
||||
2.17.1
|
||||
|
||||
54
CVE-2020-10745-5.patch
Normal file
54
CVE-2020-10745-5.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 507503f80e8913450364dcd8ab080f3211b6f855 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Sat, 25 Apr 2020 11:10:18 +1200
|
||||
Subject: [PATCH 16/22] CVE-2020-10745: ndr_dns: do not allow consecutive dots
|
||||
|
||||
The empty subdomain component is reserved for the root domain, which we
|
||||
should only (and always) see at the end of the list. That is, we expect
|
||||
"example.com.", but never "example..com".
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/ndr/ndr_dns_utils.c | 6 ++++++
|
||||
selftest/knownfail.d/dns_packet | 1 -
|
||||
selftest/knownfail.d/ndr_dns_nbt | 1 -
|
||||
3 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
|
||||
index 2ce300863bc..6931dac422d 100644
|
||||
--- a/librpc/ndr/ndr_dns_utils.c
|
||||
+++ b/librpc/ndr/ndr_dns_utils.c
|
||||
@@ -58,6 +58,12 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
(unsigned)complen);
|
||||
}
|
||||
|
||||
+ if (complen == 0 && s[complen] == '.') {
|
||||
+ return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
+ "component length is 0 "
|
||||
+ "(consecutive dots)");
|
||||
+ }
|
||||
+
|
||||
compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
(unsigned char)complen,
|
||||
(unsigned char)complen,
|
||||
diff --git a/selftest/knownfail.d/dns_packet b/selftest/knownfail.d/dns_packet
|
||||
index 6e2e5a699de..0662266f689 100644
|
||||
--- a/selftest/knownfail.d/dns_packet
|
||||
+++ b/selftest/knownfail.d/dns_packet
|
||||
@@ -1,2 +1 @@
|
||||
-samba.tests.dns_packet.samba.tests.dns_packet.TestDnsPackets.test_127_very_dotty_components
|
||||
samba.tests.dns_packet.samba.tests.dns_packet.TestNbtPackets.test_127_very_dotty_components
|
||||
diff --git a/selftest/knownfail.d/ndr_dns_nbt b/selftest/knownfail.d/ndr_dns_nbt
|
||||
index f30217c4033..e11c121b7a7 100644
|
||||
--- a/selftest/knownfail.d/ndr_dns_nbt
|
||||
+++ b/selftest/knownfail.d/ndr_dns_nbt
|
||||
@@ -1,4 +1,3 @@
|
||||
-librpc.ndr.ndr_dns_nbt.test_ndr_dns_string_all_dots
|
||||
librpc.ndr.ndr_dns_nbt.test_ndr_dns_string_half_dots
|
||||
librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_all_dots
|
||||
librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_half_dots
|
||||
--
|
||||
2.17.1
|
||||
|
||||
55
CVE-2020-10745-6.patch
Normal file
55
CVE-2020-10745-6.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 83b00656ea0e8cfdce8a9c1cef71e41477e8e6f0 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Fri, 15 May 2020 00:06:08 +1200
|
||||
Subject: [PATCH 17/22] CVE-2020-10745: dns_util/push: forbid names longer than
|
||||
255 bytes
|
||||
|
||||
As per RFC 1035.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/ndr/ndr_dns_utils.c | 10 +++++++++-
|
||||
selftest/knownfail.d/ndr_dns_nbt | 1 -
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
|
||||
index 6931dac422d..b7f11dbab4e 100644
|
||||
--- a/librpc/ndr/ndr_dns_utils.c
|
||||
+++ b/librpc/ndr/ndr_dns_utils.c
|
||||
@@ -11,6 +11,8 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
int ndr_flags,
|
||||
const char *s)
|
||||
{
|
||||
+ const char *start = s;
|
||||
+
|
||||
if (!(ndr_flags & NDR_SCALARS)) {
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
@@ -84,7 +86,13 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
talloc_free(compname);
|
||||
|
||||
s += complen;
|
||||
- if (*s == '.') s++;
|
||||
+ if (*s == '.') {
|
||||
+ s++;
|
||||
+ }
|
||||
+ if (s - start > 255) {
|
||||
+ return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
+ "name > 255 character long");
|
||||
+ }
|
||||
}
|
||||
|
||||
/* if we reach the end of the string and have pushed the last component
|
||||
diff --git a/selftest/knownfail.d/ndr_dns_nbt b/selftest/knownfail.d/ndr_dns_nbt
|
||||
index e11c121b7a7..603395c8c50 100644
|
||||
--- a/selftest/knownfail.d/ndr_dns_nbt
|
||||
+++ b/selftest/knownfail.d/ndr_dns_nbt
|
||||
@@ -1,3 +1,2 @@
|
||||
-librpc.ndr.ndr_dns_nbt.test_ndr_dns_string_half_dots
|
||||
librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_all_dots
|
||||
librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_half_dots
|
||||
--
|
||||
2.17.1
|
||||
|
||||
267
CVE-2020-10745-7.patch
Normal file
267
CVE-2020-10745-7.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From 23e9eb71052e02aecf726609db0256c0d93e0b57 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Fri, 15 May 2020 10:52:45 +1200
|
||||
Subject: [PATCH 18/22] CVE-2020-10745: ndr/dns-utils: prepare for NBT
|
||||
compatibility
|
||||
|
||||
NBT has a funny thing where it sometimes needs to send a trailing dot as
|
||||
part of the last component, because the string representation is a user
|
||||
name. In DNS, "example.com", and "example.com." are the same, both
|
||||
having three components ("example", "com", ""); in NBT, we want to treat
|
||||
them differently, with the second form having the three components
|
||||
("example", "com.", "").
|
||||
|
||||
This retains the logic of e6e2ec0001fe3c010445e26cc0efddbc1f73416b.
|
||||
|
||||
Also DNS compression cannot be turned off for NBT.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
---
|
||||
librpc/ndr/ndr_dns.c | 3 +-
|
||||
librpc/ndr/ndr_dns_utils.c | 42 ++++++++++++++++---
|
||||
librpc/ndr/ndr_dns_utils.h | 3 +-
|
||||
librpc/ndr/ndr_nbt.c | 72 ++++----------------------------
|
||||
librpc/wscript_build | 3 +-
|
||||
selftest/knownfail.d/dns_packet | 1 -
|
||||
selftest/knownfail.d/ndr_dns_nbt | 2 -
|
||||
7 files changed, 49 insertions(+), 77 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/ndr_dns_nbt
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
|
||||
index 68a3c9de782..966e0b59786 100644
|
||||
--- a/librpc/ndr/ndr_dns.c
|
||||
+++ b/librpc/ndr/ndr_dns.c
|
||||
@@ -163,7 +163,8 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
|
||||
return ndr_push_dns_string_list(ndr,
|
||||
&ndr->dns_string_list,
|
||||
ndr_flags,
|
||||
- s);
|
||||
+ s,
|
||||
+ false);
|
||||
}
|
||||
|
||||
_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
|
||||
index b7f11dbab4e..325d9c68bea 100644
|
||||
--- a/librpc/ndr/ndr_dns_utils.c
|
||||
+++ b/librpc/ndr/ndr_dns_utils.c
|
||||
@@ -9,9 +9,32 @@
|
||||
enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
struct ndr_token_list *string_list,
|
||||
int ndr_flags,
|
||||
- const char *s)
|
||||
+ const char *s,
|
||||
+ bool is_nbt)
|
||||
{
|
||||
const char *start = s;
|
||||
+ bool use_compression;
|
||||
+ size_t max_length;
|
||||
+ if (is_nbt) {
|
||||
+ use_compression = true;
|
||||
+ /*
|
||||
+ * Max length is longer in NBT/Wins, because Windows counts
|
||||
+ * the semi-decompressed size of the netbios name (16 bytes)
|
||||
+ * rather than the wire size of 32, which is what you'd expect
|
||||
+ * if it followed RFC1002 (it uses the short form in
|
||||
+ * [MS-WINSRA]). In other words the maximum size of the
|
||||
+ * "scope" is 237, not 221.
|
||||
+ *
|
||||
+ * We make the size limit slightly larger than 255 + 16,
|
||||
+ * because the 237 scope limit is already enforced in the
|
||||
+ * winsserver code with a specific return value; bailing out
|
||||
+ * here would muck with that.
|
||||
+ */
|
||||
+ max_length = 274;
|
||||
+ } else {
|
||||
+ use_compression = !(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION);
|
||||
+ max_length = 255;
|
||||
+ }
|
||||
|
||||
if (!(ndr_flags & NDR_SCALARS)) {
|
||||
return NDR_ERR_SUCCESS;
|
||||
@@ -23,7 +46,7 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
size_t complen;
|
||||
uint32_t offset;
|
||||
|
||||
- if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
+ if (use_compression) {
|
||||
/* see if we have pushed the remaining string already,
|
||||
* if so we use a label pointer to this string
|
||||
*/
|
||||
@@ -66,6 +89,14 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
"(consecutive dots)");
|
||||
}
|
||||
|
||||
+ if (is_nbt && s[complen] == '.' && s[complen + 1] == '\0') {
|
||||
+ /* nbt names are sometimes usernames, and we need to
|
||||
+ * keep a trailing dot to ensure it is byte-identical,
|
||||
+ * (not just semantically identical given DNS
|
||||
+ * semantics). */
|
||||
+ complen++;
|
||||
+ }
|
||||
+
|
||||
compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
(unsigned char)complen,
|
||||
(unsigned char)complen,
|
||||
@@ -75,7 +106,7 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
/* remember the current component + the rest of the string
|
||||
* so it can be reused later
|
||||
*/
|
||||
- if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
|
||||
+ if (use_compression) {
|
||||
NDR_CHECK(ndr_token_store(ndr, string_list, s,
|
||||
ndr->offset));
|
||||
}
|
||||
@@ -89,9 +120,10 @@ enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
if (*s == '.') {
|
||||
s++;
|
||||
}
|
||||
- if (s - start > 255) {
|
||||
+ if (s - start > max_length) {
|
||||
return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
- "name > 255 character long");
|
||||
+ "name > %zu character long",
|
||||
+ max_length);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/librpc/ndr/ndr_dns_utils.h b/librpc/ndr/ndr_dns_utils.h
|
||||
index 823e3201112..71a65433bbb 100644
|
||||
--- a/librpc/ndr/ndr_dns_utils.h
|
||||
+++ b/librpc/ndr/ndr_dns_utils.h
|
||||
@@ -2,4 +2,5 @@
|
||||
enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
|
||||
struct ndr_token_list *string_list,
|
||||
int ndr_flags,
|
||||
- const char *s);
|
||||
+ const char *s,
|
||||
+ bool is_nbt);
|
||||
diff --git a/librpc/ndr/ndr_nbt.c b/librpc/ndr/ndr_nbt.c
|
||||
index 838f947a168..e8dd7549a53 100644
|
||||
--- a/librpc/ndr/ndr_nbt.c
|
||||
+++ b/librpc/ndr/ndr_nbt.c
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "includes.h"
|
||||
#include "../libcli/nbt/libnbt.h"
|
||||
#include "../libcli/netlogon/netlogon.h"
|
||||
+#include "ndr_dns_utils.h"
|
||||
+
|
||||
|
||||
/* don't allow an unlimited number of name components */
|
||||
#define MAX_COMPONENTS 128
|
||||
@@ -141,71 +143,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_fla
|
||||
*/
|
||||
_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s)
|
||||
{
|
||||
- if (!(ndr_flags & NDR_SCALARS)) {
|
||||
- return NDR_ERR_SUCCESS;
|
||||
- }
|
||||
-
|
||||
- while (s && *s) {
|
||||
- enum ndr_err_code ndr_err;
|
||||
- char *compname;
|
||||
- size_t complen;
|
||||
- uint32_t offset;
|
||||
-
|
||||
- /* see if we have pushed the remaining string already,
|
||||
- * if so we use a label pointer to this string
|
||||
- */
|
||||
- ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false);
|
||||
- if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
- uint8_t b[2];
|
||||
-
|
||||
- if (offset > 0x3FFF) {
|
||||
- return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
- "offset for nbt string label pointer %u[%08X] > 0x00003FFF",
|
||||
- offset, offset);
|
||||
- }
|
||||
-
|
||||
- b[0] = 0xC0 | (offset>>8);
|
||||
- b[1] = (offset & 0xFF);
|
||||
-
|
||||
- return ndr_push_bytes(ndr, b, 2);
|
||||
- }
|
||||
-
|
||||
- complen = strcspn(s, ".");
|
||||
-
|
||||
- /* we need to make sure the length fits into 6 bytes */
|
||||
- if (complen > 0x3F) {
|
||||
- return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
- "component length %u[%08X] > 0x0000003F",
|
||||
- (unsigned)complen, (unsigned)complen);
|
||||
- }
|
||||
-
|
||||
- if (s[complen] == '.' && s[complen+1] == '\0') {
|
||||
- complen++;
|
||||
- }
|
||||
-
|
||||
- compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
- (unsigned char)complen,
|
||||
- (unsigned char)complen,
|
||||
- (unsigned char)complen, s);
|
||||
- NDR_ERR_HAVE_NO_MEMORY(compname);
|
||||
-
|
||||
- /* remember the current componemt + the rest of the string
|
||||
- * so it can be reused later
|
||||
- */
|
||||
- NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset));
|
||||
-
|
||||
- /* push just this component into the blob */
|
||||
- NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1));
|
||||
- talloc_free(compname);
|
||||
-
|
||||
- s += complen;
|
||||
- if (*s == '.') s++;
|
||||
- }
|
||||
-
|
||||
- /* if we reach the end of the string and have pushed the last component
|
||||
- * without using a label pointer, we need to terminate the string
|
||||
- */
|
||||
- return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
|
||||
+ return ndr_push_dns_string_list(ndr,
|
||||
+ &ndr->dns_string_list,
|
||||
+ ndr_flags,
|
||||
+ s,
|
||||
+ true);
|
||||
}
|
||||
|
||||
|
||||
diff --git a/librpc/wscript_build b/librpc/wscript_build
|
||||
index c165500644b..4917928a9c4 100644
|
||||
--- a/librpc/wscript_build
|
||||
+++ b/librpc/wscript_build
|
||||
@@ -401,7 +401,7 @@ bld.SAMBA_SUBSYSTEM('NDR_SCHANNEL',
|
||||
|
||||
bld.SAMBA_LIBRARY('ndr_nbt',
|
||||
source='gen_ndr/ndr_nbt.c ndr/ndr_nbt.c',
|
||||
- public_deps='ndr NDR_NBT_BUF NDR_SECURITY',
|
||||
+ public_deps='ndr NDR_NBT_BUF NDR_SECURITY NDR_DNS',
|
||||
public_headers='gen_ndr/nbt.h gen_ndr/ndr_nbt.h ndr/ndr_nbt.h',
|
||||
header_path=[ ('gen_ndr*', 'gen_ndr'), ('ndr*', 'ndr')],
|
||||
pc_files='ndr_nbt.pc',
|
||||
@@ -666,6 +666,5 @@ bld.SAMBA_BINARY('test_ndr_dns_nbt',
|
||||
cmocka
|
||||
ndr
|
||||
ndr_nbt
|
||||
- NDR_DNS
|
||||
''',
|
||||
install=False)
|
||||
diff --git a/selftest/knownfail.d/dns_packet b/selftest/knownfail.d/dns_packet
|
||||
index 0662266f689..e69de29bb2d 100644
|
||||
--- a/selftest/knownfail.d/dns_packet
|
||||
+++ b/selftest/knownfail.d/dns_packet
|
||||
@@ -1 +0,0 @@
|
||||
-samba.tests.dns_packet.samba.tests.dns_packet.TestNbtPackets.test_127_very_dotty_components
|
||||
diff --git a/selftest/knownfail.d/ndr_dns_nbt b/selftest/knownfail.d/ndr_dns_nbt
|
||||
deleted file mode 100644
|
||||
index 603395c8c50..00000000000
|
||||
--- a/selftest/knownfail.d/ndr_dns_nbt
|
||||
+++ /dev/null
|
||||
@@ -1,2 +0,0 @@
|
||||
-librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_all_dots
|
||||
-librpc.ndr.ndr_dns_nbt.test_ndr_nbt_string_half_dots
|
||||
--
|
||||
2.17.1
|
||||
|
||||
74
CVE-2020-10760-1.patch
Normal file
74
CVE-2020-10760-1.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From 4def2dc554754033174c60f5860f51b46d8502c1 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Fri, 5 Jun 2020 22:14:48 +1200
|
||||
Subject: [PATCH 21/22] CVE-2020-10760 dsdb: Ensure a proper talloc tree for
|
||||
saved controls
|
||||
|
||||
Otherwise a paged search on the GC port will fail as the ->data was
|
||||
not kept around for the second page of searches.
|
||||
|
||||
An example command to produce this is
|
||||
bin/ldbsearch --paged -H ldap://$SERVER:3268 -U$USERNAME%$PASSWORD
|
||||
|
||||
This shows up later in the partition module as:
|
||||
|
||||
ERROR: AddressSanitizer: heap-use-after-free on address 0x60b00151ef20 at pc 0x7fec3f801aac bp 0x7ffe8472c270 sp 0x7ffe8472c260
|
||||
READ of size 4 at 0x60b00151ef20 thread T0 (ldap(0))
|
||||
#0 0x7fec3f801aab in talloc_chunk_from_ptr ../../lib/talloc/talloc.c:526
|
||||
#1 0x7fec3f801aab in __talloc_get_name ../../lib/talloc/talloc.c:1559
|
||||
#2 0x7fec3f801aab in talloc_check_name ../../lib/talloc/talloc.c:1582
|
||||
#3 0x7fec1b86b2e1 in partition_search ../../source4/dsdb/samdb/ldb_modules/partition.c:780
|
||||
|
||||
or
|
||||
|
||||
smb_panic_default: PANIC (pid 13287): Bad talloc magic value - unknown value
|
||||
(from source4/dsdb/samdb/ldb_modules/partition.c:780)
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14402
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
source4/dsdb/samdb/ldb_modules/paged_results.c | 8 ++++++++
|
||||
source4/dsdb/samdb/ldb_modules/vlv_pagination.c | 7 +++++++
|
||||
2 files changed, 15 insertions(+)
|
||||
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
index 735883e8802..3eea3236e7d 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
@@ -523,6 +523,14 @@ paged_results_copy_down_controls(TALLOC_CTX *mem_ctx,
|
||||
continue;
|
||||
}
|
||||
new_controls[j] = talloc_steal(new_controls, control);
|
||||
+
|
||||
+ /*
|
||||
+ * Sadly the caller is not obliged to make this a
|
||||
+ * proper talloc tree, so we do so here.
|
||||
+ */
|
||||
+ if (control->data) {
|
||||
+ talloc_steal(control, control->data);
|
||||
+ }
|
||||
j++;
|
||||
}
|
||||
new_controls[j] = NULL;
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
index b103bda5f52..d6d6039e849 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/vlv_pagination.c
|
||||
@@ -746,6 +746,13 @@ vlv_copy_down_controls(TALLOC_CTX *mem_ctx, struct ldb_control **controls)
|
||||
continue;
|
||||
}
|
||||
new_controls[j] = talloc_steal(new_controls, control);
|
||||
+ /*
|
||||
+ * Sadly the caller is not obliged to make this a
|
||||
+ * proper talloc tree, so we do so here.
|
||||
+ */
|
||||
+ if (control->data) {
|
||||
+ talloc_steal(control, control->data);
|
||||
+ }
|
||||
j++;
|
||||
}
|
||||
new_controls[j] = NULL;
|
||||
--
|
||||
2.17.1
|
||||
|
||||
247
CVE-2020-10760-2.patch
Normal file
247
CVE-2020-10760-2.patch
Normal file
@ -0,0 +1,247 @@
|
||||
From df599b6b79010759279eb7f52486f1d0a59d06d3 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Mon, 8 Jun 2020 16:32:14 +1200
|
||||
Subject: [PATCH 22/22] CVE-2020-10760 dsdb: Add tests for paged_results and
|
||||
VLV over the Global Catalog port
|
||||
|
||||
This should avoid a regression.
|
||||
|
||||
(backported from master patch)
|
||||
[abartlet@samba.org: sort=True parameter on test_paged_delete_during_search
|
||||
is not in 4.11]
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
selftest/knownfail.d/vlv | 2 +-
|
||||
source4/dsdb/tests/python/vlv.py | 171 +++++++++++++++++++------------
|
||||
2 files changed, 107 insertions(+), 66 deletions(-)
|
||||
|
||||
diff --git a/selftest/knownfail.d/vlv b/selftest/knownfail.d/vlv
|
||||
index f187a2ed55e..7ae02baf17b 100644
|
||||
--- a/selftest/knownfail.d/vlv
|
||||
+++ b/selftest/knownfail.d/vlv
|
||||
@@ -1,2 +1,2 @@
|
||||
samba4.ldap.vlv.python.*__main__.VLVTests.test_vlv_change_search_expr
|
||||
-samba4.ldap.vlv.python.*__main__.PagedResultsTests.test_paged_cant_change_controls_data
|
||||
+samba4.ldap.vlv.python.*__main__.PagedResultsTestsRW.test_paged_cant_change_controls_data
|
||||
diff --git a/source4/dsdb/tests/python/vlv.py b/source4/dsdb/tests/python/vlv.py
|
||||
index f3c603e3a39..ba03b425a5b 100644
|
||||
--- a/source4/dsdb/tests/python/vlv.py
|
||||
+++ b/source4/dsdb/tests/python/vlv.py
|
||||
@@ -152,7 +152,7 @@ class TestsWithUserOU(samba.tests.TestCase):
|
||||
super(TestsWithUserOU, self).setUp()
|
||||
self.ldb = SamDB(host, credentials=creds,
|
||||
session_info=system_session(lp), lp=lp)
|
||||
-
|
||||
+ self.ldb_ro = self.ldb
|
||||
self.base_dn = self.ldb.domain_dn()
|
||||
self.tree_dn = "ou=vlvtesttree,%s" % self.base_dn
|
||||
self.ou = "ou=vlvou,%s" % self.tree_dn
|
||||
@@ -199,8 +199,60 @@ class TestsWithUserOU(samba.tests.TestCase):
|
||||
self.ldb.delete(self.tree_dn, ['tree_delete:1'])
|
||||
|
||||
|
||||
-class VLVTests(TestsWithUserOU):
|
||||
+class VLVTestsBase(TestsWithUserOU):
|
||||
+
|
||||
+ # Run a vlv search and return important fields of the response control
|
||||
+ def vlv_search(self, attr, expr, cookie="", after_count=0, offset=1):
|
||||
+ sort_ctrl = "server_sort:1:0:%s" % attr
|
||||
+ ctrl = "vlv:1:0:%d:%d:0" % (after_count, offset)
|
||||
+ if cookie:
|
||||
+ ctrl += ":" + cookie
|
||||
+
|
||||
+ res = self.ldb_ro.search(self.ou,
|
||||
+ expression=expr,
|
||||
+ scope=ldb.SCOPE_ONELEVEL,
|
||||
+ attrs=[attr],
|
||||
+ controls=[ctrl, sort_ctrl])
|
||||
+ results = [str(x[attr][0]) for x in res]
|
||||
+
|
||||
+ ctrls = [str(c) for c in res.controls if
|
||||
+ str(c).startswith('vlv')]
|
||||
+ self.assertEqual(len(ctrls), 1)
|
||||
+
|
||||
+ spl = ctrls[0].rsplit(':')
|
||||
+ cookie = ""
|
||||
+ if len(spl) == 6:
|
||||
+ cookie = spl[-1]
|
||||
+
|
||||
+ return results, cookie
|
||||
+
|
||||
+
|
||||
+class VLVTestsRO(VLVTestsBase):
|
||||
+ def test_vlv_simple_double_run(self):
|
||||
+ """Do the simplest possible VLV query to confirm if VLV
|
||||
+ works at all. Useful for showing VLV as a whole works
|
||||
+ on Global Catalog (for example)"""
|
||||
+ attr = 'roomNumber'
|
||||
+ expr = "(objectclass=user)"
|
||||
|
||||
+ # Start new search
|
||||
+ full_results, cookie = self.vlv_search(attr, expr,
|
||||
+ after_count=len(self.users))
|
||||
+
|
||||
+ results, cookie = self.vlv_search(attr, expr, cookie=cookie,
|
||||
+ after_count=len(self.users))
|
||||
+ expected_results = full_results
|
||||
+ self.assertEqual(results, expected_results)
|
||||
+
|
||||
+
|
||||
+class VLVTestsGC(VLVTestsRO):
|
||||
+ def setUp(self):
|
||||
+ super(VLVTestsRO, self).setUp()
|
||||
+ self.ldb_ro = SamDB(host + ":3268", credentials=creds,
|
||||
+ session_info=system_session(lp), lp=lp)
|
||||
+
|
||||
+
|
||||
+class VLVTests(VLVTestsBase):
|
||||
def get_full_list(self, attr, include_cn=False):
|
||||
"""Fetch the whole list sorted on the attribute, using the VLV.
|
||||
This way you get a VLV cookie."""
|
||||
@@ -1081,31 +1133,6 @@ class VLVTests(TestsWithUserOU):
|
||||
controls=[sort_control,
|
||||
"vlv:0:1:1:1:0:%s" % vlv_cookies[-1]])
|
||||
|
||||
- # Run a vlv search and return important fields of the response control
|
||||
- def vlv_search(self, attr, expr, cookie="", after_count=0, offset=1):
|
||||
- sort_ctrl = "server_sort:1:0:%s" % attr
|
||||
- ctrl = "vlv:1:0:%d:%d:0" % (after_count, offset)
|
||||
- if cookie:
|
||||
- ctrl += ":" + cookie
|
||||
-
|
||||
- res = self.ldb.search(self.ou,
|
||||
- expression=expr,
|
||||
- scope=ldb.SCOPE_ONELEVEL,
|
||||
- attrs=[attr],
|
||||
- controls=[ctrl, sort_ctrl])
|
||||
- results = [str(x[attr][0]) for x in res]
|
||||
-
|
||||
- ctrls = [str(c) for c in res.controls if
|
||||
- str(c).startswith('vlv')]
|
||||
- self.assertEqual(len(ctrls), 1)
|
||||
-
|
||||
- spl = ctrls[0].rsplit(':')
|
||||
- cookie = ""
|
||||
- if len(spl) == 6:
|
||||
- cookie = spl[-1]
|
||||
-
|
||||
- return results, cookie
|
||||
-
|
||||
def test_vlv_modify_during_view(self):
|
||||
attr = 'roomNumber'
|
||||
expr = "(objectclass=user)"
|
||||
@@ -1218,11 +1245,11 @@ class PagedResultsTests(TestsWithUserOU):
|
||||
if subtree:
|
||||
scope = ldb.SCOPE_SUBTREE
|
||||
|
||||
- res = self.ldb.search(ou,
|
||||
- expression=expr,
|
||||
- scope=scope,
|
||||
- controls=controls,
|
||||
- **kwargs)
|
||||
+ res = self.ldb_ro.search(ou,
|
||||
+ expression=expr,
|
||||
+ scope=scope,
|
||||
+ controls=controls,
|
||||
+ **kwargs)
|
||||
results = [str(r['cn'][0]) for r in res]
|
||||
|
||||
ctrls = [str(c) for c in res.controls if
|
||||
@@ -1235,6 +1262,53 @@ class PagedResultsTests(TestsWithUserOU):
|
||||
cookie = spl[-1]
|
||||
return results, cookie
|
||||
|
||||
+
|
||||
+class PagedResultsTestsRO(PagedResultsTests):
|
||||
+
|
||||
+ def test_paged_search_lockstep(self):
|
||||
+ expr = "(objectClass=*)"
|
||||
+ ps = 3
|
||||
+
|
||||
+ all_results, _ = self.paged_search(expr, page_size=len(self.users)+1)
|
||||
+
|
||||
+ # Run two different but overlapping paged searches simultaneously.
|
||||
+ set_1_index = int((len(all_results))//3)
|
||||
+ set_2_index = int((2*len(all_results))//3)
|
||||
+ set_1 = all_results[set_1_index:]
|
||||
+ set_2 = all_results[:set_2_index+1]
|
||||
+ set_1_expr = "(cn>=%s)" % (all_results[set_1_index])
|
||||
+ set_2_expr = "(cn<=%s)" % (all_results[set_2_index])
|
||||
+
|
||||
+ results, cookie1 = self.paged_search(set_1_expr, page_size=ps)
|
||||
+ self.assertEqual(results, set_1[:ps])
|
||||
+ results, cookie2 = self.paged_search(set_2_expr, page_size=ps)
|
||||
+ self.assertEqual(results, set_2[:ps])
|
||||
+
|
||||
+ results, cookie1 = self.paged_search(set_1_expr, cookie=cookie1,
|
||||
+ page_size=ps)
|
||||
+ self.assertEqual(results, set_1[ps:ps*2])
|
||||
+ results, cookie2 = self.paged_search(set_2_expr, cookie=cookie2,
|
||||
+ page_size=ps)
|
||||
+ self.assertEqual(results, set_2[ps:ps*2])
|
||||
+
|
||||
+ results, _ = self.paged_search(set_1_expr, cookie=cookie1,
|
||||
+ page_size=len(self.users))
|
||||
+ self.assertEqual(results, set_1[ps*2:])
|
||||
+ results, _ = self.paged_search(set_2_expr, cookie=cookie2,
|
||||
+ page_size=len(self.users))
|
||||
+ self.assertEqual(results, set_2[ps*2:])
|
||||
+
|
||||
+
|
||||
+class PagedResultsTestsGC(PagedResultsTestsRO):
|
||||
+
|
||||
+ def setUp(self):
|
||||
+ super(PagedResultsTestsRO, self).setUp()
|
||||
+ self.ldb_ro = SamDB(host + ":3268", credentials=creds,
|
||||
+ session_info=system_session(lp), lp=lp)
|
||||
+
|
||||
+
|
||||
+class PagedResultsTestsRW(PagedResultsTests):
|
||||
+
|
||||
def test_paged_delete_during_search(self):
|
||||
expr = "(objectClass=*)"
|
||||
|
||||
@@ -1611,39 +1685,6 @@ class PagedResultsTests(TestsWithUserOU):
|
||||
cookie, attrs=changed_attrs,
|
||||
extra_ctrls=[])
|
||||
|
||||
- def test_paged_search_lockstep(self):
|
||||
- expr = "(objectClass=*)"
|
||||
- ps = 3
|
||||
-
|
||||
- all_results, _ = self.paged_search(expr, page_size=len(self.users)+1)
|
||||
-
|
||||
- # Run two different but overlapping paged searches simultaneously.
|
||||
- set_1_index = int((len(all_results))//3)
|
||||
- set_2_index = int((2*len(all_results))//3)
|
||||
- set_1 = all_results[set_1_index:]
|
||||
- set_2 = all_results[:set_2_index+1]
|
||||
- set_1_expr = "(cn>=%s)" % (all_results[set_1_index])
|
||||
- set_2_expr = "(cn<=%s)" % (all_results[set_2_index])
|
||||
-
|
||||
- results, cookie1 = self.paged_search(set_1_expr, page_size=ps)
|
||||
- self.assertEqual(results, set_1[:ps])
|
||||
- results, cookie2 = self.paged_search(set_2_expr, page_size=ps)
|
||||
- self.assertEqual(results, set_2[:ps])
|
||||
-
|
||||
- results, cookie1 = self.paged_search(set_1_expr, cookie=cookie1,
|
||||
- page_size=ps)
|
||||
- self.assertEqual(results, set_1[ps:ps*2])
|
||||
- results, cookie2 = self.paged_search(set_2_expr, cookie=cookie2,
|
||||
- page_size=ps)
|
||||
- self.assertEqual(results, set_2[ps:ps*2])
|
||||
-
|
||||
- results, _ = self.paged_search(set_1_expr, cookie=cookie1,
|
||||
- page_size=len(self.users))
|
||||
- self.assertEqual(results, set_1[ps*2:])
|
||||
- results, _ = self.paged_search(set_2_expr, cookie=cookie2,
|
||||
- page_size=len(self.users))
|
||||
- self.assertEqual(results, set_2[ps*2:])
|
||||
-
|
||||
def test_vlv_paged(self):
|
||||
"""Testing behaviour with VLV and paged_results set.
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
65
CVE-2020-14303-1.patch
Normal file
65
CVE-2020-14303-1.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From 11034ea33fca9b8a1c2e14480e70069b55fca6a2 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Thu, 25 Jun 2020 11:59:54 +1200
|
||||
Subject: [PATCH 19/22] CVE-2020-14303 Ensure an empty packet will not DoS the
|
||||
NBT server
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
python/samba/tests/dns_packet.py | 19 +++++++++++++++++++
|
||||
selftest/knownfail.d/empty-nbt | 1 +
|
||||
2 files changed, 20 insertions(+)
|
||||
create mode 100644 selftest/knownfail.d/empty-nbt
|
||||
|
||||
diff --git a/python/samba/tests/dns_packet.py b/python/samba/tests/dns_packet.py
|
||||
index c4f843eb613..ae7bcb3ad8c 100644
|
||||
--- a/python/samba/tests/dns_packet.py
|
||||
+++ b/python/samba/tests/dns_packet.py
|
||||
@@ -156,6 +156,19 @@ class TestDnsPacketBase(TestCase):
|
||||
rcode = self.decode_reply(data)['rcode']
|
||||
return expected_rcode == rcode
|
||||
|
||||
+ def _test_empty_packet(self):
|
||||
+
|
||||
+ packet = b""
|
||||
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
+ s.sendto(packet, self.server)
|
||||
+ s.close()
|
||||
+
|
||||
+ # It is reasonable not to reply to an empty packet
|
||||
+ # but it is not reasonable to render the server
|
||||
+ # unresponsive.
|
||||
+ ok = self._known_good_query()
|
||||
+ self.assertTrue(ok, f"the server is unresponsive")
|
||||
+
|
||||
|
||||
class TestDnsPackets(TestDnsPacketBase):
|
||||
server = (SERVER, 53)
|
||||
@@ -174,6 +187,9 @@ class TestDnsPackets(TestDnsPacketBase):
|
||||
label = b'x.' * 31 + b'x'
|
||||
self._test_many_repeated_components(label, 127)
|
||||
|
||||
+ def test_empty_packet(self):
|
||||
+ self._test_empty_packet()
|
||||
+
|
||||
|
||||
class TestNbtPackets(TestDnsPacketBase):
|
||||
server = (SERVER, 137)
|
||||
@@ -209,3 +225,6 @@ class TestNbtPackets(TestDnsPacketBase):
|
||||
def test_127_half_dotty_components(self):
|
||||
label = b'x.' * 31 + b'x'
|
||||
self._test_many_repeated_components(label, 127)
|
||||
+
|
||||
+ def test_empty_packet(self):
|
||||
+ self._test_empty_packet()
|
||||
diff --git a/selftest/knownfail.d/empty-nbt b/selftest/knownfail.d/empty-nbt
|
||||
new file mode 100644
|
||||
index 00000000000..e4bcccab4e5
|
||||
--- /dev/null
|
||||
+++ b/selftest/knownfail.d/empty-nbt
|
||||
@@ -0,0 +1 @@
|
||||
+^samba.tests.dns_packet.samba.tests.dns_packet.TestNbtPackets.test_empty_packet
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.17.1
|
||||
|
||||
58
CVE-2020-14303-2.patch
Normal file
58
CVE-2020-14303-2.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 153c8db09b26455aa9802ff95943dd8a75f31893 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 24 Jun 2020 14:27:08 +1200
|
||||
Subject: [PATCH 20/22] CVE-2020-14303: s4 nbt: fix busy loop on empty UDP
|
||||
packet
|
||||
|
||||
An empty UDP packet put the nbt server into a busy loop that consumes
|
||||
100% of a cpu.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14417
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
libcli/nbt/nbtsocket.c | 17 ++++++++++++++++-
|
||||
selftest/knownfail.d/empty-nbt | 1 -
|
||||
2 files changed, 16 insertions(+), 2 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/empty-nbt
|
||||
|
||||
diff --git a/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c
|
||||
index 33d53fba993..8aecaf73247 100644
|
||||
--- a/libcli/nbt/nbtsocket.c
|
||||
+++ b/libcli/nbt/nbtsocket.c
|
||||
@@ -167,8 +167,23 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
|
||||
return;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Given a zero length, data_blob_talloc() returns the
|
||||
+ * NULL blob {NULL, 0}.
|
||||
+ *
|
||||
+ * We only want to error return here on a real out of memory condition
|
||||
+ * (i.e. dsize != 0, so the UDP packet has data, but the return of the
|
||||
+ * allocation failed, so blob.data==NULL).
|
||||
+ *
|
||||
+ * Given an actual zero length UDP packet having blob.data == NULL
|
||||
+ * isn't an out of memory error condition, that's the defined semantics
|
||||
+ * of data_blob_talloc() when asked for zero bytes.
|
||||
+ *
|
||||
+ * We still need to continue to do the zero-length socket_recvfrom()
|
||||
+ * read in order to clear the "read pending" condition on the socket.
|
||||
+ */
|
||||
blob = data_blob_talloc(tmp_ctx, NULL, dsize);
|
||||
- if (blob.data == NULL) {
|
||||
+ if (blob.data == NULL && dsize != 0) {
|
||||
talloc_free(tmp_ctx);
|
||||
return;
|
||||
}
|
||||
diff --git a/selftest/knownfail.d/empty-nbt b/selftest/knownfail.d/empty-nbt
|
||||
deleted file mode 100644
|
||||
index e4bcccab4e5..00000000000
|
||||
--- a/selftest/knownfail.d/empty-nbt
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-^samba.tests.dns_packet.samba.tests.dns_packet.TestNbtPackets.test_empty_packet
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.17.1
|
||||
|
||||
62
samba.spec
62
samba.spec
@ -49,7 +49,7 @@
|
||||
|
||||
Name: samba
|
||||
Version: 4.11.6
|
||||
Release: 7
|
||||
Release: 8
|
||||
|
||||
Summary: A suite for Linux to interoperate with Windows
|
||||
License: GPLv3+ and LGPLv3+
|
||||
@ -66,17 +66,38 @@ Source7: samba.pamd
|
||||
|
||||
Source201: README.downgrade
|
||||
|
||||
Patch100: 0000-use-gnutls-for-des-cbc.patch
|
||||
Patch101: 0001-handle-removal-des-enctypes-from-krb5.patch
|
||||
Patch102: 0002-samba-tool-create-working-private-krb5.conf.patch
|
||||
Patch103: CVE-2020-10700-1.patch
|
||||
Patch104: CVE-2020-10700-3.patch
|
||||
Patch105: CVE-2020-10704-1.patch
|
||||
Patch106: CVE-2020-10704-3.patch
|
||||
Patch107: CVE-2020-10704-5.patch
|
||||
Patch108: CVE-2020-10704-6.patch
|
||||
Patch109: CVE-2020-10704-7.patch
|
||||
Patch110: CVE-2020-10704-8.patch
|
||||
Patch0: 0000-use-gnutls-for-des-cbc.patch
|
||||
Patch1: 0001-handle-removal-des-enctypes-from-krb5.patch
|
||||
Patch2: 0002-samba-tool-create-working-private-krb5.conf.patch
|
||||
Patch3: CVE-2020-10700-1.patch
|
||||
Patch4: CVE-2020-10700-3.patch
|
||||
Patch5: CVE-2020-10704-1.patch
|
||||
Patch6: CVE-2020-10704-3.patch
|
||||
Patch7: CVE-2020-10704-5.patch
|
||||
Patch8: CVE-2020-10704-6.patch
|
||||
Patch9: CVE-2020-10704-7.patch
|
||||
Patch10: CVE-2020-10704-8.patch
|
||||
Patch11: CVE-2020-10730-1.patch
|
||||
Patch12: CVE-2020-10730-2.patch
|
||||
Patch13: CVE-2020-10730-3.patch
|
||||
Patch14: CVE-2020-10730-4.patch
|
||||
Patch15: CVE-2020-10730-5.patch
|
||||
Patch16: CVE-2020-10730-6.patch
|
||||
Patch17: CVE-2020-10730-7.patch
|
||||
Patch18: CVE-2020-10730-8.patch
|
||||
Patch19: CVE-2020-10730-9.patch
|
||||
Patch20: CVE-2020-10730-10.patch
|
||||
Patch21: CVE-2020-10745-1.patch
|
||||
Patch22: CVE-2020-10745-2.patch
|
||||
Patch23: CVE-2020-10745-3.patch
|
||||
Patch24: CVE-2020-10745-4.patch
|
||||
Patch25: CVE-2020-10745-5.patch
|
||||
Patch26: CVE-2020-10745-6.patch
|
||||
Patch27: CVE-2020-10745-7.patch
|
||||
Patch28: CVE-2020-14303-1.patch
|
||||
Patch29: CVE-2020-14303-2.patch
|
||||
Patch30: CVE-2020-10760-1.patch
|
||||
Patch31: CVE-2020-10760-2.patch
|
||||
|
||||
BuildRequires: avahi-devel cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel 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
|
||||
@ -1001,15 +1022,6 @@ fi
|
||||
%config %{_sysconfdir}/openldap/schema/samba.schema
|
||||
%config(noreplace) %{_sysconfdir}/pam.d/samba
|
||||
|
||||
%if ! %{with_vfs_glusterfs}
|
||||
%exclude %{_mandir}/man8/vfs_glusterfs.8*
|
||||
%endif
|
||||
|
||||
%if ! %{with_vfs_cephfs}
|
||||
%exclude %{_mandir}/man8/vfs_ceph.8*
|
||||
%exclude %{_mandir}/man8/vfs_ceph_snapshots.8*
|
||||
%endif
|
||||
|
||||
%attr(775,root,printadmin) %dir /var/lib/samba/drivers
|
||||
|
||||
%files libs
|
||||
@ -1902,6 +1914,8 @@ fi
|
||||
%{python3_sitearch}/samba/tests/__pycache__/upgradeprovisionneeddc.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/usage.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/xattr.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/dns_packet.*.pyc
|
||||
%{python3_sitearch}/samba/tests/dns_packet.py
|
||||
%{python3_sitearch}/samba/tests/audit_log_base.py
|
||||
%{python3_sitearch}/samba/tests/audit_log_dsdb.py
|
||||
%{python3_sitearch}/samba/tests/audit_log_pass_change.py
|
||||
@ -3062,6 +3076,12 @@ fi
|
||||
%{_mandir}/man*
|
||||
|
||||
%changelog
|
||||
* Wed Aug 05 2020 yuboyun <yuboyun@huawei.com> - 4.11.6-8
|
||||
- Type:cves
|
||||
- ID:CVE-2020-10730 CVE-2020-10745 CVE-2020-14303 CVE-2020-10760
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2020-10730CVE-2020-10745CVE-2020-14303CVE-2020-10760
|
||||
|
||||
* Fri May 29 2020 songzifeng <songzifeng1@huawei.com> - 4.11.6-7
|
||||
- fix the conflict of man and help
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user