Skip to content

Commit

Permalink
Introducing option SSL_OP_IGNORE_UNEXPECTED_EOF
Browse files Browse the repository at this point in the history
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 #11735)
  • Loading branch information
beldmit committed May 19, 2020
1 parent fb420af commit 09b90e0
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion apps/s_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 10 additions & 2 deletions apps/s_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"},
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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",
Expand Down
10 changes: 10 additions & 0 deletions doc/man1/openssl-s_client.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -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>]
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions doc/man1/openssl-s_server.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -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>]
Expand Down Expand Up @@ -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
Expand Down
19 changes: 17 additions & 2 deletions doc/man3/SSL_CTX_set_options.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)>
Expand All @@ -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

Expand Down
12 changes: 12 additions & 0 deletions doc/man3/SSL_get_error.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.
Expand Down
8 changes: 5 additions & 3 deletions doc/man3/SSL_shutdown.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)>

Expand Down
7 changes: 1 addition & 6 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 7 additions & 2 deletions ssl/record/rec_layer_s3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 09b90e0

Please sign in to comment.