Skip to content

Commit 09b90e0

Browse files
committed
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 <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> (Merged from #11735)
1 parent fb420af commit 09b90e0

File tree

10 files changed

+88
-16
lines changed

10 files changed

+88
-16
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ OpenSSL 3.0
4242

4343
*Shane Lontis*
4444

45+
* The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced. If that option
46+
is set, an unexpected EOF is ignored, it pretends a close notify was received
47+
instead and so the returned error becomes SSL_ERROR_ZERO_RETURN.
48+
49+
*Dmitry Belyavskiy*
50+
4551
* Deprecated EC_POINT_set_Jprojective_coordinates_GFp() and
4652
EC_POINT_get_Jprojective_coordinates_GFp(). These functions are not widely
4753
used and applications should instead use the

apps/s_client.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ typedef enum OPTION_choice {
576576
OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
577577
OPT_V_ENUM,
578578
OPT_X_ENUM,
579-
OPT_S_ENUM,
579+
OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF,
580580
OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
581581
OPT_DANE_TLSA_DOMAIN,
582582
#ifndef OPENSSL_NO_CT
@@ -718,6 +718,8 @@ const OPTIONS s_client_options[] = {
718718
"Do not send the server name (SNI) extension in the ClientHello"},
719719
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
720720
"Hex dump of all TLS extensions received"},
721+
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
722+
"Do not treat lack of close_notify from a peer as an error"},
721723
#ifndef OPENSSL_NO_OCSP
722724
{"status", OPT_STATUS, '-', "Request certificate status from server"},
723725
#endif
@@ -1001,6 +1003,7 @@ int s_client_main(int argc, char **argv)
10011003
#ifndef OPENSSL_NO_SCTP
10021004
int sctp_label_bug = 0;
10031005
#endif
1006+
int ignore_unexpected_eof = 0;
10041007

10051008
FD_ZERO(&readfds);
10061009
FD_ZERO(&writefds);
@@ -1180,6 +1183,9 @@ int s_client_main(int argc, char **argv)
11801183
if (!args_excert(o, &exc))
11811184
goto end;
11821185
break;
1186+
case OPT_IGNORE_UNEXPECTED_EOF:
1187+
ignore_unexpected_eof = 1;
1188+
break;
11831189
case OPT_PREXIT:
11841190
prexit = 1;
11851191
break;
@@ -1776,6 +1782,9 @@ int s_client_main(int argc, char **argv)
17761782
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
17771783
goto end;
17781784

1785+
if (ignore_unexpected_eof)
1786+
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
1787+
17791788
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
17801789
BIO_printf(bio_err, "Error setting verify params\n");
17811790
ERR_print_errors(bio_err);

apps/s_server.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ typedef enum OPTION_choice {
761761
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
762762
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
763763
OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
764-
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES,
764+
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
765765
OPT_R_ENUM,
766766
OPT_S_ENUM,
767767
OPT_V_ENUM,
@@ -850,6 +850,8 @@ const OPTIONS s_server_options[] = {
850850
"Disable caching and tickets if ephemeral (EC)DH is used"},
851851
{"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
852852
{"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
853+
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
854+
"Do not treat lack of close_notify from a peer as an error"},
853855
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
854856
"Hex dump of all TLS extensions received"},
855857
{"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
@@ -1094,6 +1096,7 @@ int s_server_main(int argc, char *argv[])
10941096
#ifndef OPENSSL_NO_SCTP
10951097
int sctp_label_bug = 0;
10961098
#endif
1099+
int ignore_unexpected_eof = 0;
10971100

10981101
/* Init of few remaining global variables */
10991102
local_argc = argc;
@@ -1667,6 +1670,9 @@ int s_server_main(int argc, char *argv[])
16671670
use_sendfile = 1;
16681671
#endif
16691672
break;
1673+
case OPT_IGNORE_UNEXPECTED_EOF:
1674+
ignore_unexpected_eof = 1;
1675+
break;
16701676
}
16711677
}
16721678
argc = opt_num_rest();
@@ -1867,7 +1873,6 @@ int s_server_main(int argc, char *argv[])
18671873
goto end;
18681874
}
18691875
}
1870-
18711876
#ifndef OPENSSL_NO_SCTP
18721877
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
18731878
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
@@ -1911,6 +1916,9 @@ int s_server_main(int argc, char *argv[])
19111916
SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
19121917
}
19131918

