[SCM] Samba Shared Repository - branch master updated

Gary Lockyer gary at samba.org
Mon May 4 04:41:07 UTC 2020


The branch, master has been updated
       via  bac809348a7 CVE-2020-10704 libcli ldap: Check search request lengths.
       via  3149ea0a8aa CVE-2020-10704: libcli ldap_message: Add search size limits to ldap_decode
       via  28ee4acc834 CVE-2020-10704: S4 ldap server: Limit request sizes
       via  d7e5213818b CVE-2020-10704: smb.conf: Add max ldap request sizes
       via  5d6bcef4b4c CVE-2020-10704: ldapserver tests: Limit search request sizes
       via  767558d4242 CVE-2020-10704: lib util asn1: Check parse tree depth
       via  b0832d20163 CVE-2020-10704: libcli ldap: test recursion depth in ldap_decode_filter_tree
       via  f467727db5f CVE-2020-10704: lib util asn1: Add ASN.1 max tree depth
      from  62621bd686a smbd: use is_lease_stat_open() in delay_for_oplock()

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit bac809348a7313a5a5a53866848e7b6b56665f43
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Apr 8 10:46:44 2020 +1200

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Gary Lockyer <gary at samba.org>
    Autobuild-Date(master): Mon May  4 04:40:10 UTC 2020 on sn-devel-184

commit 3149ea0a8aada3b03d1ca0af2e3a0f6304cda43b
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Apr 8 08:49:23 2020 +1200

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 28ee4acc8347299cb41119012d9256d48c92cc5c
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Apr 8 15:32:22 2020 +1200

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d7e5213818b960325909c73432cba34ad270fd50
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue Apr 7 09:09:01 2020 +1200

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 5d6bcef4b4cb0c086733353469ffc04dfaa8ccdd
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue Apr 14 13:32:32 2020 +1200

    CVE-2020-10704: ldapserver tests: Limit search request sizes
    
    Add tests to ensure that overly long (> 256000 bytes) LDAP search
    requests are rejected.
    
    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 767558d4242f311bbf9ae8f5d86e0988a5baaeb9
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Apr 8 15:30:52 2020 +1200

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit b0832d20163146e59586de5556a3ef75187f600f
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Apr 2 15:25:53 2020 +1300

    CVE-2020-10704: libcli ldap: test recursion depth in ldap_decode_filter_tree
    
    Add tests to check that ASN.1 ldap requests with deeply nested elements
    are rejected.  Previously there was no check on the on the depth of
    nesting and excessive nesting could cause a stack overflow.
    
    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f467727db5ff6a6e58d9b590e4d443a1d974b679
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Fri Apr 3 12:18:03 2020 +1300

    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 at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 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/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/ldap_server/ldap_server.c                 | 108 +++++++-
 source4/libcli/ldap/ldap_client.c                 |   5 +-
 source4/libcli/ldap/ldap_controls.c               |  48 ++--
 source4/selftest/tests.py                         |   7 +
 28 files changed, 838 insertions(+), 53 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
 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


Changeset truncated at 500 lines:

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/param/loadparm.c b/lib/param/loadparm.c
index 4bee921e3c7..777999a3a76 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -3056,6 +3056,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 6ae54d4cf20..dc3f43f33f4 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;
@@ -1119,9 +1142,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)
@@ -1147,3 +1175,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;
+	struct ldap_request_limits limits = {
+		.max_search_size = MAX_SEARCH_REQUEST
+	};
 
 	if (in->recv_errno != 0) {
 		goto error;
 	}
 
-	asn1 = asn1_init(in);
+	asn1 = asn1_init(in, ASN1_MAX_TREE_DEPTH);
 	if (!asn1) {
 		goto nomem;
 	}
@@ -246,7 +254,7 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c,
 	}
 
 	/* 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;
 	}
@@ -774,6 +782,9 @@ NTSTATUS cldap_search_recv(struct tevent_req *req,
 					   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;
@@ -784,7 +795,7 @@ NTSTATUS cldap_search_recv(struct tevent_req *req,
 		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;
 	}
@@ -800,7 +811,8 @@ NTSTATUS cldap_search_recv(struct tevent_req *req,
 		*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;
 		}
diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c
index f21598374a1..69a48279532 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;
@@ -1162,6 +1162,7 @@ static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 /* 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)
 {
@@ -1258,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;
diff --git a/libcli/ldap/ldap_message.h b/libcli/ldap/ldap_message.h
index 2f64881c053..19bfb99ac97 100644
--- 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,
diff --git a/libcli/ldap/tests/data/10000-or.dat b/libcli/ldap/tests/data/10000-or.dat
new file mode 100644
index 00000000000..e2d6de2ce33
Binary files /dev/null and b/libcli/ldap/tests/data/10000-or.dat differ
diff --git a/libcli/ldap/tests/data/ldap-recursive.dat b/libcli/ldap/tests/data/ldap-recursive.dat
new file mode 100644
index 00000000000..dd18d857660
Binary files /dev/null and b/libcli/ldap/tests/data/ldap-recursive.dat differ
diff --git a/libcli/ldap/tests/ldap_message_test.c b/libcli/ldap/tests/ldap_message_test.c
new file mode 100644
index 00000000000..c5aacd4bc6b
--- /dev/null
+++ b/libcli/ldap/tests/ldap_message_test.c
@@ -0,0 +1,287 @@
+/*
+ * Unit tests for ldap_message.
+ *
+ *  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/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "lib/util/attr.h"
+#include "includes.h"
+#include "lib/util/asn1.h"
+#include "libcli/ldap/ldap_message.h"
+#include "libcli/ldap/ldap_proto.h"
+
+/*
+ * declare the internal cmocka cm_print so we can output messages in
+ * sub unit format
+ */
+void cm_print_error(const char * const format, ...);
+/*
+ * helper function and macro to compare an ldap error code constant with the
+ * coresponding nt_status code
+ */
+#define NT_STATUS_LDAP_V(code) (0xF2000000 | code)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list