]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-ssl-iostream: Fix error handling if parent iostream fails
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 24 Sep 2021 16:16:43 +0000 (19:16 +0300)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 30 Sep 2021 17:08:11 +0000 (17:08 +0000)
Expand out and remove openssl_iostream_more(). It could have returned
errors to two different locations depending on whether the failure came
from SSL handshake or parent iostream.

src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/iostream-openssl.h
src/lib-ssl-iostream/istream-openssl.c
src/lib-ssl-iostream/ostream-openssl.c

index 5d11526f110b253387ae99c4f9cbe0f60989faac..ab5f3dd819599365253b2c67faee9e6b6ce7f841 100644 (file)
@@ -372,7 +372,10 @@ void openssl_iostream_shutdown(struct ssl_iostream *ssl_io)
                   the error queue */
                openssl_iostream_clear_errors();
        }
-       (void)openssl_iostream_more(ssl_io, OPENSSL_IOSTREAM_SYNC_TYPE_WRITE);
+       if (ssl_io->handshaked) {
+               (void)openssl_iostream_bio_sync(ssl_io,
+                       OPENSSL_IOSTREAM_SYNC_TYPE_WRITE);
+       }
        (void)o_stream_flush(ssl_io->plain_output);
        /* close the plain i/o streams, because their fd may be closed soon,
           but we may still keep this ssl-iostream referenced until later. */
@@ -540,20 +543,6 @@ int openssl_iostream_bio_sync(struct ssl_iostream *ssl_io,
        return ret;
 }
 
-int openssl_iostream_more(struct ssl_iostream *ssl_io,
-                         enum openssl_iostream_sync_type type)
-{
-       int ret;
-
-       if (!ssl_io->handshaked) {
-               if ((ret = ssl_iostream_handshake(ssl_io)) <= 0)
-                       return ret;
-       }
-       if (openssl_iostream_bio_sync(ssl_io, type) < 0)
-               return -1;
-       return 1;
-}
-
 static void openssl_iostream_closed(struct ssl_iostream *ssl_io)
 {
        if (ssl_io->plain_stream_errno != 0) {
index e5f5faac3583f2ff7163ac474c0dbc4ddeca84d8..70f9649fc7633014196919957de8d9aa7244dce1 100644 (file)
@@ -104,11 +104,6 @@ int openssl_min_protocol_to_options(const char *min_protocol, long *opt_r,
    occurred. */
 int openssl_iostream_bio_sync(struct ssl_iostream *ssl_io,
                              enum openssl_iostream_sync_type type);
-/* Call when there's more data available in plain_input/plain_output.
-   Returns 1 if it's ok to continue with SSL_read/SSL_write, 0 if not
-   (still handshaking), -1 if error occurred. */
-int openssl_iostream_more(struct ssl_iostream *ssl_io,
-                         enum openssl_iostream_sync_type type);
 
 /* Returns 1 if the operation should be retried (we read/wrote more data),
    0 if the operation should retried later once more data has been
index 32ad701e102247a269d72a9ac1a47fc81e4e3073..962d1b9053dee93d88683074d30c68b836538970 100644 (file)
@@ -43,17 +43,26 @@ static ssize_t i_stream_ssl_read_real(struct istream_private *stream)
                return -1;
        }
 
-       ret = openssl_iostream_more(ssl_io,
-               OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE);
-       if (ret <= 0) {
-               if (ret < 0) {
-                       /* handshake failed */
-                       i_assert(errno != 0);
-                       io_stream_set_error(&stream->iostream,
-                                           "%s", ssl_io->last_error);
-                       stream->istream.stream_errno = errno;
+       if (!ssl_io->handshaked) {
+               if ((ret = ssl_iostream_handshake(ssl_io)) <= 0) {
+                       if (ret < 0) {
+                               /* handshake failed */
+                               i_assert(errno != 0);
+                               io_stream_set_error(&stream->iostream,
+                                                   "%s", ssl_io->last_error);
+                               stream->istream.stream_errno = errno;
+                       }
+                       return ret;
                }
-               return ret;
+       }
+       if (openssl_iostream_bio_sync(ssl_io,
+                       OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE) < 0) {
+               i_assert(ssl_io->plain_stream_errno != 0 &&
+                        ssl_io->plain_stream_errstr != NULL);
+               io_stream_set_error(&stream->iostream,
+                                   "%s", ssl_io->plain_stream_errstr);
+               stream->istream.stream_errno = ssl_io->plain_stream_errno;
+               return -1;
        }
        if (!i_stream_try_alloc(stream, 1, &size))
                return -2;
index 68ddcf3afa12b8449db2948fe5b9335a05adde0e..6ee9d3a11fb0188060d3adf5166426b87728c5ec 100644 (file)
@@ -146,16 +146,30 @@ static int o_stream_ssl_flush(struct ostream_private *stream)
        struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
        struct ssl_iostream *ssl_io = sstream->ssl_io;
        struct ostream *plain_output = ssl_io->plain_output;
-       int ret;
-
-       if ((ret = openssl_iostream_more(ssl_io,
-                               OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE)) < 0) {
-               /* handshake failed */
-               io_stream_set_error(&stream->iostream, "%s",
-                                   ssl_io->last_error);
-               stream->ostream.stream_errno = errno;
-       } else if (ret > 0 && sstream->buffer != NULL &&
-                  sstream->buffer->used > 0) {
+       int ret = 1;
+
+       if (!ssl_io->handshaked) {
+               if ((ret = ssl_iostream_handshake(ssl_io)) < 0) {
+                       /* handshake failed */
+                       i_assert(errno != 0);
+                       io_stream_set_error(&stream->iostream,
+                                           "%s", ssl_io->last_error);
+                       stream->ostream.stream_errno = errno;
+                       return ret;
+               }
+       }
+       if (ret > 0 &&
+           openssl_iostream_bio_sync(
+               ssl_io, OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE) < 0) {
+               i_assert(ssl_io->plain_stream_errno != 0 &&
+                        ssl_io->plain_stream_errstr != NULL);
+               io_stream_set_error(&stream->iostream,
+                                   "%s", ssl_io->plain_stream_errstr);
+               stream->ostream.stream_errno = ssl_io->plain_stream_errno;
+               return -1;
+       }
+
+       if (ret > 0 && sstream->buffer != NULL && sstream->buffer->used > 0) {
                /* we can try to send some of our buffered data */
                ret = o_stream_ssl_flush_buffer(sstream);
        }