]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-ssl-iostream: ostream-openssl - Call SSL_shutdown() once stream is finished and...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 16 Apr 2021 12:52:34 +0000 (14:52 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 30 Sep 2021 17:08:11 +0000 (17:08 +0000)
src/lib-ssl-iostream/ostream-openssl.c

index 6ee9d3a11fb0188060d3adf5166426b87728c5ec..8434a9b7ccada3ec8f02ca2426cde6f2106c9bc9 100644 (file)
@@ -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) {