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@openssl.org>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/11735)
*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
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
"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
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (!args_excert(o, &exc))
goto end;
break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
case OPT_PREXIT:
prexit = 1;
break;
&& 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);
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,
"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"},
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
/* Init of few remaining global variables */
local_argc = argc;
use_sendfile = 1;
#endif
break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
}
}
argc = opt_num_rest();
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);
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",
[B<-split_send_frag>]
[B<-max_pipelines>]
[B<-read_buf>]
+[B<-ignore_unexpected_eof>]
[B<-bugs>]
[B<-comp>]
[B<-no_comp>]
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
[B<-WWW>]
[B<-http_server_binmode>]
[B<-no_ca_names>]
+[B<-ignore_unexpected_eof>]
[B<-servername>]
[B<-servername_fatal>]
[B<-tlsextdebug>]
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
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
=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)>
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
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:
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.
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
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)>
/* 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
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,