diff --git a/src/cpp/rtps/security/SecurityManager.cpp b/src/cpp/rtps/security/SecurityManager.cpp index 474c73a9647..20c4cf0a9e0 100644 --- a/src/cpp/rtps/security/SecurityManager.cpp +++ b/src/cpp/rtps/security/SecurityManager.cpp @@ -4255,6 +4255,19 @@ void SecurityManager::resend_handshake_message_token( remote_participant_info->event_->cancel_timer(); remote_participant_info->auth_status_ = AUTHENTICATION_FAILED; on_validation_failed(dp_it->second->participant_data(), exception); + if (remote_participant_info->change_sequence_number_ != SequenceNumber_t::unknown()) + { + participant_stateless_message_writer_history_->remove_change( + remote_participant_info->change_sequence_number_); + remote_participant_info->change_sequence_number_ = SequenceNumber_t::unknown(); + // Return the handshake handle + if (remote_participant_info->handshake_handle_ != nullptr) + { + authentication_plugin_->return_handshake_handle( + remote_participant_info->handshake_handle_, exception); + remote_participant_info->handshake_handle_ = nullptr; + } + } } } else diff --git a/test/blackbox/api/dds-pim/PubSubReader.hpp b/test/blackbox/api/dds-pim/PubSubReader.hpp index 494b18e77f1..a68566c6fcb 100644 --- a/test/blackbox/api/dds-pim/PubSubReader.hpp +++ b/test/blackbox/api/dds-pim/PubSubReader.hpp @@ -854,7 +854,7 @@ class PubSubReader } #if HAVE_SECURITY - void waitAuthorized( + void wait_authorized( std::chrono::seconds timeout = std::chrono::seconds::zero(), unsigned int expected = 1) { @@ -880,16 +880,28 @@ class PubSubReader std::cout << "Reader authorization finished..." << std::endl; } - void waitUnauthorized() + void wait_unauthorized( + std::chrono::seconds timeout = std::chrono::seconds::zero(), + unsigned int expected = 1) { std::unique_lock lock(mutexAuthentication_); std::cout << "Reader is waiting unauthorization..." << std::endl; - cvAuthentication_.wait(lock, [&]() -> bool - { - return unauthorized_ > 0; - }); + if (timeout == std::chrono::seconds::zero()) + { + cvAuthentication_.wait(lock, [&]() + { + return unauthorized_ >= expected; + }); + } + else + { + cvAuthentication_.wait_for(lock, timeout, [&]() + { + return unauthorized_ >= expected; + }); + } std::cout << "Reader unauthorization finished..." << std::endl; } diff --git a/test/blackbox/api/dds-pim/PubSubWriter.hpp b/test/blackbox/api/dds-pim/PubSubWriter.hpp index bc1d9dbcc4f..0c53e79f8bb 100644 --- a/test/blackbox/api/dds-pim/PubSubWriter.hpp +++ b/test/blackbox/api/dds-pim/PubSubWriter.hpp @@ -731,7 +731,7 @@ class PubSubWriter } #if HAVE_SECURITY - void waitAuthorized( + void wait_authorized( std::chrono::seconds timeout = std::chrono::seconds::zero(), unsigned int expected = 1) { @@ -757,16 +757,28 @@ class PubSubWriter std::cout << "Writer authorization finished..." << std::endl; } - void waitUnauthorized() + void wait_unauthorized( + std::chrono::seconds timeout = std::chrono::seconds::zero(), + unsigned int expected = 1) { std::unique_lock lock(mutexAuthentication_); std::cout << "Writer is waiting unauthorization..." << std::endl; - cvAuthentication_.wait(lock, [&]() -> bool - { - return unauthorized_ > 0; - }); + if (timeout == std::chrono::seconds::zero()) + { + cvAuthentication_.wait(lock, [&]() + { + return unauthorized_ >= expected; + }); + } + else + { + cvAuthentication_.wait_for(lock, timeout, [&]() + { + return unauthorized_ >= expected; + }); + } std::cout << "Writer unauthorization finished..." << std::endl; } diff --git a/test/blackbox/api/dds-pim/PubSubWriterReader.hpp b/test/blackbox/api/dds-pim/PubSubWriterReader.hpp index d2427a2a1e6..bd6500fef20 100644 --- a/test/blackbox/api/dds-pim/PubSubWriterReader.hpp +++ b/test/blackbox/api/dds-pim/PubSubWriterReader.hpp @@ -272,7 +272,8 @@ class PubSubWriterReader do { wreader_.receive_one(datareader, ret); - } while (ret); + } + while (ret); } } @@ -682,7 +683,7 @@ class PubSubWriterReader } #if HAVE_SECURITY - void waitAuthorized( + void wait_authorized( unsigned int how_many = 1) { std::unique_lock lock(mutexAuthentication_); @@ -698,7 +699,7 @@ class PubSubWriterReader std::cout << "WReader authorization finished..." << std::endl; } - void waitUnauthorized( + void wait_unauthorized( unsigned int how_many = 1) { std::unique_lock lock(mutexAuthentication_); diff --git a/test/blackbox/common/BlackboxTestsSecurity.cpp b/test/blackbox/common/BlackboxTestsSecurity.cpp index f9369f6d2f7..4ed1050e59c 100644 --- a/test/blackbox/common/BlackboxTestsSecurity.cpp +++ b/test/blackbox/common/BlackboxTestsSecurity.cpp @@ -49,6 +49,26 @@ enum communication_type DATASHARING }; +// A LogConsumer that just counts the number of entries consumed +struct TestConsumer : public eprosima::fastdds::dds::LogConsumer +{ + TestConsumer( + std::atomic_size_t& n_logs_ref) + : n_logs_(n_logs_ref) + { + } + + void Consume( + const eprosima::fastdds::dds::Log::Entry&) override + { + ++n_logs_; + } + +private: + + std::atomic_size_t& n_logs_; +}; + static void fill_pub_auth( PropertyPolicy& policy) { @@ -324,8 +344,8 @@ TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_validation_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -394,7 +414,7 @@ TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_validation_fail) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - writer.waitUnauthorized(); + writer.wait_unauthorized(); } { PubSubReader reader(TEST_TOPIC_NAME); @@ -414,7 +434,7 @@ TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_validation_fail) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitUnauthorized(); + reader.wait_unauthorized(); } } @@ -450,8 +470,8 @@ TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_lossy_conditions) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -466,26 +486,6 @@ TEST(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop) using Log = eprosima::fastdds::dds::Log; using LogConsumer = eprosima::fastdds::dds::LogConsumer; - // A LogConsumer that just counts the number of entries consumed - struct TestConsumer : public LogConsumer - { - TestConsumer( - std::atomic_size_t& n_logs_ref) - : n_logs_(n_logs_ref) - { - } - - void Consume( - const Log::Entry&) override - { - ++n_logs_; - } - - private: - - std::atomic_size_t& n_logs_; - }; - // Counter for log entries std::atomicn_logs{}; @@ -595,26 +595,6 @@ TEST_P(Security, BuiltinAuthenticationPlugin_ensure_same_guid_reconnection) using Log = eprosima::fastdds::dds::Log; using LogConsumer = eprosima::fastdds::dds::LogConsumer; - // A LogConsumer that just counts the number of entries consumed - struct TestConsumer : public LogConsumer - { - TestConsumer( - std::atomic_size_t& n_logs_ref) - : n_logs_(n_logs_ref) - { - } - - void Consume( - const Log::Entry&) override - { - ++n_logs_; - } - - private: - - std::atomic_size_t& n_logs_; - }; - // Counter for log entries std::atomicn_logs{}; @@ -690,8 +670,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_rtps_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -746,8 +726,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_shm_transport_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -804,8 +784,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_shm_udp_transport_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -850,8 +830,8 @@ TEST(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_rtps_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -928,8 +908,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_large_string) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -974,8 +954,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_rtps_large_string ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1028,8 +1008,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_rtps_data300kb) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1082,8 +1062,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_rtps_data300kb) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1131,8 +1111,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_submessage_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1180,8 +1160,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_submessage_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1265,8 +1245,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_submessage_larg ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1314,8 +1294,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_submessage_large_ ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1371,8 +1351,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_submessage_data ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1428,8 +1408,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_submessage_data30 ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1477,8 +1457,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_payload_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1526,8 +1506,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_payload_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1645,8 +1625,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_payload_large_s ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1694,8 +1674,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_payload_large_str ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1751,8 +1731,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_payload_data300 ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1808,8 +1788,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_payload_data300kb ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1861,8 +1841,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_all_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1914,8 +1894,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_all_ok) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -1967,8 +1947,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_all_large_strin ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2020,8 +2000,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_all_large_string) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2081,8 +2061,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_besteffort_all_data300kb) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2142,8 +2122,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_all_data300kb) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2197,8 +2177,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_reliable_all_data300kb_mix ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2273,8 +2253,8 @@ TEST_P(Security, BuiltinAuthenticationAndCryptoPlugin_user_data) ASSERT_TRUE(reader.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); reader.wait_discovery(); writer.wait_discovery(); @@ -2331,8 +2311,8 @@ TEST_P(Security, BuiltinAuthenticationAndAccessAndCryptoPlugin_governance_rule_o ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2548,8 +2528,8 @@ TEST_P(Security, BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_valid ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2659,8 +2639,8 @@ TEST_P(Security, BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_valid ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2858,8 +2838,8 @@ TEST_F(SecurityPkcs, BuiltinAuthenticationAndAccessAndCryptoPlugin_pkcs11_key) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2895,8 +2875,8 @@ TEST_F(SecurityPkcs, BuiltinAuthenticationAndAccessAndCryptoPlugin_pkcs11_key) ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -2990,8 +2970,8 @@ static void BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_validation ASSERT_TRUE(writer.isInitialized()); // Wait for authorization - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); // Wait for discovery. writer.wait_discovery(); @@ -3098,8 +3078,8 @@ TEST_P(Security, RemoveParticipantProxyDataonSecurityManagerLeaseExpired_validat std::cout << std::endl << "Waiting discovery between participants." << std::endl; // 3.Wait for authorization - pubsub_reader->waitAuthorized(); - pubsub_writer->waitAuthorized(); + pubsub_reader->wait_authorized(); + pubsub_writer->wait_authorized(); // 4.Wait for discovery. pubsub_reader->wait_discovery(); @@ -3210,7 +3190,7 @@ TEST(Security, AllowUnauthenticatedParticipants_TwoSecureParticipantsWithDiffere ASSERT_TRUE(writer.isInitialized()); //! Wait for the authorization to fail (~15secs) - writer.waitUnauthorized(); + writer.wait_unauthorized(); //! Wait for the discovery writer.wait_discovery(); @@ -3284,7 +3264,7 @@ TEST(Security, AllowUnauthenticatedParticipants_TwoParticipantsDifferentCertific ASSERT_TRUE(writer.isInitialized()); //! Wait for the authorization to fail (~15secs) - writer.waitUnauthorized(); + writer.wait_unauthorized(); //! Wait some time afterwards (this will time out) writer.wait_discovery(std::chrono::seconds(1)); @@ -3324,8 +3304,8 @@ TEST(Security, InANonSecureParticipantWithTwoSecureParticipantScenario_TheTwoSec ASSERT_TRUE(secure_reader.isInitialized()); // Wait for the authorization - secure_reader.waitAuthorized(); - secure_writer.waitAuthorized(); + secure_reader.wait_authorized(); + secure_writer.wait_authorized(); // Wait for discovery secure_writer.wait_discovery(std::chrono::seconds(5)); @@ -4223,8 +4203,8 @@ TEST_P(Security, MaliciousParticipantRemovalIgnore) ASSERT_TRUE(reader.isInitialized()); writer.init(); ASSERT_TRUE(writer.isInitialized()); - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); reader.wait_discovery(); writer.wait_discovery(); @@ -4357,12 +4337,12 @@ TEST(Security, ValidateAuthenticationHandshakeProperties) // or slower platforms std::chrono::duration max_time(500); auto t0 = std::chrono::steady_clock::now(); - reader.waitAuthorized(); + reader.wait_authorized(); auto auth_elapsed_time = std::chrono::duration( std::chrono::steady_clock::now() - t0); // Both should be authorized - writer.waitAuthorized(); + writer.wait_authorized(); ASSERT_TRUE(auth_elapsed_time < max_time); } @@ -4422,8 +4402,8 @@ TEST(Security, security_with_initial_peers_over_tcpv4_correctly_behaves) ASSERT_TRUE(tcp_server.isInitialized()); ASSERT_TRUE(tcp_client.isInitialized()); - tcp_server.waitAuthorized(); - tcp_client.waitAuthorized(); + tcp_server.wait_authorized(); + tcp_client.wait_authorized(); tcp_server.wait_discovery(); tcp_client.wait_discovery(); @@ -4443,25 +4423,6 @@ TEST(Security, security_with_initial_peers_over_tcpv4_correctly_behaves) // participants secure stateless msgs pool TEST(Security, participant_stateless_secure_writer_pool_change_is_removed_upon_participant_authentication) { - struct TestConsumer : public eprosima::fastdds::dds::LogConsumer - { - TestConsumer( - std::atomic_size_t& n_logs_ref) - : n_logs_(n_logs_ref) - { - } - - void Consume( - const eprosima::fastdds::dds::Log::Entry&) override - { - ++n_logs_; - } - - private: - - std::atomic_size_t& n_logs_; - }; - // Counter for log entries std::atomicn_logs{}; @@ -4507,13 +4468,13 @@ TEST(Security, participant_stateless_secure_writer_pool_change_is_removed_upon_p } // Wait for the first participant to authenticate the rest - participants.front()->waitAuthorized(std::chrono::seconds::zero(), n_participants - 1); + participants.front()->wait_authorized(std::chrono::seconds::zero(), n_participants - 1); // Init the last one participants.back()->init(); ASSERT_TRUE(participants.back()->isInitialized()); - participants.front()->waitAuthorized(std::chrono::seconds::zero(), n_participants); + participants.front()->wait_authorized(std::chrono::seconds::zero(), n_participants); // No SECURITY error logs should have been produced eprosima::fastdds::dds::Log::Flush(); @@ -4589,8 +4550,8 @@ TEST(Security, legacy_token_algorithms_communicate) ASSERT_TRUE(writer.isInitialized()); // Wait for discovery - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); reader.wait_discovery(); writer.wait_discovery(); ASSERT_TRUE(reader.is_matched()); @@ -4641,8 +4602,132 @@ TEST(Security, SerializationOfParticipantGenericMessageWhenAddingProperties) ASSERT_TRUE(writer.isInitialized()); // Both should be authorized - reader.waitAuthorized(); - writer.waitAuthorized(); + reader.wait_authorized(); + writer.wait_authorized(); +} + +/** + * This test is a regression test for Redmine issue #23431. + * On validation failed, the participant generic message + * shall be removed from the history and freed from the pool. + */ +TEST(Security, participant_stateless_secure_writer_pool_change_is_removed_upon_authentication_failure) +{ + // Counter for log entries + std::atomicn_logs{}; + + // Prepare Log module to check that no SECURITY errors are produced + eprosima::fastdds::dds::Log::SetCategoryFilter(std::regex("SECURITY")); + eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); + eprosima::fastdds::dds::Log::RegisterConsumer(std::unique_ptr(new TestConsumer( + n_logs))); + + const size_t n_participants = 100; + const uint32_t known_unicast_port = 7350; + + // Configure security and handshake properties + const std::string governance_file("governance_helloworld_all_enable.smime"); + const std::string permissions_file("permissions_helloworld.smime"); + + PropertyPolicy handshake_prop_policy; + + // Set a configuration that fails the authentication fast + handshake_prop_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.max_handshake_requests", + "10")); + handshake_prop_policy.properties().emplace_back(Property( + "dds.sec.auth.builtin.PKI-DH.initial_handshake_resend_period", + "50")); + + // Create the main participant (pointee by the rest) + PubSubWriter main_participant("HelloWorldTopic"); + + // Create 100 secure participants pointing to the main one + // 100 is because of the history size for the participant stateless message writer + std::vector>> participants; + participants.reserve(n_participants); + + // Create a test transport that will drop the participant stateless messages only + auto test_transport = std::make_shared(); + + // Filter to drop participant stateless messages + test_transport->drop_data_messages_filter_ = [](eprosima::fastdds::rtps::CDRMessage_t& msg) + -> bool + { + auto old_pos = msg.pos; + + // Jump to writer entity id + msg.pos += 2 + 2 + 4; + + // Read writer entity id + EntityId_t writer_entity_id; + writer_entity_id = eprosima::fastdds::helpers::cdr_parse_entity_id( + (char*)&msg.buffer[msg.pos]); + msg.pos = old_pos; + + if (writer_entity_id == eprosima::fastdds::rtps::participant_stateless_message_writer_entity_id) + { + // Drop the message if the message comes from participant generic message + return true; + } + + return false; + }; + + // Configure the main participant security + CommonPermissionsConfigure(main_participant, governance_file, permissions_file, handshake_prop_policy); + + main_participant.disable_builtin_transport() + .add_user_transport_to_pparams(test_transport) + .add_to_metatraffic_unicast_locator_list("127.0.0.1", known_unicast_port) + .init(); + ASSERT_TRUE(main_participant.isInitialized()); + + // Set the initial peers for the rest of the participants + // They will all point to the main participant + LocatorList_t initial_peers; + Locator_t main_participant_locator; + main_participant_locator.kind = LOCATOR_KIND_UDPv4; + main_participant_locator.port = known_unicast_port; + IPLocator::setIPv4(main_participant_locator, "127.0.0.1"); + initial_peers.push_back(main_participant_locator); + + for (size_t i = 0; i < n_participants; ++i) + { + participants.emplace_back(std::make_shared>("HelloWorldTopic")); + + // Configure security for the new participant + CommonPermissionsConfigure(*participants.back(), governance_file, permissions_file, handshake_prop_policy); + + // Init participant with the main participant as initial peer + // and disable multicast so it does not try to discover noone else + participants.back()->disable_multicast(static_cast(i + 1)) + .initial_peers(initial_peers) + .init(); + + ASSERT_TRUE(participants.back()->isInitialized()); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + // Wait for the main participant to fail authentication with the rest + main_participant.wait_unauthorized(std::chrono::seconds::zero(), n_participants); + + // If the participant stateless messages history of the main participant is not correctly freed, + // the main participant will fail creating a new participant stateless message for him + auto failing_participant = std::make_shared>("HelloWorldTopic"); + CommonPermissionsConfigure(*failing_participant, governance_file, permissions_file, handshake_prop_policy); + failing_participant->disable_multicast(static_cast(n_participants + 1)) + .initial_peers(initial_peers) + .init(); + + // Wait for the main participant to unauthorize the new one + main_participant.wait_unauthorized(std::chrono::seconds::zero(), n_participants + 1); + + // In case logs are not flushed immediately, we wait a bit + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + // No SECURITY error logs should have been produced + eprosima::fastdds::dds::Log::Flush(); + EXPECT_EQ(0u, n_logs); } void blackbox_security_init()