[SCM] Samba Shared Repository - branch v4-12-test updated
Karolin Seeger
kseeger at samba.org
Tue Apr 28 11:49:19 UTC 2020
The branch, v4-12-test has been updated
via af4d2a38fcb VERSION: Bump version up to 4.12.3.
via 11620a07a89 Merge tag 'samba-4.12.2' into v4-12-test
via ee9600d8a8f VERSION: Disable GIT_SNAPSHOT for the 4.12.2 release.
via 51b4bf0c873 WHATSNEW: Add release notes for Samba 4.12.2.
via 71b92c9554d CVE-2020-10704 libcli ldap: Check search request lengths.
via db78f2667eb CVE-2020-10704: libcli ldap_message: Add search size limits to ldap_decode
via 8729c05b1cd CVE-2020-10704: S4 ldap server: Limit request sizes
via 48a3bdd7703 CVE-2020-10704: smb.conf: Add max ldap request sizes
via 4aeb07ef49e CVE-2020-10704: ldapserver tests: Limit search request sizes
via 16da9c6e3d8 CVE-2020-10704: lib util asn1: Check parse tree depth
via 74986c179ea CVE-2020-10704: libcli ldap: test recursion depth in ldap_decode_filter_tree
via 109b128ec1d CVE-2020-10704: lib util asn1: Add ASN.1 max tree depth
via fecb05c8980 CVE-2020-10700: ldb: Bump version up to 2.1.2.
via fb3e51020ab CVE-2020-10700: dsdb: Do not permit the ASQ control for the GUID search in paged_results
via b824444544f CVE-2020-10700: ldb: Always use ldb_next_request() in ASQ module
via 8e597aa1b9b CVE-2020-10700: dsdb: Add test for ASQ and ASQ in combination with paged_results
via feb24fc1e51 VERSION: Bump version up to 4.12.2...
from 21f64af155b ctdb: Fix a memleak
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-12-test
- Log -----------------------------------------------------------------
commit af4d2a38fcb92ae58e4310acbfe43ab9548d1fa5
Author: Karolin Seeger <kseeger at samba.org>
Date: Tue Apr 28 13:48:51 2020 +0200
VERSION: Bump version up to 4.12.3.
Signed-off-by: Karolin Seeger <kseeger at samba.org>
commit 11620a07a898146384f1473206791ebcfe09dfa5
Merge: 21f64af155b ee9600d8a8f
Author: Karolin Seeger <kseeger at samba.org>
Date: Tue Apr 28 13:48:23 2020 +0200
Merge tag 'samba-4.12.2' into v4-12-test
samba: tag release samba-4.12.2
-----------------------------------------------------------------------
Summary of changes:
VERSION | 2 +-
WHATSNEW.txt | 65 ++++-
auth/gensec/gensec_util.c | 2 +-
docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml | 18 ++
docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml | 18 ++
docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml | 18 ++
lib/fuzzing/fuzz_ldap_decode.c | 15 +-
lib/ldb/ABI/{ldb-2.0.5.sigs => ldb-2.1.2.sigs} | 0
...pyldb-util-2.1.0.sigs => pyldb-util-2.1.2.sigs} | 0
lib/ldb/modules/asq.c | 12 +-
lib/ldb/wscript | 2 +-
lib/param/loadparm.c | 7 +
lib/util/asn1.c | 37 ++-
lib/util/asn1.h | 10 +-
lib/util/tests/asn1_tests.c | 2 +-
libcli/auth/spnego_parse.c | 6 +-
libcli/cldap/cldap.c | 20 +-
libcli/ldap/ldap_message.c | 7 +-
libcli/ldap/ldap_message.h | 5 +
libcli/ldap/tests/data/10000-or.dat | Bin 0 -> 39875 bytes
libcli/ldap/tests/data/ldap-recursive.dat | Bin 0 -> 970 bytes
libcli/ldap/tests/ldap_message_test.c | 287 +++++++++++++++++++++
libcli/ldap/wscript_build | 15 ++
python/samba/tests/ldap_raw.py | 234 +++++++++++++++++
source3/lib/tldap.c | 4 +-
source3/lib/tldap_util.c | 4 +-
source3/libsmb/clispnego.c | 4 +-
source3/param/loadparm.c | 4 +
source3/torture/torture.c | 2 +-
source4/auth/gensec/gensec_krb5.c | 4 +-
source4/dsdb/samdb/ldb_modules/paged_results.c | 18 +-
source4/dsdb/tests/python/asq.py | 171 ++++++++++++
source4/ldap_server/ldap_server.c | 108 +++++++-
source4/libcli/ldap/ldap_client.c | 5 +-
source4/libcli/ldap/ldap_controls.c | 48 ++--
source4/selftest/tests.py | 8 +
36 files changed, 1091 insertions(+), 71 deletions(-)
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml
create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml
copy lib/ldb/ABI/{ldb-2.0.5.sigs => ldb-2.1.2.sigs} (100%)
copy lib/ldb/ABI/{pyldb-util-2.1.0.sigs => pyldb-util-2.1.2.sigs} (100%)
create mode 100644 libcli/ldap/tests/data/10000-or.dat
create mode 100644 libcli/ldap/tests/data/ldap-recursive.dat
create mode 100644 libcli/ldap/tests/ldap_message_test.c
create mode 100644 python/samba/tests/ldap_raw.py
create mode 100644 source4/dsdb/tests/python/asq.py
Changeset truncated at 500 lines:
diff --git a/VERSION b/VERSION
index e651d0ad94b..2a84f16e464 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
########################################################
SAMBA_VERSION_MAJOR=4
SAMBA_VERSION_MINOR=12
-SAMBA_VERSION_RELEASE=2
+SAMBA_VERSION_RELEASE=3
########################################################
# If a official release has a serious bug #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 621fb63bac8..57498cdc8ed 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,3 +1,64 @@
+ ==============================
+ Release Notes for Samba 4.12.2
+ April 28, 2020
+ ==============================
+
+
+This is a security release in order to address the following defects:
+
+o CVE-2020-10700: Use-after-free in Samba AD DC LDAP Server with ASQ
+o CVE-2020-10704: LDAP Denial of Service (stack overflow) in Samba AD DC
+
+
+=======
+Details
+=======
+
+o CVE-2020-10700:
+ A client combining the 'ASQ' and 'Paged Results' LDAP controls can cause a
+ use-after-free in Samba's AD DC LDAP server.
+o CVE-2020-10704:
+ A deeply nested filter in an un-authenticated LDAP search can exhaust the
+ LDAP server's stack memory causing a SIGSEGV.
+
+For more details, please refer to the security advisories.
+
+
+Changes since 4.12.1
+--------------------
+
+o Andrew Bartlett <abartlet at samba.org>
+ * BUG 14331: CVE-2020-10700: Fix use-after-free in AD DC LDAP server when
+ ASQ and paged_results combined.
+
+o Gary Lockyer <gary at catalyst.net.nz>
+ * BUG 20454: CVE-2020-10704: Fix LDAP Denial of Service (stack overflow) in
+ Samba AD DC.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the Samba 4.1 and newer product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
==============================
Release Notes for Samba 4.12.1
April 07, 2020
@@ -70,8 +131,8 @@ database (https://bugzilla.samba.org/).
======================================================================
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
+
==============================
Release Notes for Samba 4.12.0
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/docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml b/docs-xml/smbdotconf/ldap/ldapmaxanonrequest.xml
new file mode 100644
index 00000000000..61bdcec674d
--- /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>
diff --git a/docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml b/docs-xml/smbdotconf/ldap/ldapmaxauthrequest.xml
new file mode 100644
index 00000000000..c5934f73f95
--- /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>
diff --git a/docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml b/docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml
new file mode 100644
index 00000000000..ebeb0816c01
--- /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>
diff --git a/lib/fuzzing/fuzz_ldap_decode.c b/lib/fuzzing/fuzz_ldap_decode.c
index 659169aca96..e3bcf7b9d0a 100644
--- a/lib/fuzzing/fuzz_ldap_decode.c
+++ b/lib/fuzzing/fuzz_ldap_decode.c
@@ -32,9 +32,19 @@ int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len)
TALLOC_CTX *mem_ctx = talloc_init(__FUNCTION__);
struct asn1_data *asn1;
struct ldap_message *ldap_msg;
+ struct ldap_request_limits limits = {
+ /*
+ * The default size is currently 256000 bytes
+ */
+ .max_search_size = 256000
+ };
NTSTATUS status;
- asn1 = asn1_init(mem_ctx);
+ /*
+ * Need to limit the max parse tree depth to 250 to prevent
+ * ASAN detecting stack overflows.
+ */
+ asn1 = asn1_init(mem_ctx, 250);
if (!asn1) {
goto out;
}
@@ -46,7 +56,8 @@ int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len)
goto out;
}
- status = ldap_decode(asn1, samba_ldap_control_handlers(), ldap_msg);
+ status = ldap_decode(
+ asn1, &limits, samba_ldap_control_handlers(), ldap_msg);
out:
talloc_free(mem_ctx);
diff --git a/lib/ldb/ABI/ldb-2.0.5.sigs b/lib/ldb/ABI/ldb-2.1.2.sigs
similarity index 100%
copy from lib/ldb/ABI/ldb-2.0.5.sigs
copy to lib/ldb/ABI/ldb-2.1.2.sigs
diff --git a/lib/ldb/ABI/pyldb-util-2.1.0.sigs b/lib/ldb/ABI/pyldb-util-2.1.2.sigs
similarity index 100%
copy from lib/ldb/ABI/pyldb-util-2.1.0.sigs
copy to lib/ldb/ABI/pyldb-util-2.1.2.sigs
diff --git a/lib/ldb/modules/asq.c b/lib/ldb/modules/asq.c
index 7482de826f0..4eba941ae0b 100644
--- a/lib/ldb/modules/asq.c
+++ b/lib/ldb/modules/asq.c
@@ -311,12 +311,9 @@ static int asq_build_multiple_requests(struct asq_context *ac, bool *terminated)
static int asq_search_continue(struct asq_context *ac)
{
- struct ldb_context *ldb;
bool terminated = false;
int ret;
- ldb = ldb_module_get_ctx(ac->module);
-
switch (ac->step) {
case ASQ_SEARCH_BASE:
@@ -328,7 +325,7 @@ static int asq_search_continue(struct asq_context *ac)
ac->step = ASQ_SEARCH_MULTI;
- return ldb_request(ldb, ac->reqs[ac->cur_req]);
+ return ldb_next_request(ac->module, ac->reqs[ac->cur_req]);
case ASQ_SEARCH_MULTI:
@@ -339,7 +336,7 @@ static int asq_search_continue(struct asq_context *ac)
return asq_search_terminate(ac);
}
- return ldb_request(ldb, ac->reqs[ac->cur_req]);
+ return ldb_next_request(ac->module, ac->reqs[ac->cur_req]);
}
return LDB_ERR_OPERATIONS_ERROR;
@@ -347,14 +344,11 @@ static int asq_search_continue(struct asq_context *ac)
static int asq_search(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_context *ldb;
struct ldb_request *base_req;
struct ldb_control *control;
struct asq_context *ac;
int ret;
- ldb = ldb_module_get_ctx(module);
-
/* check if there's an ASQ control */
control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID);
if (control == NULL) {
@@ -385,7 +379,7 @@ static int asq_search(struct ldb_module *module, struct ldb_request *req)
ac->step = ASQ_SEARCH_BASE;
- return ldb_request(ldb, base_req);
+ return ldb_next_request(ac->module, base_req);
}
static int asq_init(struct ldb_module *module)
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index 06c8922aa8d..17ec69bc194 100644
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'ldb'
-VERSION = '2.1.1'
+VERSION = '2.1.2'
import sys, os
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 611c1b240af..63291283905 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -3041,6 +3041,13 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
lpcfg_do_global_parameter(lp_ctx, "spotlight backend", "noindex");
+ lpcfg_do_global_parameter(
+ 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)) {
lp_ctx->flags[i] |= FLAG_DEFAULT;
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
index 51da5424956..32d7981d28f 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;
}
@@ -637,6 +647,16 @@ bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
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;
@@ -693,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;
@@ -1103,9 +1126,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)
@@ -1131,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 ddd69863574..de92a767f14 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);
@@ -99,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/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 f609bf278e4..7de72b5e899 100644
--- 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) {
@@ -228,12 +233,15 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c,
void *p;
struct cldap_search_state *search;
NTSTATUS status;
--
Samba Shared Repository
More information about the samba-cvs
mailing list