[openssl] master update

beldmit at gmail.com beldmit at gmail.com
Tue May 19 16:05:53 UTC 2020


The branch master has been updated
       via  e638112e15c63bfb4ab9bf5af66aa439e5983f23 (commit)
       via  09b90e0ed7915809fcd4ee1e250d881b77d06d45 (commit)
      from  fb420afc878fa38a5d8cf22e25cf7d438d39987a (commit)


- Log -----------------------------------------------------------------
commit e638112e15c63bfb4ab9bf5af66aa439e5983f23
Author: Dmitry Belyavskiy <beldmit at gmail.com>
Date:   Fri May 15 23:03:41 2020 +0300

    Test for the SSL_OP_IGNORE_UNEXPECTED_EOF option
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11735)

commit 09b90e0ed7915809fcd4ee1e250d881b77d06d45
Author: Dmitry Belyavskiy <beldmit at gmail.com>
Date:   Tue May 5 16:20:42 2020 +0300

    Introducing option SSL_OP_IGNORE_UNEXPECTED_EOF
    
    Partially fixes #11209.
    
    Before OpenSSL 3.0 in case when peer does not send close_notify,
    the behaviour was to set SSL_ERROR_SYSCALL error with errno 0.
    This behaviour has changed. The SSL_OP_IGNORE_UNEXPECTED_EOF restores
    the old behaviour for compatibility's sake.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11735)

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

Summary of changes:
 CHANGES.md                       |  6 +++++
 apps/s_client.c                  | 11 +++++++-
 apps/s_server.c                  | 12 +++++++--
 doc/man1/openssl-s_client.pod.in | 10 +++++++
 doc/man1/openssl-s_server.pod.in | 10 +++++++
 doc/man3/SSL_CTX_set_options.pod | 19 ++++++++++++--
 doc/man3/SSL_get_error.pod       | 12 +++++++++
 doc/man3/SSL_shutdown.pod        |  8 +++---
 include/openssl/ssl.h            |  7 +----
 ssl/record/rec_layer_s3.c        |  9 +++++--
 test/sslapitest.c                | 56 ++++++++++++++++++++++++++++++++++++++++
 11 files changed, 144 insertions(+), 16 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index e5731d0e61..8afcb07b50 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -42,6 +42,12 @@ OpenSSL 3.0
 
    *Shane Lontis*
 
+ * The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced. If that option
+   is set, an unexpected EOF is ignored, it pretends a close notify was received
+   instead and so the returned error becomes SSL_ERROR_ZERO_RETURN.
+
+   *Dmitry Belyavskiy*
+
  * Deprecated EC_POINT_set_Jprojective_coordinates_GFp() and
    EC_POINT_get_Jprojective_coordinates_GFp(). These functions are not widely
    used and applications should instead use the
