From 29701b4db5e43d1f1f40e78d9515d082f832ca64 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 13 Sep 2018 18:05:31 +0200 Subject: [PATCH] Add ApiListener#tls_handshake_timeout option This allows to specify the previously hardcoded timeout of 10s. refs #6517 --- doc/09-object-types.md | 1 + lib/base/configuration.cpp | 11 +++++++++++ lib/base/configuration.hpp | 4 ++++ lib/base/configuration.ti | 5 +++++ lib/base/tlsstream.cpp | 7 ++++--- lib/remote/apilistener.cpp | 18 ++++++++++++++++++ lib/remote/apilistener.hpp | 4 ++++ lib/remote/apilistener.ti | 6 ++++++ 8 files changed, 53 insertions(+), 3 deletions(-) diff --git a/doc/09-object-types.md b/doc/09-object-types.md index fffad0000..6dda8c91d 100644 --- a/doc/09-object-types.md +++ b/doc/09-object-types.md @@ -64,6 +64,7 @@ Configuration Attributes: max\_anonymous\_clients | Number | **Optional.** Limit the number of anonymous client connections (not configured endpoints and signing requests). cipher\_list | String | **Optional.** Cipher list that is allowed. For a list of available ciphers run `openssl ciphers`. Defaults to `ALL:!LOW:!WEAK:!MEDIUM:!EXP:!NULL`. tls\_protocolmin | String | **Optional.** Minimum TLS protocol version. Must be one of `TLSv1`, `TLSv1.1` or `TLSv1.2`. Defaults to `TLSv1`. + tls\_handshake\_timeout | Number | **Optional.** TLS Handshake timeout. Defaults to `10s`. access\_control\_allow\_origin | Array | **Optional.** Specifies an array of origin URLs that may access the API. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin) access\_control\_allow\_credentials | Boolean | **Deprecated.** Indicates whether or not the actual request can be made using credentials. Defaults to `true`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials) access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers) diff --git a/lib/base/configuration.cpp b/lib/base/configuration.cpp index 31f691265..10d33645a 100644 --- a/lib/base/configuration.cpp +++ b/lib/base/configuration.cpp @@ -49,6 +49,7 @@ String Configuration::RunAsGroup; String Configuration::RunAsUser; String Configuration::SpoolDir; String Configuration::StatePath; +double Configuration::TlsHandshakeTimeout{10}; String Configuration::VarsPath; String Configuration::ZonesDir; @@ -309,6 +310,16 @@ void Configuration::SetStatePath(const String& val, bool suppress_events, const HandleUserWrite("StatePath", &Configuration::StatePath, val, m_ReadOnly); } +double Configuration::GetTlsHandshakeTimeout() const +{ + return Configuration::TlsHandshakeTimeout; +} + +void Configuration::SetTlsHandshakeTimeout(double val, bool suppress_events, const Value& cookie) +{ + HandleUserWrite("TlsHandshakeTimeout", &Configuration::TlsHandshakeTimeout, val, m_ReadOnly); +} + String Configuration::GetVarsPath() const { return Configuration::VarsPath; diff --git a/lib/base/configuration.hpp b/lib/base/configuration.hpp index 02a516b87..2a57bbbd8 100644 --- a/lib/base/configuration.hpp +++ b/lib/base/configuration.hpp @@ -108,6 +108,9 @@ public: String GetStatePath() const override; void SetStatePath(const String& value, bool suppress_events = false, const Value& cookie = Empty) override; + double GetTlsHandshakeTimeout() const override; + void SetTlsHandshakeTimeout(double value, bool suppress_events = false, const Value& cookie = Empty) override; + String GetVarsPath() const override; void SetVarsPath(const String& value, bool suppress_events = false, const Value& cookie = Empty) override; @@ -151,6 +154,7 @@ public: static String RunAsUser; static String SpoolDir; static String StatePath; + static double TlsHandshakeTimeout; static String VarsPath; static String ZonesDir; diff --git a/lib/base/configuration.ti b/lib/base/configuration.ti index abcba7d55..b15d5b21e 100644 --- a/lib/base/configuration.ti +++ b/lib/base/configuration.ti @@ -146,6 +146,11 @@ abstract class Configuration set; }; + [config, no_storage, virtual] double TlsHandshakeTimeout { + get; + set; + }; + [config, no_storage, virtual] String VarsPath { get; set; diff --git a/lib/base/tlsstream.cpp b/lib/base/tlsstream.cpp index 33d72d465..afb46b781 100644 --- a/lib/base/tlsstream.cpp +++ b/lib/base/tlsstream.cpp @@ -21,6 +21,8 @@ #include "base/utility.hpp" #include "base/exception.hpp" #include "base/logger.hpp" +#include "base/configuration.hpp" +#include "base/convert.hpp" #include #ifndef _WIN32 @@ -315,14 +317,13 @@ void TlsStream::Handshake() m_CurrentAction = TlsActionHandshake; ChangeEvents(POLLOUT); - boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(TLS_TIMEOUT_SECONDS); + boost::system_time const timeout = boost::get_system_time() + boost::posix_time::milliseconds(long(Configuration::TlsHandshakeTimeout * 1000)); while (!m_HandshakeOK && !m_ErrorOccurred && !m_Eof && timeout > boost::get_system_time()) m_CV.timed_wait(lock, timeout); - // We should _NOT_ (underline, bold, itallic and wordart) throw an exception for a timeout. if (timeout < boost::get_system_time()) - BOOST_THROW_EXCEPTION(std::runtime_error("Timeout during handshake.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Timeout was reached (" + Convert::ToString(Configuration::TlsHandshakeTimeout) + ") during TLS handshake.")); if (m_Eof) BOOST_THROW_EXCEPTION(std::runtime_error("Socket was closed during TLS handshake.")); diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index c9cbd3867..4605df364 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -89,6 +89,16 @@ String ApiListener::GetDefaultCaPath() return GetCertsDir() + "/ca.crt"; } +double ApiListener::GetTlsHandshakeTimeout() const +{ + return Configuration::TlsHandshakeTimeout; +} + +void ApiListener::SetTlsHandshakeTimeout(double value, bool suppress_events, const Value& cookie) +{ + Configuration::TlsHandshakeTimeout = value; +} + void ApiListener::CopyCertificateFile(const String& oldCertPath, const String& newCertPath) { struct stat st1, st2; @@ -1453,6 +1463,14 @@ void ApiListener::ValidateTlsProtocolmin(const Lazy& lvalue, const Valid } } +void ApiListener::ValidateTlsHandshakeTimeout(const Lazy& lvalue, const ValidationUtils& utils) +{ + ObjectImpl::ValidateTlsHandshakeTimeout(lvalue, utils); + + if (lvalue() <= 0) + BOOST_THROW_EXCEPTION(ValidationError(this, { "tls_handshake_timeout" }, "Value must be greater than 0.")); +} + bool ApiListener::IsHACluster() { Zone::Ptr zone = Zone::GetLocalZone(); diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 27d236eaa..7868352d4 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -108,6 +108,9 @@ public: static String GetDefaultKeyPath(); static String GetDefaultCaPath(); + double GetTlsHandshakeTimeout() const override; + void SetTlsHandshakeTimeout(double value, bool suppress_events, const Value& cookie) override; + protected: void OnConfigLoaded() override; void OnAllConfigLoaded() override; @@ -115,6 +118,7 @@ protected: void Stop(bool runtimeDeleted) override; void ValidateTlsProtocolmin(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateTlsHandshakeTimeout(const Lazy& lvalue, const ValidationUtils& utils) override; private: std::shared_ptr m_SSLContext; diff --git a/lib/remote/apilistener.ti b/lib/remote/apilistener.ti index b98dae1cb..7d0b018d5 100644 --- a/lib/remote/apilistener.ti +++ b/lib/remote/apilistener.ti @@ -54,6 +54,12 @@ class ApiListener : ConfigObject default {{{ return -1; }}} }; + [config] double tls_handshake_timeout { + get; + set; + default {{{ return Configuration::TlsHandshakeTimeout; }}} + }; + [config] String ticket_salt; [config] Array::Ptr access_control_allow_origin;