From 9c217b42d25fd35ebc66a93aba601c6837734835 Mon Sep 17 00:00:00 2001 From: Sebastien Vincent Date: Mon, 17 Dec 2018 10:50:38 +0100 Subject: [PATCH] [libfscp] Adds a limitation for PRESENTATION messages processing. We adds a limit of 512 PRESENTATION packets per 10 seconds. This is not a perfect solution but at least it will not bother too much existing communications between peers. --- libs/fscp/include/fscp/server.hpp | 21 +++++++++++++++++++ libs/fscp/src/server.cpp | 34 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/libs/fscp/include/fscp/server.hpp b/libs/fscp/include/fscp/server.hpp index c22ec621..687d9023 100644 --- a/libs/fscp/include/fscp/server.hpp +++ b/libs/fscp/include/fscp/server.hpp @@ -1426,6 +1426,12 @@ namespace fscp void handle_presentation_message_from(const identity_store&, const presentation_message&, const ep_type&); void do_handle_presentation(const identity_store& identity, const ep_type&, bool, cert_type); + /** + * \brief Reset presentation limit. + * \param ec error code. + */ + void do_presentation_reset_limit(const boost::system::error_code& ec); + void do_set_presentation_message_received_callback(presentation_message_received_handler_type, void_handler_type); // This strand is also used by session requests and session messages during the cipherment/decipherment phase. @@ -1437,6 +1443,21 @@ namespace fscp presentation_store_map m_presentation_store_map; presentation_message_received_handler_type m_presentation_message_received_handler; + /** + * \brief Current number of session request sent. + */ + size_t m_presentation_requests; + + /** + * \brief Timer for reesting presentation requests limit. + */ + boost::asio::deadline_timer m_presentation_limit_timer; + + /** + * \brief maximum number of session request. + */ + static const size_t MAX_PRESENTATION_REQUESTS; + private: // SESSION_REQUEST messages typedef std::map peer_session_map_type; diff --git a/libs/fscp/src/server.cpp b/libs/fscp/src/server.cpp index ecf2278d..3c69f5b8 100644 --- a/libs/fscp/src/server.cpp +++ b/libs/fscp/src/server.cpp @@ -214,6 +214,8 @@ namespace fscp } } + const size_t server::MAX_PRESENTATION_REQUESTS = 512; + // Public methods server::server(boost::asio::io_service& io_service, fscp::logger& _logger, const identity_store& identity) : @@ -227,6 +229,8 @@ namespace fscp m_hello_message_received_handler(), m_presentation_strand(io_service), m_presentation_message_received_handler(), + m_presentation_requests(0), + m_presentation_limit_timer(io_service, boost::posix_time::seconds(10)), m_session_strand(io_service), m_accept_session_request_messages_default(true), m_cipher_suites(get_default_cipher_suites()), @@ -307,6 +311,9 @@ namespace fscp async_receive_from(); m_keep_alive_timer.async_wait(m_session_strand.wrap(boost::bind(&server::do_check_keep_alive, this, boost::asio::placeholders::error))); + m_presentation_limit_timer.async_wait(m_presentation_strand.wrap( + boost::bind(&server::do_presentation_reset_limit, this, + boost::asio::placeholders::error))); } void server::close() @@ -315,6 +322,8 @@ namespace fscp m_keep_alive_timer.cancel(); + m_presentation_limit_timer.cancel(); + m_socket.close(); } @@ -1415,6 +1424,16 @@ namespace fscp void server::do_handle_presentation(const identity_store& identity, const ep_type& sender, bool has_session, cert_type signature_certificate) { // All do_handle_presentation() calls are done in the same strand so the following is thread-safe. + if(m_presentation_requests <= MAX_PRESENTATION_REQUESTS) + { + m_presentation_requests++; + } + else + { + // presentation flood? + return; + } + presentation_status_type presentation_status = PS_FIRST; const presentation_store_map::iterator entry = m_presentation_store_map.find(sender); @@ -1442,6 +1461,21 @@ namespace fscp m_presentation_store_map[sender] = presentation_store(signature_certificate, identity.pre_shared_key()); } + void server::do_presentation_reset_limit(const boost::system::error_code& ec) + { + // All do_presentation_reset_limit calls are done in the same strand so the following is thread-safe. + if (ec != boost::asio::error::operation_aborted) + { + m_presentation_requests = 0; + + // rearm timer again + m_presentation_limit_timer.expires_from_now(boost::posix_time::seconds(10)); + m_presentation_limit_timer.async_wait(m_presentation_strand.wrap( + boost::bind(&server::do_presentation_reset_limit, this, + boost::asio::placeholders::error))); + } + } + void server::do_set_presentation_message_received_callback(presentation_message_received_handler_type callback, void_handler_type handler) { // All do_set_presentation_message_received_callback() calls are done in the same strand so the following is thread-safe.