From: Stephan Bosch Date: Fri, 16 Apr 2021 12:52:34 +0000 (+0200) Subject: lib-ssl-iostream: ostream-openssl - Call SSL_shutdown() once stream is finished and... X-Git-Tag: 2.3.18~285 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f4a532bd10f85d9a78f7a5804085ecffaa51709;p=thirdparty%2Fdovecot%2Fcore.git lib-ssl-iostream: ostream-openssl - Call SSL_shutdown() once stream is finished and buffer is empty. --- diff --git a/src/lib-ssl-iostream/ostream-openssl.c b/src/lib-ssl-iostream/ostream-openssl.c index 6ee9d3a11f..8434a9b7cc 100644 --- a/src/lib-ssl-iostream/ostream-openssl.c +++ b/src/lib-ssl-iostream/ostream-openssl.c @@ -10,6 +10,8 @@ struct ssl_ostream { struct ostream_private ostream; struct ssl_iostream *ssl_io; buffer_t *buffer; + + bool shutdown:1; }; static void @@ -101,6 +103,8 @@ static int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream) size_t pos = 0; int ret = 1; + i_assert(!sstream->shutdown); + while (pos < sstream->buffer->used) { /* we're writing plaintext data to OpenSSL, which it encrypts and writes to bio_int's buffer. ssl_iostream_bio_sync() @@ -174,6 +178,21 @@ static int o_stream_ssl_flush(struct ostream_private *stream) ret = o_stream_ssl_flush_buffer(sstream); } + /* Stream is finished; shutdown the SSL write direction once our buffer + is empty. */ + if (stream->finished && !sstream->shutdown && ret >= 0 && + (sstream->buffer == NULL || sstream->buffer->used == 0)) { + sstream->shutdown = TRUE; + if (SSL_shutdown(ssl_io->ssl) < 0) { + io_stream_set_error( + &sstream->ostream.iostream, "%s", + t_strdup_printf("SSL_shutdown() failed: %s", + openssl_iostream_error())); + sstream->ostream.ostream.stream_errno = EIO; + ret = -1; + } + } + if (ret == 0 && ssl_io->want_read) { /* we need to read more data until we can continue. */ o_stream_set_flush_pending(plain_output, FALSE); @@ -196,6 +215,8 @@ o_stream_ssl_sendv(struct ostream_private *stream, struct ssl_ostream *sstream = (struct ssl_ostream *)stream; size_t bytes_sent = 0; + i_assert(!sstream->shutdown); + bytes_sent = o_stream_ssl_buffer(sstream, iov, iov_count, bytes_sent); if (sstream->ssl_io->handshaked && sstream->buffer->used == bytes_sent) {