From e39ca5b012254a16822363e0860a2ce0755f9312 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Thu, 8 Mar 2018 13:36:56 +0100 Subject: [PATCH] ssl connection fixes --- examples/libev.cpp | 7 ++++- src/linux_tcp/sslconnected.h | 9 ++++--- src/linux_tcp/sslhandshake.h | 24 ++++++++--------- src/linux_tcp/sslshutdown.h | 51 ++++++++++++++++++++---------------- 4 files changed, 53 insertions(+), 38 deletions(-) diff --git a/examples/libev.cpp b/examples/libev.cpp index 2868e29..2188637 100644 --- a/examples/libev.cpp +++ b/examples/libev.cpp @@ -14,6 +14,7 @@ #include #include #include +#include /** * Custom handler @@ -66,7 +67,11 @@ int main() MyHandler handler(loop); // init the SSL library -// SSL_library_init(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + SSL_library_init(); +#else + OPENSSL_init_ssl(0, NULL); +#endif // make a connection AMQP::Address address("amqp://guest:guest@localhost/"); diff --git a/src/linux_tcp/sslconnected.h b/src/linux_tcp/sslconnected.h index 6b773a4..8f34f76 100644 --- a/src/linux_tcp/sslconnected.h +++ b/src/linux_tcp/sslconnected.h @@ -139,11 +139,14 @@ private: } else if (_closed) { + // start the state that closes the connection + auto *nextstate = new SslShutdown(_connection, _socket, std::move(_ssl), _finalized, _handler); + // we forget the current socket to prevent that it gets destructed _socket = -1; - // start the state that closes the connection - return new SslShutdown(_connection, _socket, std::move(_ssl), _finalized, _handler); + // report the next state + return nextstate; } else { @@ -263,7 +266,7 @@ public: { // tell the handler to monitor the socket if there is an out _handler->monitor(_connection, _socket, _state == state_sending ? readable | writable : readable); - } + } /** * Destructor diff --git a/src/linux_tcp/sslhandshake.h b/src/linux_tcp/sslhandshake.h index ec082a2..b593381 100644 --- a/src/linux_tcp/sslhandshake.h +++ b/src/linux_tcp/sslhandshake.h @@ -122,7 +122,7 @@ public: _ssl(SslContext(OpenSSL::TLS_client_method())), _socket(socket), _out(std::move(buffer)) - { + { // we will be using the ssl context as a client OpenSSL::SSL_set_connect_state(_ssl); @@ -168,13 +168,13 @@ public: // start the ssl handshake int result = OpenSSL::SSL_do_handshake(_ssl); - + // if the connection succeeds, we can move to the ssl-connected state if (result == 1) return nextstate(new SslConnected(_connection, _socket, std::move(_ssl), std::move(_out), _handler)); // error was returned, so we must investigate what is going on auto error = OpenSSL::SSL_get_error(_ssl, result); - + // check the error switch (error) { case SSL_ERROR_WANT_READ: return proceed(readable); @@ -217,15 +217,15 @@ public: auto error = OpenSSL::SSL_get_error(_ssl, result); // check the error - switch (error) - { - // if openssl reports that socket readability or writability is needed, - // we wait for that until this situation is reached - case SSL_ERROR_WANT_READ: wait.readable(); break; - case SSL_ERROR_WANT_WRITE: wait.active(); break; - - // something is wrong, we proceed to the next state - default: return reportError(monitor); + switch (error) { + + // if openssl reports that socket readability or writability is needed, + // we wait for that until this situation is reached + case SSL_ERROR_WANT_READ: wait.readable(); break; + case SSL_ERROR_WANT_WRITE: wait.active(); break; + + // something is wrong, we proceed to the next state + default: return reportError(monitor); } } } diff --git a/src/linux_tcp/sslshutdown.h b/src/linux_tcp/sslshutdown.h index 67da802..7083ea1 100644 --- a/src/linux_tcp/sslshutdown.h +++ b/src/linux_tcp/sslshutdown.h @@ -42,6 +42,28 @@ private: bool _finalized; + /** + * Close the socket + * @return bool + */ + bool close() + { + // skip if already closed + if (_socket < 0) return false; + + // we're no longer interested in events + _handler->monitor(_connection, _socket, 0); + + // close the socket + ::close(_socket); + + // forget the socket + _socket = -1; + + // done + return true; + } + /** * Report an error * @param monitor object to check if connection still exists @@ -50,10 +72,7 @@ private: TcpState *reporterror(const Monitor &monitor) { // close the socket - close(_socket); - - // forget the socket - _socket = -1; + close(); // if we have already told user space that connection is gone if (_finalized) return new TcpClosed(this); @@ -76,14 +95,8 @@ private: */ TcpState *proceed(const Monitor &monitor) { - // we're no longer interested in events - _handler->monitor(_connection, _socket, 0); - // close the socket - close(_socket); - - // forget the socket - _socket = -1; + close(); // if we have already told user space that connection is gone if (_finalized) return new TcpClosed(this); @@ -108,7 +121,7 @@ private: { // error was returned, so we must investigate what is going on auto error = OpenSSL::SSL_get_error(_ssl, result); - + // check the error switch (error) { case SSL_ERROR_WANT_READ: @@ -143,8 +156,8 @@ public: _socket(socket), _finalized(finalized) { - // tell the handler to monitor the socket if there is an out - _handler->monitor(_connection, _socket, readable); + // wait until the socket is accessible + _handler->monitor(_connection, _socket, readable | writable); } /** @@ -152,14 +165,8 @@ public: */ virtual ~SslShutdown() noexcept { - // skip if socket is already gond - if (_socket < 0) return; - - // we no longer have to monitor the socket - _handler->monitor(_connection, _socket, 0); - // close the socket - close(_socket); + close(); } /** @@ -182,7 +189,7 @@ public: // close the connection auto result = OpenSSL::SSL_shutdown(_ssl); - + // if this is a success, we can proceed with the event loop if (result > 0) return proceed(monitor);