1919+
if (ignore_unexpected_eof)
1920+
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
1921+
19141922
if (max_send_fragment > 0
19151923
&& !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
19161924
BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",

doc/man1/openssl-s_client.pod.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ B<openssl> B<s_client>
7878
[B<-split_send_frag>]
7979
[B<-max_pipelines>]
8080
[B<-read_buf>]
81+
[B<-ignore_unexpected_eof>]
8182
[B<-bugs>]
8283
[B<-comp>]
8384
[B<-no_comp>]
@@ -578,6 +579,15 @@ effect if the buffer size is larger than the size that would otherwise be used
578579
and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
579580
further information).
580581

582+
=item B<-ignore_unexpected_eof>
583+
584+
Some TLS implementations do not send the mandatory close_notify alert on
585+
shutdown. If the application tries to wait for the close_notify alert but the
586+
peer closes the connection without sending it, an error is generated. When this
587+
option is enabled the peer does not need to send the close_notify alert and a
588+
closed connection will be treated as if the close_notify alert was received.
589+
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
590+
581591
=item B<-bugs>
582592

583593
There are several known bugs in SSL and TLS implementations. Adding this

doc/man1/openssl-s_server.pod.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ B<openssl> B<s_server>
4747
[B<-WWW>]
4848
[B<-http_server_binmode>]
4949
[B<-no_ca_names>]
50+
[B<-ignore_unexpected_eof>]
5051
[B<-servername>]
5152
[B<-servername_fatal>]
5253
[B<-tlsextdebug>]
@@ -420,6 +421,15 @@ Disable TLS Extension CA Names. You may want to disable it for security reasons
420421
or for compatibility with some Windows TLS implementations crashing when this
421422
extension is larger than 1024 bytes.
422423

424+
=item B<-ignore_unexpected_eof>
425+
426+
Some TLS implementations do not send the mandatory close_notify alert on
427+
shutdown. If the application tries to wait for the close_notify alert but the
428+
peer closes the connection without sending it, an error is generated. When this
429+
option is enabled the peer does not need to send the close_notify alert and a
430+
closed connection will be treated as if the close_notify alert was received.
431+
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
432+
423433
=item B<-id_prefix> I<val>
424434

425435
Generate SSL/TLS session IDs prefixed by I<val>. This is mostly useful

doc/man3/SSL_CTX_set_options.pod

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,20 @@ not propose, and servers will not accept the extension.
217217
Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
218218
messages, and ignore renegotiation requests via ClientHello.
219219

220+
=item SSL_OP_IGNORE_UNEXPECTED_EOF
221+
222+
Some TLS implementations do not send the mandatory close_notify alert on
223+
shutdown. If the application tries to wait for the close_notify alert but the
224+
peer closes the connection without sending it, an error is generated. When this
225+
option is enabled the peer does not need to send the close_notify alert and a
226+
closed connection will be treated as if the close_notify alert was received.
227+
228+
You should only enable this option if the protocol running over TLS
229+
can detect a truncation attack itself, and that the application is checking for
230+
that truncation attack.
231+
232+
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
233+
220234
=item SSL_OP_ALLOW_NO_DHE_KEX
221235

222236
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.
367381

368382
=head1 SEE ALSO
369383

370-
L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>,
384+
L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>, L<SSL_shutdown(3)>
371385
L<SSL_CTX_set_tmp_dh_callback(3)>,
372386
L<SSL_CTX_set_min_proto_version(3)>,
373387
L<openssl-dhparam(1)>
@@ -380,7 +394,8 @@ OpenSSL 0.9.8m.
380394
The B<SSL_OP_PRIORITIZE_CHACHA> and B<SSL_OP_NO_RENEGOTIATION> options
381395
were added in OpenSSL 1.1.1.
382396