diff --git a/apps/s_client.c b/apps/s_client.c
index a5f0fa0444..e21a23da75 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -576,7 +576,7 @@ typedef enum OPTION_choice {
     OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
     OPT_V_ENUM,
     OPT_X_ENUM,
-    OPT_S_ENUM,
+    OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF,
     OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
     OPT_DANE_TLSA_DOMAIN,
 #ifndef OPENSSL_NO_CT
@@ -718,6 +718,8 @@ const OPTIONS s_client_options[] = {
      "Do not send the server name (SNI) extension in the ClientHello"},
     {"tlsextdebug", OPT_TLSEXTDEBUG, '-',
      "Hex dump of all TLS extensions received"},
+    {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+     "Do not treat lack of close_notify from a peer as an error"},
 #ifndef OPENSSL_NO_OCSP
     {"status", OPT_STATUS, '-', "Request certificate status from server"},
 #endif
@@ -1001,6 +1003,7 @@ int s_client_main(int argc, char **argv)
 #ifndef OPENSSL_NO_SCTP
     int sctp_label_bug = 0;
 #endif
+    int ignore_unexpected_eof = 0;
 
     FD_ZERO(&readfds);
     FD_ZERO(&writefds);
@@ -1180,6 +1183,9 @@ int s_client_main(int argc, char **argv)
             if (!args_excert(o, &exc))
                 goto end;
             break;
+        case OPT_IGNORE_UNEXPECTED_EOF:
+            ignore_unexpected_eof = 1;
+            break;
         case OPT_PREXIT:
             prexit = 1;
             break;
@@ -1776,6 +1782,9 @@ int s_client_main(int argc, char **argv)
         && SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
         goto end;
 
+    if (ignore_unexpected_eof)
+        SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
     if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
         BIO_printf(bio_err, "Error setting verify params\n");
         ERR_print_errors(bio_err);
diff --git a/apps/s_server.c b/apps/s_server.c
index 09bcc0cfb8..9995953526 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -761,7 +761,7 @@ typedef enum OPTION_choice {
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
     OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
     OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
-    OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES,
+    OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
     OPT_R_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
@@ -850,6 +850,8 @@ const OPTIONS s_server_options[] = {
      "Disable caching and tickets if ephemeral (EC)DH is used"},
     {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
     {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
+    {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+     "Do not treat lack of close_notify from a peer as an error"},
     {"tlsextdebug", OPT_TLSEXTDEBUG, '-',
      "Hex dump of all TLS extensions received"},
     {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
@@ -1094,6 +1096,7 @@ int s_server_main(int argc, char *argv[])
 #ifndef OPENSSL_NO_SCTP
     int sctp_label_bug = 0;
 #endif
+    int ignore_unexpected_eof = 0;
 
     /* Init of few remaining global variables */
     local_argc = argc;
@@ -1667,6 +1670,9 @@ int s_server_main(int argc, char *argv[])
             use_sendfile = 1;
 #endif
             break;
+        case OPT_IGNORE_UNEXPECTED_EOF:
+            ignore_unexpected_eof = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1867,7 +1873,6 @@ int s_server_main(int argc, char *argv[])
             goto end;
         }
     }
-
 #ifndef OPENSSL_NO_SCTP
     if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
         SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
@@ -1911,6 +1916,9 @@ int s_server_main(int argc, char *argv[])
         SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
     }
 
+    if (ignore_unexpected_eof)
+        SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
     if (max_send_fragment > 0
         && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
         BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
diff --git a/doc/man1/openssl-s_client.pod.in b/doc/man1/openssl-s_client.pod.in
index 4d6b54a5e3..367e59e925 100644
--- a/doc/man1/openssl-s_client.pod.in
+++ b/doc/man1/openssl-s_client.pod.in
@@ -78,6 +78,7 @@ B<openssl> B<s_client>
 [B<-split_send_frag>]
 [B<-max_pipelines>]
 [B<-read_buf>]
+[B<-ignore_unexpected_eof>]
 [B<-bugs>]
 [B<-comp>]
 [B<-no_comp>]
@@ -578,6 +579,15 @@ effect if the buffer size is larger than the size that would otherwise be used
 and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
 further information).
 
+=item B<-ignore_unexpected_eof>
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
 =item B<-bugs>
 
 There are several known bugs in SSL and TLS implementations. Adding this
diff --git a/doc/man1/openssl-s_server.pod.in b/doc/man1/openssl-s_server.pod.in
index 8e5da51c40..28ef15ea56 100644
--- a/doc/man1/openssl-s_server.pod.in
+++ b/doc/man1/openssl-s_server.pod.in
@@ -47,6 +47,7 @@ B<openssl> B<s_server>
 [B<-WWW>]
 [B<-http_server_binmode>]
 [B<-no_ca_names>]
+[B<-ignore_unexpected_eof>]
 [B<-servername>]
 [B<-servername_fatal>]
 [B<-tlsextdebug>]
@@ -420,6 +421,15 @@ Disable TLS Extension CA Names. You may want to disable it for security reasons
 or for compatibility with some Windows TLS implementations crashing when this
 extension is larger than 1024 bytes.
 
+=item B<-ignore_unexpected_eof>
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
 =item B<-id_prefix> I<val>
 
 Generate SSL/TLS session IDs prefixed by I<val>. This is mostly useful
diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod
index 39cb2ec30e..24bf66ad85 100644
--- a/doc/man3/SSL_CTX_set_options.pod
+++ b/doc/man3/SSL_CTX_set_options.pod
@@ -217,6 +217,20 @@ not propose, and servers will not accept the extension.
 Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
 messages, and ignore renegotiation requests via ClientHello.
 
+=item SSL_OP_IGNORE_UNEXPECTED_EOF
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+
+You should only enable this option if the protocol running over TLS
+can detect a truncation attack itself, and that the application is checking for
+that truncation attack.
+
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
 =item SSL_OP_ALLOW_NO_DHE_KEX
 
 In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
@@ -367,7 +381,7 @@ secure renegotiation and 0 if it does not.
 
 =head1 SEE ALSO
 
-L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>,
+L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>, L<SSL_shutdown(3)>
 L<SSL_CTX_set_tmp_dh_callback(3)>,
 L<SSL_CTX_set_min_proto_version(3)>,
 L<openssl-dhparam(1)>
@@ -380,7 +394,8 @@ OpenSSL 0.9.8m.
 The B<SSL_OP_PRIORITIZE_CHACHA> and B<SSL_OP_NO_RENEGOTIATION> options
 were added in OpenSSL 1.1.1.
 
-The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> option was added in OpenSSL 3.0.
+The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> and B<SSL_OP_IGNORE_UNEXPECTED_EOF>
+options were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod
index 8d081a5e0d..f13f3ea468 100644
--- a/doc/man3/SSL_get_error.pod
+++ b/doc/man3/SSL_get_error.pod
@@ -25,6 +25,15 @@ other OpenSSL function calls should appear in between.  The current
 thread's error queue must be empty before the TLS/SSL I/O operation is
 attempted, or SSL_get_error() will not work reliably.
 
+=head1 NOTES
+
+Some TLS implementations do not send a close_notify alert on shutdown.
+
+On an unexpected EOF, versions before OpenSSL 3.0 returned
+B<SSL_ERROR_SYSCALL>, nothing was added to the error stack, and errno was 0.
+Since OpenSSL 3.0 the returned error is B<SSL_ERROR_SSL> with a meaningful
+error on the error stack.
+
 =head1 RETURN VALUES
 
 The following return values can currently occur:
@@ -44,6 +53,9 @@ No more data can be read.
 Note that B<SSL_ERROR_ZERO_RETURN> does not necessarily
 indicate that the underlying transport has been closed.
 
+This error can also appear when the option B<SSL_OP_IGNORE_UNEXPECTED_EOF>
+is set. See L<SSL_CTX_set_options(3)> for more details.
+
 =item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
 
 The operation did not complete and can be retried later.
diff --git a/doc/man3/SSL_shutdown.pod b/doc/man3/SSL_shutdown.pod
index 25191130ae..34469bae37 100644
--- a/doc/man3/SSL_shutdown.pod
+++ b/doc/man3/SSL_shutdown.pod
@@ -83,8 +83,10 @@ message, otherwise an unexpected EOF will be reported.
 There are implementations that do not send the required close_notify alert.
 If there is a need to communicate with such an implementation, and it's clear
 that all data has been received, do not wait for the peer's close_notify alert.
-Waiting for the close_notify alert when the peer just closes the connection will
-result in an error being generated.
+Waiting for the close_notify alert when the peer just closes the connection
+will result in an error being generated.
+The error can be ignored using the B<SSL_OP_IGNORE_UNEXPECTED_EOF>.
+For more information see L<SSL_CTX_set_options(3)>.
 
 =head2 First to close the connection
 
@@ -159,7 +161,7 @@ It can also occur when not all data was read using SSL_read().
 
 L<SSL_get_error(3)>, L<SSL_connect(3)>,
 L<SSL_accept(3)>, L<SSL_set_shutdown(3)>,
-L<SSL_CTX_set_quiet_shutdown(3)>,
+L<SSL_CTX_set_quiet_shutdown(3)>, L<SSL_CTX_set_options(3)>
 L<SSL_clear(3)>, L<SSL_free(3)>,
 L<ssl(7)>, L<bio(7)>
 
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 05755b014d..d1e9f7957d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -325,14 +325,9 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
 /* Allow initial connection to servers that don't support RI */
 # define SSL_OP_LEGACY_SERVER_CONNECT                    0x00000004U
 
-/* Reserved value (until OpenSSL 3.0.0)                  0x00000008U */
 # define SSL_OP_TLSEXT_PADDING                           0x00000010U
-/* Reserved value (until OpenSSL 3.0.0)                  0x00000020U */
 # define SSL_OP_SAFARI_ECDHE_ECDSA_BUG                   0x00000040U
-/*
- * Reserved value (until OpenSSL 3.0.0)                  0x00000080U
- * Reserved value (until OpenSSL 3.0.0)                  0x00000100U
- */
+# define SSL_OP_IGNORE_UNEXPECTED_EOF                    0x00000080U
 
 # define SSL_OP_DISABLE_TLSEXT_CA_NAMES                  0x00000200U
 
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index bceac72051..b1dcd517e2 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -303,8 +303,13 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
             if (ret <= 0
                     && !BIO_should_retry(s->rbio)
                     && BIO_eof(s->rbio)) {
-                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_READ_N,
-                         SSL_R_UNEXPECTED_EOF_WHILE_READING);
+                if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
+                    SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN);
+                    s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
+                } else {
+                    SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_READ_N,
+                             SSL_R_UNEXPECTED_EOF_WHILE_READING);
+                }
             }
         } else {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N,
diff --git a/test/sslapitest.c b/test/sslapitest.c
index c1c288e50a..423da560ae 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -6782,6 +6782,61 @@ static int test_ticket_callbacks(int tst)
     return testresult;
 }
 
