The Samba-Bugzilla – Attachment 15923 Details for
Bug 14334
CVE-2020-10704 [FUZZING][SECURITY] Stack overflow in AD DC (C)LDAP server
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for V4.5 (v5)
CVE-2020-10704-4.5-V5.patch (text/plain), 39.34 KB, created by
Gary Lockyer
on 2020-04-16 21:29:07 UTC
(
hide
)
Description:
Patch for V4.5 (v5)
Filename:
MIME Type:
Creator:
Gary Lockyer
Created:
2020-04-16 21:29:07 UTC
Size:
39.34 KB
patch
obsolete
>From 26003b45116842c213f12b7ffeca65da3b0c2c6d 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/6] 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/krb5_wrap/krb5_samba.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 +-- > 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 da2e2e5f4b8..4ec1bed6b7f 100644 >--- a/auth/gensec/gensec_util.c >+++ b/auth/gensec/gensec_util.c >@@ -73,7 +73,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/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c >index fe29386ad70..3ae122783fb 100644 >--- a/lib/krb5_wrap/krb5_samba.c >+++ b/lib/krb5_wrap/krb5_samba.c >@@ -552,7 +552,7 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, > return false; > } > >- data = asn1_init(mem_ctx); >+ data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH); > if (data == NULL) { > return false; > } >diff --git a/lib/util/asn1.c b/lib/util/asn1.c >index d3b46aac857..5460b677790 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; > } > >@@ -473,6 +477,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) { >@@ -480,6 +489,7 @@ bool asn1_load(struct asn1_data *data, DATA_BLOB blob) > return false; > } > data->length = blob.length; >+ data->max_depth = max_depth; > return true; > } > >@@ -1093,9 +1103,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 87f82b9b0de..2ef861498d5 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 5fcb43c29f4..6ffd2335c9e 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 89f812b97e0..c8c7808f544 100644 >--- a/source3/lib/tldap_util.c >+++ b/source3/lib/tldap_util.c >@@ -634,7 +634,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; > } >@@ -774,7 +774,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/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c >index 2af6b145f6c..3ddfaf80aec 100644 >--- a/source4/auth/gensec/gensec_krb5.c >+++ b/source4/auth/gensec/gensec_krb5.c >@@ -409,7 +409,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; > } >@@ -443,7 +443,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 31c1171f7ad..42bdc51358b 100644 >--- a/source4/ldap_server/ldap_server.c >+++ b/source4/ldap_server/ldap_server.c >@@ -525,7 +525,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 40d508cb01c..3129d96e97d 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 7ecc9080cd1..4ea55dbd0cd 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 > > >From e22cf00ad40656dadd3c821c795acc6ab26600fc 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 2/6] 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 +++++++++++++ > 1 file changed, 13 insertions(+) > >diff --git a/lib/util/asn1.c b/lib/util/asn1.c >index 5460b677790..d0de05911bf 100644 >--- a/lib/util/asn1.c >+++ b/lib/util/asn1.c >@@ -640,6 +640,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; > >@@ -696,6 +706,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; >-- >2.17.1 > > >From ecb1f6c015e1e2a33062e706f8d6d95a5dfabc8b 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 3/6] 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 > >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/lib/param/loadparm.c b/lib/param/loadparm.c >index 5f4610ead7e..9e42f820ecf 100644 >--- a/lib/param/loadparm.c >+++ b/lib/param/loadparm.c >@@ -2914,6 +2914,11 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) > } > } > >+ 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; >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index 7f9a1d149e6..d09eb59204a 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -933,6 +933,9 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) > > Globals.aio_max_threads = 100; > >+ 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(); > } >-- >2.17.1 > > >From 3879e64c7ba7a049148bb7d7acc8066e43202ecc 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 4/6] 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> >--- > source4/ldap_server/ldap_server.c | 98 ++++++++++++++++++++++++++++++- > 1 file changed, 96 insertions(+), 2 deletions(-) > >diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c >index 42bdc51358b..4739c604f12 100644 >--- a/source4/ldap_server/ldap_server.c >+++ b/source4/ldap_server/ldap_server.c >@@ -415,6 +415,10 @@ static void ldapsrv_accept_tls_done(struct tevent_req *subreq) > } > > 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) > { >@@ -468,7 +472,7 @@ static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn) > 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: " >@@ -486,6 +490,9 @@ static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn) > } > > 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) > { >@@ -496,6 +503,7 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq) > struct ldapsrv_call *call; > struct asn1_data *asn1; > DATA_BLOB blob; >+ int ret = LDAP_SUCCESS; > > conn->sockets.read_req = NULL; > >@@ -525,6 +533,14 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq) > 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"); >@@ -1182,7 +1198,85 @@ failed: > } > > >-NTSTATUS server_service_ldap_init(void) >+/* >+ * 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) > { > return register_server_service("ldap", ldapsrv_task_init); > } >-- >2.17.1 > > >From 8f82faacdf2d4d5b98765301ae13faba706bad32 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 5/6] 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 +++++ > source3/param/loadparm.c | 1 + > source4/ldap_server/ldap_server.c | 10 ++++++++-- > source4/libcli/ldap/ldap_client.c | 3 ++- > 8 files changed, 52 insertions(+), 6 deletions(-) > create mode 100644 docs-xml/smbdotconf/ldap/ldapmaxsearchrequest.xml > >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/param/loadparm.c b/lib/param/loadparm.c >index 9e42f820ecf..21d5dbc3012 100644 >--- a/lib/param/loadparm.c >+++ b/lib/param/loadparm.c >@@ -2918,6 +2918,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) > 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)) { >diff --git a/libcli/cldap/cldap.c b/libcli/cldap/cldap.c >index 2ef861498d5..2cebe1ab19b 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) { >@@ -224,6 +229,9 @@ 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; >@@ -242,7 +250,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; > } >@@ -772,6 +780,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; >@@ -782,7 +793,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; > } >@@ -798,7 +809,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 ba82bddeab1..d38fa0b3b61 100644 >--- a/libcli/ldap/ldap_message.c >+++ b/libcli/ldap/ldap_message.c >@@ -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) > { >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/source3/param/loadparm.c b/source3/param/loadparm.c >index d09eb59204a..d08714a56d3 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -935,6 +935,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) > > 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(); >diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c >index 4739c604f12..171316b47a6 100644 >--- a/source4/ldap_server/ldap_server.c >+++ b/source4/ldap_server/ldap_server.c >@@ -504,6 +504,7 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq) > struct asn1_data *asn1; > DATA_BLOB blob; > int ret = LDAP_SUCCESS; >+ struct ldap_request_limits limits = {0}; > > conn->sockets.read_req = NULL; > >@@ -558,8 +559,13 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq) > 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; >diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c >index 3129d96e97d..e7dcb80d05c 100644 >--- a/source4/libcli/ldap/ldap_client.c >+++ b/source4/libcli/ldap/ldap_client.c >@@ -277,6 +277,7 @@ static void ldap_connection_recv_done(struct tevent_req *subreq) > 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(struct tevent_req *subreq) > > 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); >-- >2.17.1 > > >From 1358a839a9d024a7c81f0aa9e6ce966263b00af9 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 6/6] 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 d0de05911bf..6b5f1beba37 100644 >--- a/lib/util/asn1.c >+++ b/lib/util/asn1.c >@@ -1149,3 +1149,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 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
abartlet
:
review+
gary
:
ci-passed+
Actions:
View
Attachments on
bug 14334
:
15889
|
15893
|
15894
|
15895
|
15896
|
15906
|
15907
|
15910
|
15914
|
15915
|
15916
|
15917
|
15918
|
15920
|
15922
| 15923