383-
The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> option was added in OpenSSL 3.0.
397+
The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> and B<SSL_OP_IGNORE_UNEXPECTED_EOF>
398+
options were added in OpenSSL 3.0.
384399

385400
=head1 COPYRIGHT
386401

doc/man3/SSL_get_error.pod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ other OpenSSL function calls should appear in between. The current
2525
thread's error queue must be empty before the TLS/SSL I/O operation is
2626
attempted, or SSL_get_error() will not work reliably.
2727

28+
=head1 NOTES
29+
30+
Some TLS implementations do not send a close_notify alert on shutdown.
31+
32+
On an unexpected EOF, versions before OpenSSL 3.0 returned
33+
B<SSL_ERROR_SYSCALL>, nothing was added to the error stack, and errno was 0.
34+
Since OpenSSL 3.0 the returned error is B<SSL_ERROR_SSL> with a meaningful
35+
error on the error stack.
36+
2837
=head1 RETURN VALUES
2938

3039
The following return values can currently occur:
@@ -44,6 +53,9 @@ No more data can be read.
4453
Note that B<SSL_ERROR_ZERO_RETURN> does not necessarily
4554
indicate that the underlying transport has been closed.
4655

56+
This error can also appear when the option B<SSL_OP_IGNORE_UNEXPECTED_EOF>
57+
is set. See L<SSL_CTX_set_options(3)> for more details.
58+
4759
=item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
4860

4961
The operation did not complete and can be retried later.

doc/man3/SSL_shutdown.pod

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,10 @@ message, otherwise an unexpected EOF will be reported.
8383
There are implementations that do not send the required close_notify alert.
8484
If there is a need to communicate with such an implementation, and it's clear
8585
that all data has been received, do not wait for the peer's close_notify alert.
86-
Waiting for the close_notify alert when the peer just closes the connection will
87-
result in an error being generated.
86+
Waiting for the close_notify alert when the peer just closes the connection
87+
will result in an error being generated.
88+
The error can be ignored using the B<SSL_OP_IGNORE_UNEXPECTED_EOF>.
89+
For more information see L<SSL_CTX_set_options(3)>.
8890

8991
=head2 First to close the connection
9092

@@ -159,7 +161,7 @@ It can also occur when not all data was read using SSL_read().
159161

160162
L<SSL_get_error(3)>, L<SSL_connect(3)>,
161163
L<SSL_accept(3)>, L<SSL_set_shutdown(3)>,
162-
L<SSL_CTX_set_quiet_shutdown(3)>,
164+
L<SSL_CTX_set_quiet_shutdown(3)>, L<SSL_CTX_set_options(3)>
163165
L<SSL_clear(3)>, L<SSL_free(3)>,
164166
L<ssl(7)>, L<bio(7)>
165167

include/openssl/ssl.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,9 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
325325
/* Allow initial connection to servers that don't support RI */
326326
# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U
327327

328-
/* Reserved value (until OpenSSL 3.0.0) 0x00000008U */
329328
# define SSL_OP_TLSEXT_PADDING 0x00000010U
330-
/* Reserved value (until OpenSSL 3.0.0) 0x00000020U */
331329
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U
332-
/*
333-
* Reserved value (until OpenSSL 3.0.0) 0x00000080U
334-
* Reserved value (until OpenSSL 3.0.0) 0x00000100U
335-
*/
330+
# define SSL_OP_IGNORE_UNEXPECTED_EOF 0x00000080U
336331

337332
# define SSL_OP_DISABLE_TLSEXT_CA_NAMES 0x00000200U
338333

ssl/record/rec_layer_s3.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,13 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
303303
if (ret <= 0
304304
&& !BIO_should_retry(s->rbio)
305305
&& BIO_eof(s->rbio)) {
306-
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_READ_N,
307-
SSL_R_UNEXPECTED_EOF_WHILE_READING);
306+
if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
307+
SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN);
308+
s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
309+
} else {
310+
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_READ_N,
311+
SSL_R_UNEXPECTED_EOF_WHILE_READING);
312+
}
308313
}
309314
} else {
310315
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N,

0 commit comments

Comments
 (0)