+/*
+ * Test incorrect shutdown.
+ * Test 0: client does not shutdown properly,
+ *         server does not set SSL_OP_IGNORE_UNEXPECTED_EOF,
+ *         server should get SSL_ERROR_SSL
+ * Test 1: client does not shutdown properly,
+ *         server sets SSL_OP_IGNORE_UNEXPECTED_EOF,
+ *         server should get SSL_ERROR_ZERO_RETURN
+ */
+static int test_incorrect_shutdown(int tst)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    char buf[80];
+    BIO *c2s;
+
+    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+                                       TLS_client_method(), 0, 0,
+                                       &sctx, &cctx, cert, privkey)))
+        goto end;
+
+    if (tst == 1)
+        SSL_CTX_set_options(sctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+                                            NULL, NULL)))
+        goto end;
+
+    if (!TEST_true(create_ssl_connection(serverssl, clientssl,
+                                              SSL_ERROR_NONE)))
+        goto end;
+
+    c2s = SSL_get_rbio(serverssl);
+    BIO_set_mem_eof_return(c2s, 0);
+
+    if (!TEST_false(SSL_read(serverssl, buf, sizeof(buf))))
+        goto end;
+
+    if (tst == 0 && !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL) )
+        goto end;
+    if (tst == 1 && !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_ZERO_RETURN) )
+        goto end;
+
+    testresult = 1;
+
+ end:
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
 /*
  * Test bi-directional shutdown.
  * Test 0: TLSv1.2
@@ -7796,6 +7851,7 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data));
     ADD_ALL_TESTS(test_ticket_callbacks, 16);
     ADD_ALL_TESTS(test_shutdown, 7);
+    ADD_ALL_TESTS(test_incorrect_shutdown, 2);
     ADD_ALL_TESTS(test_cert_cb, 6);
     ADD_ALL_TESTS(test_client_cert_cb, 2);
     ADD_ALL_TESTS(test_ca_names, 3);


More information about the openssl-commits mailing list