!19 【LTS升级】update samba to 4.11.12
Merge pull request !19 from yu_boyun/openEuler-20.03-LTS
This commit is contained in:
commit
afc685fe74
@ -1,222 +0,0 @@
|
||||
From 0e77fa7747d789bd8c9256373498a352251f6877 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Mon, 30 Mar 2020 09:44:20 +0000
|
||||
Subject: [PATCH 1/4] CVE-2020-10700: dsdb: Add test for ASQ and ASQ in
|
||||
combination with paged_results
|
||||
|
||||
Thanks to Andrei Popa <andrei.popa@next-gen.ro> for finding,
|
||||
reporting and working with us to diagnose this issue!
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14331
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
selftest/knownfail.d/asq | 1 +
|
||||
source4/dsdb/tests/python/asq.py | 171 +++++++++++++++++++++++++++++++
|
||||
source4/selftest/tests.py | 1 +
|
||||
3 files changed, 173 insertions(+)
|
||||
create mode 100644 selftest/knownfail.d/asq
|
||||
create mode 100644 source4/dsdb/tests/python/asq.py
|
||||
|
||||
diff --git a/selftest/knownfail.d/asq b/selftest/knownfail.d/asq
|
||||
new file mode 100644
|
||||
index 00000000000..eb0e3e0aba1
|
||||
--- /dev/null
|
||||
+++ b/selftest/knownfail.d/asq
|
||||
@@ -0,0 +1 @@
|
||||
+samba4.asq.python\(ad_dc_default\).__main__.ASQLDAPTest.test_asq_paged
|
||||
\ No newline at end of file
|
||||
diff --git a/source4/dsdb/tests/python/asq.py b/source4/dsdb/tests/python/asq.py
|
||||
new file mode 100644
|
||||
index 00000000000..a32c9f40cd3
|
||||
--- /dev/null
|
||||
+++ b/source4/dsdb/tests/python/asq.py
|
||||
@@ -0,0 +1,171 @@
|
||||
+#!/usr/bin/env python3
|
||||
+#
|
||||
+# Test ASQ LDAP control behaviour in Samba
|
||||
+# Copyright (C) Andrew Bartlett 2019-2020
|
||||
+#
|
||||
+# Based on Unit tests for the notification control
|
||||
+# Copyright (C) Stefan Metzmacher 2016
|
||||
+#
|
||||
+# 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/>.
|
||||
+
|
||||
+import optparse
|
||||
+import sys
|
||||
+import os
|
||||
+import random
|
||||
+
|
||||
+sys.path.insert(0, "bin/python")
|
||||
+import samba
|
||||
+from samba.tests.subunitrun import SubunitOptions, TestProgram
|
||||
+
|
||||
+import samba.getopt as options
|
||||
+
|
||||
+from samba.auth import system_session
|
||||
+from samba import ldb
|
||||
+from samba.samdb import SamDB
|
||||
+from samba.ndr import ndr_unpack
|
||||
+from samba import gensec
|
||||
+from samba.credentials import Credentials
|
||||
+import samba.tests
|
||||
+
|
||||
+from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
|
||||
+from ldb import ERR_TIME_LIMIT_EXCEEDED, ERR_ADMIN_LIMIT_EXCEEDED, ERR_UNWILLING_TO_PERFORM
|
||||
+from ldb import Message
|
||||
+
|
||||
+parser = optparse.OptionParser("large_ldap.py [options] <host>")
|
||||
+sambaopts = options.SambaOptions(parser)
|
||||
+parser.add_option_group(sambaopts)
|
||||
+parser.add_option_group(options.VersionOptions(parser))
|
||||
+# use command line creds if available
|
||||
+credopts = options.CredentialsOptions(parser)
|
||||
+parser.add_option_group(credopts)
|
||||
+subunitopts = SubunitOptions(parser)
|
||||
+parser.add_option_group(subunitopts)
|
||||
+opts, args = parser.parse_args()
|
||||
+
|
||||
+if len(args) < 1:
|
||||
+ parser.print_usage()
|
||||
+ sys.exit(1)
|
||||
+
|
||||
+url = args[0]
|
||||
+
|
||||
+lp = sambaopts.get_loadparm()
|
||||
+creds = credopts.get_credentials(lp)
|
||||
+
|
||||
+
|
||||
+class ASQLDAPTest(samba.tests.TestCase):
|
||||
+
|
||||
+ def setUp(self):
|
||||
+ super(ASQLDAPTest, self).setUp()
|
||||
+ self.ldb = samba.Ldb(url, credentials=creds, session_info=system_session(lp), lp=lp)
|
||||
+ self.base_dn = self.ldb.get_default_basedn()
|
||||
+ self.NAME_ASQ="asq_" + format(random.randint(0, 99999), "05")
|
||||
+ self.OU_NAME_ASQ= self.NAME_ASQ + "_ou"
|
||||
+ self.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME_ASQ + "," + str(self.base_dn))
|
||||
+
|
||||
+ samba.tests.delete_force(self.ldb, self.ou_dn,
|
||||
+ controls=['tree_delete:1'])
|
||||
+
|
||||
+ self.ldb.add({
|
||||
+ "dn": self.ou_dn,
|
||||
+ "objectclass": "organizationalUnit",
|
||||
+ "ou": self.OU_NAME_ASQ})
|
||||
+
|
||||
+ self.members = []
|
||||
+ self.members2 = []
|
||||
+
|
||||
+ for x in range(20):
|
||||
+ name = self.NAME_ASQ + "_" + str(x)
|
||||
+ dn = ldb.Dn(self.ldb,
|
||||
+ "cn=" + name + "," + str(self.ou_dn))
|
||||
+ self.members.append(dn)
|
||||
+ self.ldb.add({
|
||||
+ "dn": dn,
|
||||
+ "objectclass": "group"})
|
||||
+
|
||||
+ for x in range(20):
|
||||
+ name = self.NAME_ASQ + "_" + str(x + 20)
|
||||
+ dn = ldb.Dn(self.ldb,
|
||||
+ "cn=" + name + "," + str(self.ou_dn))
|
||||
+ self.members2.append(dn)
|
||||
+ self.ldb.add({
|
||||
+ "dn": dn,
|
||||
+ "objectclass": "group",
|
||||
+ "member": [str(x) for x in self.members]})
|
||||
+
|
||||
+ name = self.NAME_ASQ + "_" + str(x + 40)
|
||||
+ self.top_dn = ldb.Dn(self.ldb,
|
||||
+ "cn=" + name + "," + str(self.ou_dn))
|
||||
+ self.ldb.add({
|
||||
+ "dn": self.top_dn,
|
||||
+ "objectclass": "group",
|
||||
+ "member": [str(x) for x in self.members2]})
|
||||
+
|
||||
+ def tearDown(self):
|
||||
+ samba.tests.delete_force(self.ldb, self.ou_dn,
|
||||
+ controls=['tree_delete:1'])
|
||||
+
|
||||
+ def test_asq(self):
|
||||
+ """Testing ASQ behaviour.
|
||||
+
|
||||
+ 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!
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ msgs = self.ldb.search(base=self.top_dn,
|
||||
+ scope=ldb.SCOPE_BASE,
|
||||
+ attrs=["objectGUID", "cn", "member"],
|
||||
+ controls=["asq:1:member"])
|
||||
+
|
||||
+ 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)
|
||||
+
|
||||
+ def test_asq_paged(self):
|
||||
+ """Testing ASQ behaviour with 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!
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ msgs = self.ldb.search(base=self.top_dn,
|
||||
+ scope=ldb.SCOPE_BASE,
|
||||
+ attrs=["objectGUID", "cn", "member"],
|
||||
+ controls=["asq:1:member",
|
||||
+ "paged_results:1:1024"])
|
||||
+
|
||||
+ 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
|
||||
+ else:
|
||||
+ url = "ldap://%s" % url
|
||||
+
|
||||
+TestProgram(module=__name__, opts=subunitopts)
|
||||
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
|
||||
index ae2b10ae659..52db18a872b 100755
|
||||
--- a/source4/selftest/tests.py
|
||||
+++ b/source4/selftest/tests.py
|
||||
@@ -885,6 +885,7 @@ plantestsuite_loadlist("samba4.tokengroups.krb5.python(ad_dc_default)", "ad_dc_d
|
||||
plantestsuite_loadlist("samba4.tokengroups.ntlm.python(ad_dc_default)", "ad_dc_default:local", [python, os.path.join(DSDB_PYTEST_DIR, "token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '-k', 'no', '$LOADLIST', '$LISTOPT'])
|
||||
plantestsuite("samba4.sam.python(fl2008r2dc)", "fl2008r2dc", [python, os.path.join(DSDB_PYTEST_DIR, "sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
|
||||
plantestsuite("samba4.sam.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
|
||||
+plantestsuite("samba4.asq.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "asq.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
|
||||
plantestsuite("samba4.user_account_control.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "user_account_control.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
|
||||
|
||||
for env in ['ad_dc_default:local', 'schema_dc:local']:
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
From 34f9e6e969913629f9241522020c5895dc9636dc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Bartlett <abartlet@samba.org>
|
||||
Date: Wed, 11 Mar 2020 16:43:31 +1300
|
||||
Subject: [PATCH 3/4] CVE-2020-10700: dsdb: Do not permit the ASQ control for
|
||||
the GUID search in paged_results
|
||||
|
||||
ASQ is a very strange control and a BASE search can return multiple results
|
||||
that are NOT the requested DN, but the DNs pointed to by it!
|
||||
|
||||
Thanks to Andrei Popa <andrei.popa@next-gen.ro> for finding,
|
||||
reporting and working with us to diagnose this issue!
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14331
|
||||
|
||||
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
||||
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
---
|
||||
selftest/knownfail.d/asq | 1 -
|
||||
source4/dsdb/samdb/ldb_modules/paged_results.c | 18 +++++++++++++-----
|
||||
2 files changed, 13 insertions(+), 6 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/asq
|
||||
|
||||
diff --git a/selftest/knownfail.d/asq b/selftest/knownfail.d/asq
|
||||
deleted file mode 100644
|
||||
index eb0e3e0aba1..00000000000
|
||||
--- a/selftest/knownfail.d/asq
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-samba4.asq.python\(ad_dc_default\).__main__.ASQLDAPTest.test_asq_paged
|
||||
\ No newline at end of file
|
||||
diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
index 940d2254fb0..dc211dd18ce 100644
|
||||
--- a/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
+++ b/source4/dsdb/samdb/ldb_modules/paged_results.c
|
||||
@@ -483,8 +483,14 @@ paged_results_copy_down_controls(TALLOC_CTX *mem_ctx,
|
||||
if (control->oid == NULL) {
|
||||
continue;
|
||||
}
|
||||
- if (strncmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID,
|
||||
- sizeof(LDB_CONTROL_PAGED_RESULTS_OID)) == 0) {
|
||||
+ if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_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);
|
||||
@@ -534,21 +540,23 @@ static bool paged_controls_same(struct ldb_request *req,
|
||||
|
||||
num_non_null_req_controls = 0;
|
||||
for (i=0; req->controls[i] != NULL; i++) {
|
||||
- if (req->controls[i]->oid != NULL) {
|
||||
+ if (req->controls[i]->oid != NULL &&
|
||||
+ strcmp(req->controls[i]->oid,
|
||||
+ LDB_CONTROL_ASQ_OID) != 0) {
|
||||
num_non_null_req_controls++;
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point we have the number of non-null entries for both
|
||||
* control lists and we know that:
|
||||
- * 1. down_controls does not contain the paged control
|
||||
+ * 1. down_controls does not contain the paged control or ASQ
|
||||
* (because paged_results_copy_down_controls excludes it)
|
||||
* 2. req->controls does contain the paged control
|
||||
* (because this function is only called if this is true)
|
||||
* 3. down_controls is a subset of non-null controls in req->controls
|
||||
* (checked above)
|
||||
* So to confirm that the two lists are identical except for the paged
|
||||
- * control, all we need to check is: */
|
||||
+ * control and possibly ASQ, all we need to check is: */
|
||||
if (num_non_null_req_controls == num_down_controls + 1) {
|
||||
return true;
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
||||
@ -1,547 +0,0 @@
|
||||
From b01952c6fb15b92fff3ad1bf8f1cf579875e5483 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Fri, 3 Apr 2020 12:18:03 +1300
|
||||
Subject: [PATCH 1/8] CVE-2020-10704: lib util asn1: Add ASN.1 max tree depth
|
||||
|
||||
Add maximum parse tree depth to the call to asn1_init, which will be
|
||||
used to limit the depth of the ASN.1 parse tree.
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
auth/gensec/gensec_util.c | 2 +-
|
||||
lib/util/asn1.c | 17 +++++++++-
|
||||
lib/util/asn1.h | 9 +++++-
|
||||
lib/util/tests/asn1_tests.c | 2 +-
|
||||
libcli/auth/spnego_parse.c | 6 ++--
|
||||
libcli/cldap/cldap.c | 2 +-
|
||||
libcli/ldap/ldap_message.c | 2 +-
|
||||
source3/lib/tldap.c | 4 +--
|
||||
source3/lib/tldap_util.c | 4 +--
|
||||
source3/libsmb/clispnego.c | 4 +--
|
||||
source3/torture/torture.c | 2 +-
|
||||
source4/auth/gensec/gensec_krb5.c | 4 +--
|
||||
source4/ldap_server/ldap_server.c | 2 +-
|
||||
source4/libcli/ldap/ldap_client.c | 2 +-
|
||||
source4/libcli/ldap/ldap_controls.c | 48 ++++++++++++++---------------
|
||||
15 files changed, 66 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
|
||||
index 20c9c2a1fbb..e185acc0c20 100644
|
||||
--- a/auth/gensec/gensec_util.c
|
||||
+++ b/auth/gensec/gensec_util.c
|
||||
@@ -76,7 +76,7 @@ NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
|
||||
static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
|
||||
{
|
||||
bool ret = false;
|
||||
- struct asn1_data *data = asn1_init(NULL);
|
||||
+ struct asn1_data *data = asn1_init(NULL, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
|
||||
index 51da5424956..ec6e674ce20 100644
|
||||
--- a/lib/util/asn1.c
|
||||
+++ b/lib/util/asn1.c
|
||||
@@ -36,15 +36,19 @@ struct asn1_data {
|
||||
off_t ofs;
|
||||
struct nesting *nesting;
|
||||
bool has_error;
|
||||
+ unsigned depth;
|
||||
+ unsigned max_depth;
|
||||
};
|
||||
|
||||
/* allocate an asn1 structure */
|
||||
-struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
|
||||
+struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx, unsigned max_depth)
|
||||
{
|
||||
struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
|
||||
if (ret == NULL) {
|
||||
DEBUG(0,("asn1_init failed! out of memory\n"));
|
||||
+ return ret;
|
||||
}
|
||||
+ ret->max_depth = max_depth;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -480,6 +484,11 @@ bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
|
||||
/* load a struct asn1_data structure with a lump of data, ready to be parsed */
|
||||
bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
|
||||
{
|
||||
+ /*
|
||||
+ * Save the maximum depth
|
||||
+ */
|
||||
+ unsigned max_depth = data->max_depth;
|
||||
+
|
||||
ZERO_STRUCTP(data);
|
||||
data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
|
||||
if (!data->data) {
|
||||
@@ -487,6 +496,7 @@ bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
|
||||
return false;
|
||||
}
|
||||
data->length = blob.length;
|
||||
+ data->max_depth = max_depth;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1103,9 +1113,14 @@ bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
*/
|
||||
void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
|
||||
{
|
||||
+ /*
|
||||
+ * Save max_depth
|
||||
+ */
|
||||
+ unsigned max_depth = data->max_depth;
|
||||
ZERO_STRUCTP(data);
|
||||
data->data = buf;
|
||||
data->length = len;
|
||||
+ data->max_depth = max_depth;
|
||||
}
|
||||
|
||||
int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
|
||||
diff --git a/lib/util/asn1.h b/lib/util/asn1.h
|
||||
index ddd69863574..fc365724e93 100644
|
||||
--- a/lib/util/asn1.h
|
||||
+++ b/lib/util/asn1.h
|
||||
@@ -45,7 +45,14 @@ typedef struct asn1_data ASN1_DATA;
|
||||
|
||||
#define ASN1_MAX_OIDS 20
|
||||
|
||||
-struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx);
|
||||
+/*
|
||||
+ * The maximum permitted depth for an ASN.1 parse tree, the limit is chosen
|
||||
+ * to align with the value for windows. Note that this value will trigger
|
||||
+ * ASAN stack overflow errors.
|
||||
+ */
|
||||
+#define ASN1_MAX_TREE_DEPTH 512
|
||||
+
|
||||
+struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx, unsigned max_depth);
|
||||
void asn1_free(struct asn1_data *data);
|
||||
bool asn1_has_error(const struct asn1_data *data);
|
||||
void asn1_set_error(struct asn1_data *data);
|
||||
diff --git a/lib/util/tests/asn1_tests.c b/lib/util/tests/asn1_tests.c
|
||||
index e4b386ad785..ab5262c4ffb 100644
|
||||
--- a/lib/util/tests/asn1_tests.c
|
||||
+++ b/lib/util/tests/asn1_tests.c
|
||||
@@ -330,7 +330,7 @@ static bool test_asn1_Integer(struct torture_context *tctx)
|
||||
DATA_BLOB blob;
|
||||
int val;
|
||||
|
||||
- data = asn1_init(mem_ctx);
|
||||
+ data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
if (!data) {
|
||||
goto err;
|
||||
}
|
||||
diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c
|
||||
index f538b44552c..f7f19b10778 100644
|
||||
--- a/libcli/auth/spnego_parse.c
|
||||
+++ b/libcli/auth/spnego_parse.c
|
||||
@@ -296,7 +296,7 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
|
||||
return ret;
|
||||
}
|
||||
|
||||
- asn1 = asn1_init(mem_ctx);
|
||||
+ asn1 = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
if (asn1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -339,7 +339,7 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
|
||||
|
||||
ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_data *spnego)
|
||||
{
|
||||
- struct asn1_data *asn1 = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *asn1 = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (asn1 == NULL) {
|
||||
@@ -411,7 +411,7 @@ bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB *blob)
|
||||
{
|
||||
bool ret = false;
|
||||
- struct asn1_data *asn1 = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *asn1 = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (asn1 == NULL) {
|
||||
return false;
|
||||
diff --git a/libcli/cldap/cldap.c b/libcli/cldap/cldap.c
|
||||
index daba37a21d7..8fa9ce0b273 100644
|
||||
--- a/libcli/cldap/cldap.c
|
||||
+++ b/libcli/cldap/cldap.c
|
||||
@@ -229,7 +229,7 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c,
|
||||
goto error;
|
||||
}
|
||||
|
||||
- asn1 = asn1_init(in);
|
||||
+ asn1 = asn1_init(in, ASN1_MAX_TREE_DEPTH);
|
||||
if (!asn1) {
|
||||
goto nomem;
|
||||
}
|
||||
diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c
|
||||
index f21598374a1..ba82bddeab1 100644
|
||||
--- a/libcli/ldap/ldap_message.c
|
||||
+++ b/libcli/ldap/ldap_message.c
|
||||
@@ -390,7 +390,7 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
|
||||
const struct ldap_control_handler *control_handlers,
|
||||
DATA_BLOB *result, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
int i, j;
|
||||
|
||||
if (!data) return false;
|
||||
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
|
||||
index d6c6e8859a6..bf5fc05d785 100644
|
||||
--- a/source3/lib/tldap.c
|
||||
+++ b/source3/lib/tldap.c
|
||||
@@ -632,7 +632,7 @@ static void tldap_msg_received(struct tevent_req *subreq)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- data = asn1_init(talloc_tos());
|
||||
+ data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
|
||||
if (data == NULL) {
|
||||
status = TLDAP_NO_MEMORY;
|
||||
goto fail;
|
||||
@@ -763,7 +763,7 @@ static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
- state->out = asn1_init(state);
|
||||
+ state->out = asn1_init(state, ASN1_MAX_TREE_DEPTH);
|
||||
if (state->out == NULL) {
|
||||
goto err;
|
||||
}
|
||||
diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c
|
||||
index 1b86962a32e..168932a8a96 100644
|
||||
--- a/source3/lib/tldap_util.c
|
||||
+++ b/source3/lib/tldap_util.c
|
||||
@@ -644,7 +644,7 @@ static struct tevent_req *tldap_ship_paged_search(
|
||||
struct tldap_control *pgctrl;
|
||||
struct asn1_data *asn1 = NULL;
|
||||
|
||||
- asn1 = asn1_init(state);
|
||||
+ asn1 = asn1_init(state, ASN1_MAX_TREE_DEPTH);
|
||||
if (asn1 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -783,7 +783,7 @@ static void tldap_search_paged_done(struct tevent_req *subreq)
|
||||
|
||||
TALLOC_FREE(state->cookie.data);
|
||||
|
||||
- asn1 = asn1_init(talloc_tos());
|
||||
+ asn1 = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
|
||||
if (tevent_req_nomem(asn1, req)) {
|
||||
return;
|
||||
}
|
||||
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
|
||||
index 4a0fbcd73af..1608f6a9960 100644
|
||||
--- a/source3/libsmb/clispnego.c
|
||||
+++ b/source3/libsmb/clispnego.c
|
||||
@@ -50,7 +50,7 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
|
||||
*secblob = data_blob_null;
|
||||
}
|
||||
|
||||
- data = asn1_init(talloc_tos());
|
||||
+ data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
|
||||
if (data == NULL) {
|
||||
return false;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const ui
|
||||
ASN1_DATA *data;
|
||||
DATA_BLOB ret = data_blob_null;
|
||||
|
||||
- data = asn1_init(talloc_tos());
|
||||
+ data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
|
||||
if (data == NULL) {
|
||||
return data_blob_null;
|
||||
}
|
||||
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
|
||||
index a795e61125f..c4b0a7bc4f9 100644
|
||||
--- a/source3/torture/torture.c
|
||||
+++ b/source3/torture/torture.c
|
||||
@@ -11370,7 +11370,7 @@ tldap_build_extended_control(enum tldap_extended_val val)
|
||||
ZERO_STRUCT(empty_control);
|
||||
|
||||
if (val != EXTENDED_NONE) {
|
||||
- data = asn1_init(talloc_tos());
|
||||
+ data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
|
||||
index 0323da87d29..b735063656a 100644
|
||||
--- a/source4/auth/gensec/gensec_krb5.c
|
||||
+++ b/source4/auth/gensec/gensec_krb5.c
|
||||
@@ -444,7 +444,7 @@ static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLO
|
||||
struct asn1_data *data;
|
||||
DATA_BLOB ret = data_blob_null;
|
||||
|
||||
- data = asn1_init(mem_ctx);
|
||||
+ data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
if (!data || !ticket->data) {
|
||||
return ret;
|
||||
}
|
||||
@@ -478,7 +478,7 @@ static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLO
|
||||
static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, DATA_BLOB *ticket, uint8_t tok_id[2])
|
||||
{
|
||||
bool ret = false;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
int data_remaining;
|
||||
|
||||
if (!data) {
|
||||
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
|
||||
index 709b7bcacfa..6d329329909 100644
|
||||
--- a/source4/ldap_server/ldap_server.c
|
||||
+++ b/source4/ldap_server/ldap_server.c
|
||||
@@ -560,7 +560,7 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
||||
return;
|
||||
}
|
||||
|
||||
- asn1 = asn1_init(call);
|
||||
+ asn1 = asn1_init(call, ASN1_MAX_TREE_DEPTH);
|
||||
if (asn1 == NULL) {
|
||||
ldapsrv_terminate_connection(conn, "no memory");
|
||||
return;
|
||||
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
|
||||
index da84adc7769..2d75af6af6e 100644
|
||||
--- a/source4/libcli/ldap/ldap_client.c
|
||||
+++ b/source4/libcli/ldap/ldap_client.c
|
||||
@@ -284,7 +284,7 @@ static void ldap_connection_recv_done(struct tevent_req *subreq)
|
||||
return;
|
||||
}
|
||||
|
||||
- asn1 = asn1_init(conn);
|
||||
+ asn1 = asn1_init(conn, ASN1_MAX_TREE_DEPTH);
|
||||
if (asn1 == NULL) {
|
||||
TALLOC_FREE(msg);
|
||||
ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
|
||||
diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c
|
||||
index 716ca148308..df012a158e0 100644
|
||||
--- a/source4/libcli/ldap/ldap_controls.c
|
||||
+++ b/source4/libcli/ldap/ldap_controls.c
|
||||
@@ -32,7 +32,7 @@ static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB attr;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_sort_resp_control *lsrc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -79,7 +79,7 @@ static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB attr;
|
||||
DATA_BLOB rule;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_server_sort_control **lssc;
|
||||
int num;
|
||||
|
||||
@@ -166,7 +166,7 @@ static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
return true;
|
||||
}
|
||||
|
||||
- data = asn1_init(mem_ctx);
|
||||
+ data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
if (!data) return false;
|
||||
|
||||
if (!asn1_load(data, in)) {
|
||||
@@ -198,7 +198,7 @@ static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_sd_flags_control *lsdfc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -232,7 +232,7 @@ static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_search_options_control *lsoc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -267,7 +267,7 @@ static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB cookie;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_paged_control *lprc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -316,7 +316,7 @@ static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB cookie;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_dirsync_control *ldc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -372,7 +372,7 @@ static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB source_attribute;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_asq_control *lac;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -433,7 +433,7 @@ static bool decode_verify_name_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB name;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_verify_name_control *lvnc;
|
||||
int len;
|
||||
|
||||
@@ -485,7 +485,7 @@ static bool decode_verify_name_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
static bool encode_verify_name_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_verify_name_control *lvnc = talloc_get_type(in, struct ldb_verify_name_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
DATA_BLOB gc_utf16;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -528,7 +528,7 @@ static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB assertion_value, context_id;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_vlv_req_control *lvrc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -626,7 +626,7 @@ static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
DATA_BLOB context_id;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct ldb_vlv_resp_control *lvrc;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -682,7 +682,7 @@ static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -716,7 +716,7 @@ static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
int num;
|
||||
|
||||
if (!data) return false;
|
||||
@@ -782,7 +782,7 @@ static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
- data = asn1_init(mem_ctx);
|
||||
+ data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -810,7 +810,7 @@ static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -838,7 +838,7 @@ static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -866,7 +866,7 @@ static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *ou
|
||||
static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -901,7 +901,7 @@ static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out
|
||||
static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -936,7 +936,7 @@ static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -972,7 +972,7 @@ static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -1040,7 +1040,7 @@ static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -1083,7 +1083,7 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
{
|
||||
struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
|
||||
int i,j;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -1132,7 +1132,7 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
|
||||
static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
|
||||
{
|
||||
void **out = (void **)_out;
|
||||
- struct asn1_data *data = asn1_init(mem_ctx);
|
||||
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
|
||||
struct dsdb_openldap_dereference_result_control *control;
|
||||
struct dsdb_openldap_dereference_result **r = NULL;
|
||||
int i = 0;
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
Backport of:
|
||||
|
||||
From d3be674c3ffa3541e2ba757e2c6dfb32508db440 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 8 Apr 2020 15:30:52 +1200
|
||||
Subject: [PATCH 3/8] CVE-2020-10704: lib util asn1: Check parse tree depth
|
||||
|
||||
Check the current depth of the parse tree and reject the input if the
|
||||
depth exceeds that passed to asn1_init
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
lib/util/asn1.c | 13 +++++++++++++
|
||||
selftest/knownfail.d/ldap_message | 2 --
|
||||
2 files changed, 13 insertions(+), 2 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/ldap_message
|
||||
|
||||
--- a/lib/util/asn1.c
|
||||
+++ b/lib/util/asn1.c
|
||||
@@ -647,6 +647,16 @@ bool asn1_start_tag(struct asn1_data *da
|
||||
uint8_t b;
|
||||
struct nesting *nesting;
|
||||
|
||||
+ /*
|
||||
+ * Check the depth of the parse tree and prevent it from growing
|
||||
+ * too large.
|
||||
+ */
|
||||
+ data->depth++;
|
||||
+ if (data->depth > data->max_depth) {
|
||||
+ data->has_error = true;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (!asn1_read_uint8(data, &b))
|
||||
return false;
|
||||
|
||||
@@ -703,6 +713,9 @@ bool asn1_end_tag(struct asn1_data *data
|
||||
{
|
||||
struct nesting *nesting;
|
||||
|
||||
+ if (data->depth > 0) {
|
||||
+ data->depth--;
|
||||
+ }
|
||||
/* make sure we read it all */
|
||||
if (asn1_tag_remaining(data) != 0) {
|
||||
data->has_error = true;
|
||||
@ -1,96 +0,0 @@
|
||||
From 9944df6ef1e421331ea1ca773f7e5652262d5d1b Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Tue, 7 Apr 2020 09:09:01 +1200
|
||||
Subject: [PATCH 5/8] CVE-2020-10704: smb.conf: Add max ldap request sizes
|
||||
|
||||
Add two new smb.conf parameters to control the maximum permitted ldap
|
||||
request size.
|
||||
|
||||
Adds:
|
||||
ldap max anonymous request size default 250Kb
|
||||
ldap max authenticated request size default 16Mb
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
.../smbdotconf/ldap/ldapmaxanonrequest.xml | 18 ++++++++++++++++++
|
||||
.../smbdotconf/ldap/ldapmaxauthrequest.xml | 18 ++++++++++++++++++
|
||||
lib/param/loadparm.c | 5 +++++
|
||||
source3/param/loadparm.c | 3 +++
|
||||
4 files changed, 44 insertions(+)
|
||||
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml
|
||||
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml
|
||||
@@ -0,0 +1,18 @@
|
||||
+<samba:parameter name="ldap max anonymous request size"
|
||||
+ context="G"
|
||||
+ type="integer"
|
||||
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
||||
+<description>
|
||||
+ <para>
|
||||
+ This parameter specifies the maximum permitted size (in bytes)
|
||||
+ for an LDAP request received on an anonymous connection.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ If the request size exceeds this limit the request will be
|
||||
+ rejected.
|
||||
+ </para>
|
||||
+</description>
|
||||
+<value type="default">256000</value>
|
||||
+<value type="example">500000</value>
|
||||
+</samba:parameter>
|
||||
--- /dev/null
|
||||
+++ b/docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml
|
||||
@@ -0,0 +1,18 @@
|
||||
+<samba:parameter name="ldap max authenticated request size"
|
||||
+ context="G"
|
||||
+ type="integer"
|
||||
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
||||
+<description>
|
||||
+ <para>
|
||||
+ This parameter specifies the maximum permitted size (in bytes)
|
||||
+ for an LDAP request received on an authenticated connection.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ If the request size exceeds this limit the request will be
|
||||
+ rejected.
|
||||
+ </para>
|
||||
+</description>
|
||||
+<value type="default">16777216</value>
|
||||
+<value type="example">4194304</value>
|
||||
+</samba:parameter>
|
||||
--- a/lib/param/loadparm.c
|
||||
+++ b/lib/param/loadparm.c
|
||||
@@ -3027,6 +3027,11 @@ struct loadparm_context *loadparm_init(T
|
||||
|
||||
lpcfg_do_global_parameter(lp_ctx, "debug encryption", "no");
|
||||
|
||||
+ lpcfg_do_global_parameter(
|
||||
+ lp_ctx, "ldap max anonymous request size", "256000");
|
||||
+ lpcfg_do_global_parameter(
|
||||
+ lp_ctx, "ldap max authenticated request size", "16777216");
|
||||
+
|
||||
for (i = 0; parm_table[i].label; i++) {
|
||||
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
|
||||
lp_ctx->flags[i] |= FLAG_DEFAULT;
|
||||
--- a/source3/param/loadparm.c
|
||||
+++ b/source3/param/loadparm.c
|
||||
@@ -956,6 +956,9 @@ static void init_globals(struct loadparm
|
||||
Globals.prefork_backoff_increment = 10;
|
||||
Globals.prefork_maximum_backoff = 120;
|
||||
|
||||
+ Globals.ldap_max_anonymous_request_size = 256000;
|
||||
+ Globals.ldap_max_authenticated_request_size = 16777216;
|
||||
+
|
||||
/* Now put back the settings that were set with lp_set_cmdline() */
|
||||
apply_lp_set_cmdline();
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
Backport of:
|
||||
|
||||
From 85619363d3280346b2253fe44bf67d4881a53ebd Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 8 Apr 2020 15:32:22 +1200
|
||||
Subject: [PATCH 6/8] CVE-2020-10704: S4 ldap server: Limit request sizes
|
||||
|
||||
Check the size of authenticated and anonymous ldap requests and reject
|
||||
them if they exceed the limits in smb.conf
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
selftest/knownfail.d/ldap_raw | 1 -
|
||||
source4/ldap_server/ldap_server.c | 96 ++++++++++++++++++++++++++++++-
|
||||
2 files changed, 95 insertions(+), 2 deletions(-)
|
||||
delete mode 100644 selftest/knownfail.d/ldap_raw
|
||||
|
||||
--- a/source4/ldap_server/ldap_server.c
|
||||
+++ b/source4/ldap_server/ldap_server.c
|
||||
@@ -441,6 +441,10 @@ static void ldapsrv_accept_tls_done(stru
|
||||
}
|
||||
|
||||
static void ldapsrv_call_read_done(struct tevent_req *subreq);
|
||||
+static NTSTATUS ldapsrv_packet_check(
|
||||
+ void *private_data,
|
||||
+ DATA_BLOB blob,
|
||||
+ size_t *packet_size);
|
||||
|
||||
static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
|
||||
{
|
||||
@@ -494,7 +498,7 @@ static bool ldapsrv_call_read_next(struc
|
||||
conn->connection->event.ctx,
|
||||
conn->sockets.active,
|
||||
7, /* initial_read_size */
|
||||
- ldap_full_packet,
|
||||
+ ldapsrv_packet_check,
|
||||
conn);
|
||||
if (subreq == NULL) {
|
||||
ldapsrv_terminate_connection(conn, "ldapsrv_call_read_next: "
|
||||
@@ -520,6 +524,9 @@ static bool ldapsrv_call_read_next(struc
|
||||
}
|
||||
|
||||
static void ldapsrv_call_process_done(struct tevent_req *subreq);
|
||||
+static int ldapsrv_check_packet_size(
|
||||
+ struct ldapsrv_connection *conn,
|
||||
+ size_t size);
|
||||
|
||||
static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
||||
{
|
||||
@@ -530,6 +537,7 @@ static void ldapsrv_call_read_done(struc
|
||||
struct ldapsrv_call *call;
|
||||
struct asn1_data *asn1;
|
||||
DATA_BLOB blob;
|
||||
+ int ret = LDAP_SUCCESS;
|
||||
|
||||
conn->sockets.read_req = NULL;
|
||||
|
||||
@@ -560,6 +568,14 @@ static void ldapsrv_call_read_done(struc
|
||||
return;
|
||||
}
|
||||
|
||||
+ ret = ldapsrv_check_packet_size(conn, blob.length);
|
||||
+ if (ret != LDAP_SUCCESS) {
|
||||
+ ldapsrv_terminate_connection(
|
||||
+ conn,
|
||||
+ "Request packet too large");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
asn1 = asn1_init(call, ASN1_MAX_TREE_DEPTH);
|
||||
if (asn1 == NULL) {
|
||||
ldapsrv_terminate_connection(conn, "no memory");
|
||||
@@ -1362,6 +1378,84 @@ static void ldapsrv_post_fork(struct tas
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Check the size of an ldap request packet.
|
||||
+ *
|
||||
+ * For authenticated connections the maximum packet size is controlled by
|
||||
+ * the smb.conf parameter "ldap max authenticated request size"
|
||||
+ *
|
||||
+ * For anonymous connections the maximum packet size is controlled by
|
||||
+ * the smb.conf parameter "ldap max anonymous request size"
|
||||
+ */
|
||||
+static int ldapsrv_check_packet_size(
|
||||
+ struct ldapsrv_connection *conn,
|
||||
+ size_t size)
|
||||
+{
|
||||
+ bool is_anonymous = false;
|
||||
+ size_t max_size = 0;
|
||||
+
|
||||
+ max_size = lpcfg_ldap_max_anonymous_request_size(conn->lp_ctx);
|
||||
+ if (size <= max_size) {
|
||||
+ return LDAP_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Request is larger than the maximum unauthenticated request size.
|
||||
+ * As this code is called frequently we avoid calling
|
||||
+ * security_token_is_anonymous if possible
|
||||
+ */
|
||||
+ if (conn->session_info != NULL &&
|
||||
+ conn->session_info->security_token != NULL) {
|
||||
+ is_anonymous = security_token_is_anonymous(
|
||||
+ conn->session_info->security_token);
|
||||
+ }
|
||||
+
|
||||
+ if (is_anonymous) {
|
||||
+ DBG_WARNING(
|
||||
+ "LDAP request size (%zu) exceeds (%zu)\n",
|
||||
+ size,
|
||||
+ max_size);
|
||||
+ return LDAP_UNWILLING_TO_PERFORM;
|
||||
+ }
|
||||
+
|
||||
+ max_size = lpcfg_ldap_max_authenticated_request_size(conn->lp_ctx);
|
||||
+ if (size > max_size) {
|
||||
+ DBG_WARNING(
|
||||
+ "LDAP request size (%zu) exceeds (%zu)\n",
|
||||
+ size,
|
||||
+ max_size);
|
||||
+ return LDAP_UNWILLING_TO_PERFORM;
|
||||
+ }
|
||||
+ return LDAP_SUCCESS;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Check that the blob contains enough data to be a valid packet
|
||||
+ * If there is a packet header check the size to ensure that it does not
|
||||
+ * exceed the maximum sizes.
|
||||
+ *
|
||||
+ */
|
||||
+static NTSTATUS ldapsrv_packet_check(
|
||||
+ void *private_data,
|
||||
+ DATA_BLOB blob,
|
||||
+ size_t *packet_size)
|
||||
+{
|
||||
+ NTSTATUS ret;
|
||||
+ struct ldapsrv_connection *conn = private_data;
|
||||
+ int result = LDB_SUCCESS;
|
||||
+
|
||||
+ ret = ldap_full_packet(private_data, blob, packet_size);
|
||||
+ if (!NT_STATUS_IS_OK(ret)) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ result = ldapsrv_check_packet_size(conn, *packet_size);
|
||||
+ if (result != LDAP_SUCCESS) {
|
||||
+ return NT_STATUS_LDAP(result);
|
||||
+ }
|
||||
+ return NT_STATUS_OK;
|
||||
+}
|
||||
+
|
||||
NTSTATUS server_service_ldap_init(TALLOC_CTX *ctx)
|
||||
{
|
||||
static const struct service_details details = {
|
||||
@ -1,211 +0,0 @@
|
||||
Backport of:
|
||||
|
||||
From 9be121c7055fde841be15f8d570ff49801b68bff Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 8 Apr 2020 08:49:23 +1200
|
||||
Subject: [PATCH 7/8] CVE-2020-10704: libcli ldap_message: Add search size
|
||||
limits to ldap_decode
|
||||
|
||||
Add search request size limits to ldap_decode calls.
|
||||
|
||||
The ldap server uses the smb.conf variable
|
||||
"ldap max search request size" which defaults to 250Kb.
|
||||
For cldap the limit is hard coded as 4096.
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
.../smbdotconf/ldap/ldapmaxsearchrequest.xml | 18 ++++++++++++++
|
||||
lib/param/loadparm.c | 2 ++
|
||||
libcli/cldap/cldap.c | 18 +++++++++++---
|
||||
libcli/ldap/ldap_message.c | 1 +
|
||||
libcli/ldap/ldap_message.h | 5 ++++
|
||||
libcli/ldap/tests/ldap_message_test.c | 24 +++++++++++++++----
|
||||
source3/param/loadparm.c | 1 +
|
||||
source4/ldap_server/ldap_server.c | 10 ++++++--
|
||||
source4/libcli/ldap/ldap_client.c | 3 ++-
|
||||
9 files changed, 72 insertions(+), 10 deletions(-)
|
||||
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml
|
||||
@@ -0,0 +1,18 @@
|
||||
+<samba:parameter name="ldap max search request size"
|
||||
+ context="G"
|
||||
+ type="integer"
|
||||
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
||||
+<description>
|
||||
+ <para>
|
||||
+ This parameter specifies the maximum permitted size (in bytes)
|
||||
+ for an LDAP search request.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ If the request size exceeds this limit the request will be
|
||||
+ rejected.
|
||||
+ </para>
|
||||
+</description>
|
||||
+<value type="default">256000</value>
|
||||
+<value type="example">4194304</value>
|
||||
+</samba:parameter>
|
||||
--- a/lib/param/loadparm.c
|
||||
+++ b/lib/param/loadparm.c
|
||||
@@ -3031,6 +3031,8 @@ struct loadparm_context *loadparm_init(T
|
||||
lp_ctx, "ldap max anonymous request size", "256000");
|
||||
lpcfg_do_global_parameter(
|
||||
lp_ctx, "ldap max authenticated request size", "16777216");
|
||||
+ lpcfg_do_global_parameter(
|
||||
+ lp_ctx, "ldap max search request size", "256000");
|
||||
|
||||
for (i = 0; parm_table[i].label; i++) {
|
||||
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
|
||||
--- a/libcli/cldap/cldap.c
|
||||
+++ b/libcli/cldap/cldap.c
|
||||
@@ -111,6 +111,11 @@ struct cldap_search_state {
|
||||
struct tevent_req *req;
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * For CLDAP we limit the maximum search request size to 4kb
|
||||
+ */
|
||||
+#define MAX_SEARCH_REQUEST 4096
|
||||
+
|
||||
static int cldap_socket_destructor(struct cldap_socket *c)
|
||||
{
|
||||
while (c->searches.list) {
|
||||
@@ -224,6 +229,9 @@ static bool cldap_socket_recv_dgram(stru
|
||||
void *p;
|
||||
struct cldap_search_state *search;
|
||||
NTSTATUS status;
|
||||
+ struct ldap_request_limits limits = {
|
||||
+ .max_search_size = MAX_SEARCH_REQUEST
|
||||
+ };
|
||||
|
||||
if (in->recv_errno != 0) {
|
||||
goto error;
|
||||
@@ -242,7 +250,7 @@ static bool cldap_socket_recv_dgram(stru
|
||||
}
|
||||
|
||||
/* this initial decode is used to find the message id */
|
||||
- status = ldap_decode(asn1, NULL, in->ldap_msg);
|
||||
+ status = ldap_decode(asn1, &limits, NULL, in->ldap_msg);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto nterror;
|
||||
}
|
||||
@@ -770,6 +778,9 @@ NTSTATUS cldap_search_recv(struct tevent
|
||||
struct cldap_search_state);
|
||||
struct ldap_message *ldap_msg;
|
||||
NTSTATUS status;
|
||||
+ struct ldap_request_limits limits = {
|
||||
+ .max_search_size = MAX_SEARCH_REQUEST
|
||||
+ };
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
goto failed;
|
||||
@@ -780,7 +791,7 @@ NTSTATUS cldap_search_recv(struct tevent
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
- status = ldap_decode(state->response.asn1, NULL, ldap_msg);
|
||||
+ status = ldap_decode(state->response.asn1, &limits, NULL, ldap_msg);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
@@ -796,7 +807,8 @@ NTSTATUS cldap_search_recv(struct tevent
|
||||
*io->out.response = ldap_msg->r.SearchResultEntry;
|
||||
|
||||
/* decode the 2nd part */
|
||||
- status = ldap_decode(state->response.asn1, NULL, ldap_msg);
|
||||
+ status = ldap_decode(
|
||||
+ state->response.asn1, &limits, NULL, ldap_msg);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
--- a/libcli/ldap/ldap_message.c
|
||||
+++ b/libcli/ldap/ldap_message.c
|
||||
@@ -1162,6 +1162,7 @@ static bool ldap_decode_attribs(TALLOC_C
|
||||
/* This routine returns LDAP status codes */
|
||||
|
||||
_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
|
||||
+ const struct ldap_request_limits *limits,
|
||||
const struct ldap_control_handler *control_handlers,
|
||||
struct ldap_message *msg)
|
||||
{
|
||||
--- a/libcli/ldap/ldap_message.h
|
||||
+++ b/libcli/ldap/ldap_message.h
|
||||
@@ -213,10 +213,15 @@ struct ldap_control_handler {
|
||||
bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
|
||||
};
|
||||
|
||||
+struct ldap_request_limits {
|
||||
+ unsigned max_search_size;
|
||||
+};
|
||||
+
|
||||
struct asn1_data;
|
||||
|
||||
struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx);
|
||||
NTSTATUS ldap_decode(struct asn1_data *data,
|
||||
+ const struct ldap_request_limits *limits,
|
||||
const struct ldap_control_handler *control_handlers,
|
||||
struct ldap_message *msg);
|
||||
bool ldap_encode(struct ldap_message *msg,
|
||||
--- a/source3/param/loadparm.c
|
||||
+++ b/source3/param/loadparm.c
|
||||
@@ -958,6 +958,7 @@ static void init_globals(struct loadparm
|
||||
|
||||
Globals.ldap_max_anonymous_request_size = 256000;
|
||||
Globals.ldap_max_authenticated_request_size = 16777216;
|
||||
+ Globals.ldap_max_search_request_size = 256000;
|
||||
|
||||
/* Now put back the settings that were set with lp_set_cmdline() */
|
||||
apply_lp_set_cmdline();
|
||||
--- a/source4/ldap_server/ldap_server.c
|
||||
+++ b/source4/ldap_server/ldap_server.c
|
||||
@@ -538,6 +538,7 @@ static void ldapsrv_call_read_done(struc
|
||||
struct asn1_data *asn1;
|
||||
DATA_BLOB blob;
|
||||
int ret = LDAP_SUCCESS;
|
||||
+ struct ldap_request_limits limits = {0};
|
||||
|
||||
conn->sockets.read_req = NULL;
|
||||
|
||||
@@ -593,8 +594,13 @@ static void ldapsrv_call_read_done(struc
|
||||
return;
|
||||
}
|
||||
|
||||
- status = ldap_decode(asn1, samba_ldap_control_handlers(),
|
||||
- call->request);
|
||||
+ limits.max_search_size =
|
||||
+ lpcfg_ldap_max_search_request_size(conn->lp_ctx);
|
||||
+ status = ldap_decode(
|
||||
+ asn1,
|
||||
+ &limits,
|
||||
+ samba_ldap_control_handlers(),
|
||||
+ call->request);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ldapsrv_terminate_connection(conn, nt_errstr(status));
|
||||
return;
|
||||
--- a/source4/libcli/ldap/ldap_client.c
|
||||
+++ b/source4/libcli/ldap/ldap_client.c
|
||||
@@ -277,6 +277,7 @@ static void ldap_connection_recv_done(st
|
||||
struct ldap_message *msg;
|
||||
struct asn1_data *asn1;
|
||||
DATA_BLOB blob;
|
||||
+ struct ldap_request_limits limits = {0};
|
||||
|
||||
msg = talloc_zero(conn, struct ldap_message);
|
||||
if (msg == NULL) {
|
||||
@@ -306,7 +307,7 @@ static void ldap_connection_recv_done(st
|
||||
|
||||
asn1_load_nocopy(asn1, blob.data, blob.length);
|
||||
|
||||
- status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
|
||||
+ status = ldap_decode(asn1, &limits, samba_ldap_control_handlers(), msg);
|
||||
asn1_free(asn1);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(msg);
|
||||
@ -1,66 +0,0 @@
|
||||
From ee3156c76b86c11829f6f3fe1e3c940b45899c56 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Date: Wed, 8 Apr 2020 10:46:44 +1200
|
||||
Subject: [PATCH 8/8] CVE-2020-10704 libcli ldap: Check search request lengths.
|
||||
|
||||
Check the search request lengths against the limits passed to
|
||||
ldap_decode.
|
||||
|
||||
Credit to OSS-Fuzz
|
||||
|
||||
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334
|
||||
|
||||
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
|
||||
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
||||
---
|
||||
lib/util/asn1.c | 7 +++++++
|
||||
lib/util/asn1.h | 1 +
|
||||
libcli/ldap/ldap_message.c | 4 ++++
|
||||
3 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
|
||||
index ee3cff9cb65..32d7981d28f 100644
|
||||
--- a/lib/util/asn1.c
|
||||
+++ b/lib/util/asn1.c
|
||||
@@ -1159,3 +1159,10 @@ int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
|
||||
*packet_size = size;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Get the length of the ASN.1 data
|
||||
+ */
|
||||
+size_t asn1_get_length(const struct asn1_data *asn1) {
|
||||
+ return asn1->length;
|
||||
+}
|
||||
diff --git a/lib/util/asn1.h b/lib/util/asn1.h
|
||||
index fc365724e93..de92a767f14 100644
|
||||
--- a/lib/util/asn1.h
|
||||
+++ b/lib/util/asn1.h
|
||||
@@ -106,5 +106,6 @@ bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB *pblob);
|
||||
void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len);
|
||||
int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
|
||||
+size_t asn1_get_length(const struct asn1_data *asn1);
|
||||
|
||||
#endif /* _ASN_1_H */
|
||||
diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c
|
||||
index d38fa0b3b61..69a48279532 100644
|
||||
--- a/libcli/ldap/ldap_message.c
|
||||
+++ b/libcli/ldap/ldap_message.c
|
||||
@@ -1259,7 +1259,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
|
||||
struct ldap_SearchRequest *r = &msg->r.SearchRequest;
|
||||
int sizelimit, timelimit;
|
||||
const char **attrs = NULL;
|
||||
+ size_t request_size = asn1_get_length(data);
|
||||
msg->type = LDAP_TAG_SearchRequest;
|
||||
+ if (request_size > limits->max_search_size) {
|
||||
+ goto prot_err;
|
||||
+ }
|
||||
if (!asn1_start_tag(data, tag)) goto prot_err;
|
||||
if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
|
||||
if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,138 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,171 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,272 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,316 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,241 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,267 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,74 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,247 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
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
|
||||
|
||||
7
samba-4.11.12.tar.asc
Normal file
7
samba-4.11.12.tar.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iHMEABECADMWIQRS+8C4bZVLCEMyTNxvM5FbZWi36gUCX0TCrBUcc2FtYmEtYnVn
|
||||
c0BzYW1iYS5vcmcACgkQbzORW2Vot+pkIgCePoB8Vb0cE4j0tafdJDK411aAP9YA
|
||||
n0xcJD8v1hc1/qlhXLjA6bG3i7Rx
|
||||
=GXx8
|
||||
-----END PGP SIGNATURE-----
|
||||
Binary file not shown.
28
samba-4.11.13-lib_util_wscript.patch
Normal file
28
samba-4.11.13-lib_util_wscript.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 7f2c62dcdebb387b086df37c8dd38a6027d8b631 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
|
||||
Date: Tue, 25 Aug 2020 10:37:18 +0200
|
||||
Subject: [PATCH] lib/util: do not install /usr/bin/test_util
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14166
|
||||
|
||||
Guenther
|
||||
|
||||
Signed-off-by: Guenther Deschner <gd@samba.org>
|
||||
---
|
||||
lib/util/wscript_build | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
|
||||
index 4ac0a9cc064..e04752cb130 100644
|
||||
--- a/lib/util/wscript_build
|
||||
+++ b/lib/util/wscript_build
|
||||
@@ -291,4 +291,5 @@ else:
|
||||
bld.SAMBA_BINARY('test_util',
|
||||
source='tests/test_util.c',
|
||||
deps='cmocka replace talloc samba-util',
|
||||
- local_include=False)
|
||||
+ local_include=False,
|
||||
+ install=False)
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iHMEABECADMWIQRS+8C4bZVLCEMyTNxvM5FbZWi36gUCXjALthUcc2FtYmEtYnVn
|
||||
c0BzYW1iYS5vcmcACgkQbzORW2Vot+od+ACgpzREKkVcyLse9EwufX0vS/JMUYIA
|
||||
n2xGjOlyTFJJUD9heWInjmYzy4W0
|
||||
=472O
|
||||
-----END PGP SIGNATURE-----
|
||||
50
samba.spec
50
samba.spec
@ -4,7 +4,7 @@
|
||||
%define talloc_version 2.2.0
|
||||
%define tdb_version 1.4.2
|
||||
%define tevent_version 0.10.0
|
||||
%define ldb_version 2.0.8
|
||||
%define ldb_version 2.0.12
|
||||
|
||||
%undefine _strict_symbol_defs_build
|
||||
|
||||
@ -48,8 +48,8 @@
|
||||
%define samba_depver %{version}-%{release}
|
||||
|
||||
Name: samba
|
||||
Version: 4.11.6
|
||||
Release: 8
|
||||
Version: 4.11.12
|
||||
Release: 1
|
||||
|
||||
Summary: A suite for Linux to interoperate with Windows
|
||||
License: GPLv3+ and LGPLv3+
|
||||
@ -69,35 +69,7 @@ Source201: README.downgrade
|
||||
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
|
||||
Patch3: samba-4.11.13-lib_util_wscript.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
|
||||
@ -1856,6 +1828,7 @@ fi
|
||||
%{python3_sitearch}/samba/tests/__pycache__/hostconfig.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/join.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/krb5_credentials.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/ldap_raw.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/ldap_referrals.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/loadparm.*.pyc
|
||||
%{python3_sitearch}/samba/tests/__pycache__/libsmb.*.pyc
|
||||
@ -2039,6 +2012,7 @@ fi
|
||||
%{python3_sitearch}/samba/tests/kcc/kcc_utils.py
|
||||
%{python3_sitearch}/samba/tests/kcc/ldif_import_export.py
|
||||
%{python3_sitearch}/samba/tests/krb5_credentials.py
|
||||
%{python3_sitearch}/samba/tests/ldap_raw.py
|
||||
%{python3_sitearch}/samba/tests/ldap_referrals.py
|
||||
%{python3_sitearch}/samba/tests/libsmb.py
|
||||
%{python3_sitearch}/samba/tests/loadparm.py
|
||||
@ -2113,6 +2087,9 @@ fi
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_check_password_script.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_virtualCryptSHA.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_virtualCryptSHA_base.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_virtualCryptSHA_gpg.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_virtualCryptSHA_userPassword.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/user_wdigest.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/visualize.*.pyc
|
||||
%{python3_sitearch}/samba/tests/samba_tool/__pycache__/visualize_drs.*.pyc
|
||||
@ -2144,6 +2121,9 @@ fi
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_check_password_script.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_virtualCryptSHA.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_virtualCryptSHA_base.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/user_wdigest.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/visualize.py
|
||||
%{python3_sitearch}/samba/tests/samba_tool/visualize_drs.py
|
||||
@ -3076,6 +3056,12 @@ fi
|
||||
%{_mandir}/man*
|
||||
|
||||
%changelog
|
||||
* Mon Aug 31 2020 yuboyun <yuboyun@huawei.com> - 4.11.12-1
|
||||
- Type:NA
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:update to 4.11.12
|
||||
|
||||
* 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user