From 416e244b31c75b1b4d36788c73999deb383f28e3 Mon Sep 17 00:00:00 2001 From: Trevor Perrin <5209956+trevorperrin@users.noreply.github.com> Date: Thu, 26 Apr 2018 15:50:32 -0500 Subject: [PATCH] Clear SSL Error Queue The OpenSSL documentation states that the error queue for the current thread needs to be emptied prior to the next TLS/SSL I/O operation, or the call to SSL_get_error() will not be reliable. --- src/linux_tcp/openssl.cpp | 13 +++++++++++++ src/linux_tcp/openssl.h | 2 ++ src/linux_tcp/sslconnected.h | 19 ++++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/linux_tcp/openssl.cpp b/src/linux_tcp/openssl.cpp index 2afc378..18be0cd 100644 --- a/src/linux_tcp/openssl.cpp +++ b/src/linux_tcp/openssl.cpp @@ -310,6 +310,19 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type) return func(ssl, file, type); } +/** + * Clear the SSL error queue + * @return void + */ +void ERR_clear_error() +{ + // create a function + static Function func(handle, "ERR_clear_error"); + + // call the openssl function + return func(); +} + /** * End of namespace */ diff --git a/src/linux_tcp/openssl.h b/src/linux_tcp/openssl.h index e3461e2..c8d7694 100644 --- a/src/linux_tcp/openssl.h +++ b/src/linux_tcp/openssl.h @@ -18,6 +18,7 @@ * Dependencies */ #include +#include /** * Begin of namespace @@ -49,6 +50,7 @@ void SSL_set_connect_state(SSL *ssl); void SSL_CTX_free(SSL_CTX *ctx); void SSL_free(SSL *ssl); long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); +void ERR_clear_error(void); /** * End of namespace diff --git a/src/linux_tcp/sslconnected.h b/src/linux_tcp/sslconnected.h index f745e36..8ff83bc 100644 --- a/src/linux_tcp/sslconnected.h +++ b/src/linux_tcp/sslconnected.h @@ -270,8 +270,12 @@ private: // we may have to repeat the operation on failure if (result > 0) continue; + // Check for error and clear the error queue before the next TLS/SSL I/O operation + auto error = OpenSSL::SSL_get_error(_ssl, result); + OpenSSL::ERR_clear_error(); + // the operation failed, we may have to repeat our call - return repeat(monitor, state_sending, OpenSSL::SSL_get_error(_ssl, result)); + return repeat(monitor, state_sending, error); } while (_out && !readable); @@ -297,8 +301,14 @@ private: auto result = _in.receivefrom(_ssl, _connection->expected()); // if this is a failure, we are going to repeat the operation - if (result <= 0) return repeat(monitor, state_receiving, OpenSSL::SSL_get_error(_ssl, result)); - + if (result <= 0) + { + // Check for error and clear the error queue before the next TLS/SSL I/O operation + auto error = OpenSSL::SSL_get_error(_ssl, result); + OpenSSL::ERR_clear_error(); + + return repeat(monitor, state_receiving, error); + } // go process the received data auto *nextstate = parse(monitor, result); @@ -419,6 +429,9 @@ public: { // error was returned, so we must investigate what is going on auto error = OpenSSL::SSL_get_error(_ssl, result); + + // clear the error queue before the next TLS/SSL I/O operation + OpenSSL::ERR_clear_error(); // get the next state given the error auto *nextstate = repeat(monitor, state_sending, error);