Rate-limit SSL client renegotiation (RIPD-360)

This commit is contained in:
David Schwartz
2014-07-09 14:09:37 -07:00
committed by Vinnie Falco
parent bbbae072ea
commit a2764b68ca
3 changed files with 6702 additions and 6643 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,13 @@
#include <ripple/common/RippleSSLContext.h>
#include <ripple/common/seconds_clock.h>
#include <beast/container/aged_unordered_set.h>
#include <cstdint>
#include <sstream>
namespace ripple {
class RippleSSLContextImp : public RippleSSLContext
@@ -29,6 +33,8 @@ class RippleSSLContextImp : public RippleSSLContext
private:
boost::asio::ssl::context m_context;
// track when SSL connections have last negotiated
public:
RippleSSLContextImp ()
: RippleSSLContext (m_context)
@@ -45,6 +51,55 @@ public:
return DHparams_dup (getDH (key_length));
}
static bool disallowRenegotiation (SSL const* ssl, bool isNew)
{
// Do not allow a connection to renegotiate
// more than once every 4 minutes
static std::mutex negotiationSetLock;
static beast::aged_unordered_set <SSL const*> negotiationSet (ripple::get_seconds_clock ());
static std::chrono::seconds const minRenegotiationSeconds = std::chrono::minutes (4);
std::lock_guard <std::mutex> locker (negotiationSetLock);
auto const expired = (negotiationSet.clock().now() - minRenegotiationSeconds);
// Remove expired entries
for (auto iter (negotiationSet.chronological.begin ());
(iter != negotiationSet.chronological.end ()) && (iter.when () <= expired);
iter = negotiationSet.chronological.begin ())
{
negotiationSet.erase (iter);
}
auto iter = negotiationSet.find (ssl);
if (iter != negotiationSet.end ())
{
if (!isNew)
{
// This is a renegotiation and the last negotiation was recent
return true;
}
negotiationSet.touch (iter);
}
else
{
negotiationSet.emplace (ssl);
}
return false;
}
static void info_handler (SSL const* ssl, int event, int)
{
if ((ssl->s3) && (event & SSL_CB_HANDSHAKE_START))
{
if (disallowRenegotiation (ssl, SSL_in_before (ssl)))
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
// Pretty prints an error message
std::string error_message (std::string const& what,
boost::system::error_code const& ec)
@@ -105,6 +160,10 @@ public:
SSL_CTX_set_tmp_dh_callback (
m_context.native_handle (),
tmp_dh_handler);
SSL_CTX_set_info_callback (
m_context.native_handle (),
info_handler);
}
//--------------------------------------------------------------------------