From: Timo Sirainen Date: Fri, 24 Sep 2021 16:16:43 +0000 (+0300) Subject: lib-ssl-iostream: Fix error handling if parent iostream fails X-Git-Tag: 2.3.18~291 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a9d1aa7b61bca93ab3722a88b8fd06240188b75;p=thirdparty%2Fdovecot%2Fcore.git lib-ssl-iostream: Fix error handling if parent iostream fails 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. --- diff --git a/src/lib-ssl-iostream/iostream-openssl.c b/src/lib-ssl-iostream/iostream-openssl.c index 5d11526f11..ab5f3dd819 100644 --- a/src/lib-ssl-iostream/iostream-openssl.c +++ b/src/lib-ssl-iostream/iostream-openssl.c @@ -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) { diff --git a/src/lib-ssl-iostream/iostream-openssl.h b/src/lib-ssl-iostream/iostream-openssl.h index e5f5faac35..70f9649fc7 100644 --- a/src/lib-ssl-iostream/iostream-openssl.h +++ b/src/lib-ssl-iostream/iostream-openssl.h @@ -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 diff --git a/src/lib-ssl-iostream/istream-openssl.c b/src/lib-ssl-iostream/istream-openssl.c index 32ad701e10..962d1b9053 100644 --- a/src/lib-ssl-iostream/istream-openssl.c +++ b/src/lib-ssl-iostream/istream-openssl.c @@ -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; diff --git a/src/lib-ssl-iostream/ostream-openssl.c b/src/lib-ssl-iostream/ostream-openssl.c index 68ddcf3afa..6ee9d3a11f 100644 --- a/src/lib-ssl-iostream/ostream-openssl.c +++ b/src/lib-ssl-iostream/ostream-openssl.c @@ -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); }