From 5ce93e8710d3acc1a13a7c2bf96e5e5226f8714d Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 17 Jan 2020 17:39:19 +0000 Subject: [PATCH 1/2] Detect EOF while reading in libssl If we hit an EOF while reading in libssl then we will report an error back to the application (SSL_ERROR_SYSCALL) but errno will be 0. We add an error to the stack (which means we instead return SSL_ERROR_SSL) and therefore give a hint as to what went wrong. Contains a partial fix for #10880 --- crypto/bio/bss_sock.c | 5 +++++ crypto/err/openssl.txt | 3 ++- include/openssl/bio.h | 1 + include/openssl/sslerr.h | 3 ++- ssl/record/rec_layer_s3.c | 6 ++++++ ssl/ssl_err.c | 4 +++- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c index da818ca90e813..3ad989adf21f1 100644 --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -101,6 +101,8 @@ static int sock_read(BIO *b, char *out, int outl) if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_read(b); + else if (ret == 0) + b->flags |= BIO_FLAGS_IN_EOF; } } return ret; @@ -151,6 +153,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = 1; break; + case BIO_CTRL_EOF: + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + break; default: ret = 0; break; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index e4b8ebf228e6c..1d7fa2d0bc1e2 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -2849,6 +2849,7 @@ SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data +SSL_R_UNEXPECTED_EOF_WHILE_READING:294:unexpected eof while reading SSL_R_UNEXPECTED_MESSAGE:244:unexpected message SSL_R_UNEXPECTED_RECORD:245:unexpected record SSL_R_UNINITIALIZED:276:uninitialized diff --git a/include/openssl/bio.h b/include/openssl/bio.h index e1fddfb7969d6..9e2bcddc3e19d 100644 --- a/include/openssl/bio.h +++ b/include/openssl/bio.h @@ -169,6 +169,7 @@ extern "C" { */ # define BIO_FLAGS_MEM_RDONLY 0x200 # define BIO_FLAGS_NONCLEAR_RST 0x400 +# define BIO_FLAGS_IN_EOF 0x800 typedef union bio_addr_st BIO_ADDR; typedef struct bio_addrinfo_st BIO_ADDRINFO; diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index 3d6850dea36e2..b6cac4f5f55b1 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -733,6 +733,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 # define SSL_R_UNEXPECTED_CCS_MESSAGE 262 # define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178 +# define SSL_R_UNEXPECTED_EOF_WHILE_READING 294 # define SSL_R_UNEXPECTED_MESSAGE 244 # define SSL_R_UNEXPECTED_RECORD 245 # define SSL_R_UNINITIALIZED 276 diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 9e23b4fb3b5b9..d5d511f48af73 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -296,6 +296,12 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, ret = BIO_read(s->rbio, pkt + len + left, max - left); if (ret >= 0) bioread = ret; + 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); + } } else { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET); diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 4b12ed1485d98..a0c7b79659d4d 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -1205,6 +1205,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "unexpected ccs message"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA), "unexpected end of early data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_EOF_WHILE_READING), + "unexpected eof while reading"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"}, From f24b8f4d258a282deaa7b67f012f2c620f7309cf Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 24 Jan 2020 16:07:51 +0000 Subject: [PATCH 2/2] Teach more BIOs how to handle BIO_CTRL_EOF --- crypto/bio/bss_acpt.c | 7 ++++++- crypto/bio/bss_conn.c | 5 +++++ crypto/bio/bss_fd.c | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index c6a2c388914bb..c9acf62dea6cc 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -527,7 +527,12 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_DUP: break; - + case BIO_CTRL_EOF: + if (b->next_bio == NULL) + ret = 0; + else + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; default: ret = 0; break; diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index ad299ac716ef2..bb5049fb5939d 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -316,6 +316,8 @@ static int conn_read(BIO *b, char *out, int outl) if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_read(b); + else if (ret == 0) + b->flags |= BIO_FLAGS_IN_EOF; } } return ret; @@ -495,6 +497,9 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) *fptr = data->info_callback; } break; + case BIO_CTRL_EOF: + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + break; default: ret = 0; break; diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c index 894b3ff9e7230..76ca0bd887f7c 100644 --- a/crypto/bio/bss_fd.c +++ b/crypto/bio/bss_fd.c @@ -123,6 +123,8 @@ static int fd_read(BIO *b, char *out, int outl) if (ret <= 0) { if (BIO_fd_should_retry(ret)) BIO_set_retry_read(b); + else if (ret == 0) + b->flags |= BIO_FLAGS_IN_EOF; } } return ret; @@ -186,6 +188,9 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = 1; break; + case BIO_CTRL_EOF: + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + break; default: ret = 0; break;