Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[20181] Hotfix: Secure simple participants with initialpeers over TCP match (backport #5071) #5176

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion include/fastdds/rtps/builtin/discovery/participant/PDPSimple.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,16 @@ class PDPSimple : public PDP

void match_pdp_remote_endpoints(
const ParticipantProxyData& pdata,
bool notify_secure_endpoints);
bool notify_secure_endpoints,
bool writer_only);

/**
* @brief Unmatch PDP endpoints with a remote participant.
*
* @param participant_guid GUID of the remote participant.
*/
void unmatch_pdp_remote_endpoints(
const GUID_t& participant_guid);

void assign_low_level_remote_endpoints(
const ParticipantProxyData& pdata,
Expand Down
27 changes: 19 additions & 8 deletions src/cpp/rtps/builtin/discovery/participant/PDPSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,11 @@ bool PDPSimple::createPDPEndpoints()
secure_endpoints->secure_reader.listener_.reset(new PDPListener(this));

endpoints = secure_endpoints;
endpoints->reader.listener_.reset(new PDPSecurityInitiatorListener(this));
endpoints->reader.listener_.reset(new PDPSecurityInitiatorListener(this,
[this](const ParticipantProxyData& participant_data)
{
match_pdp_remote_endpoints(participant_data, false, true);
}));
}
else
#endif // HAVE_SECURITY
Expand Down Expand Up @@ -550,7 +554,7 @@ void PDPSimple::assignRemoteEndpoints(
{
// This participant is not secure.
// Match PDP and other builtin endpoints.
match_pdp_remote_endpoints(*pdata, false);
match_pdp_remote_endpoints(*pdata, false, false);
assign_low_level_remote_endpoints(*pdata, false);
}
}
Expand All @@ -560,8 +564,13 @@ void PDPSimple::removeRemoteEndpoints(
ParticipantProxyData* pdata)
{
EPROSIMA_LOG_INFO(RTPS_PDP, "For RTPSParticipant: " << pdata->m_guid);
unmatch_pdp_remote_endpoints(pdata->m_guid);
}

GUID_t guid = pdata->m_guid;
void PDPSimple::unmatch_pdp_remote_endpoints(
const GUID_t& participant_guid)
{
GUID_t guid = participant_guid;

{
auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
Expand Down Expand Up @@ -593,7 +602,8 @@ void PDPSimple::notifyAboveRemoteEndpoints(
{
if (notify_secure_endpoints)
{
match_pdp_remote_endpoints(pdata, true);
unmatch_pdp_remote_endpoints(pdata.m_guid);
match_pdp_remote_endpoints(pdata, true, false);
}
else
{
Expand All @@ -606,7 +616,7 @@ void PDPSimple::notifyAboveRemoteEndpoints(
notify_and_maybe_ignore_new_participant(part_data, ignored);
if (!ignored)
{
match_pdp_remote_endpoints(*part_data, false);
match_pdp_remote_endpoints(*part_data, false, false);
assign_low_level_remote_endpoints(*part_data, false);
}
}
Expand All @@ -616,7 +626,8 @@ void PDPSimple::notifyAboveRemoteEndpoints(

void PDPSimple::match_pdp_remote_endpoints(
const ParticipantProxyData& pdata,
bool notify_secure_endpoints)
bool notify_secure_endpoints,
bool writer_only)
{
#if !HAVE_SECURITY
static_cast<void>(notify_secure_endpoints);
Expand Down Expand Up @@ -653,7 +664,7 @@ void PDPSimple::match_pdp_remote_endpoints(
}
#endif // HAVE_SECURITY

if (0 != (endp & pdp_writer_mask))
if (!writer_only && (0 != (endp & pdp_writer_mask)))
{
auto temp_writer_data = get_temporary_writer_proxies_pool().get();

Expand Down Expand Up @@ -711,7 +722,7 @@ void PDPSimple::match_pdp_remote_endpoints(
writer->matched_reader_add(*temp_reader_data);
}

if (BEST_EFFORT_RELIABILITY_QOS == reliability_kind)
if (!writer_only && (BEST_EFFORT_RELIABILITY_QOS == reliability_kind))
{
endpoints->writer.writer_->unsent_changes_reset();
}
Expand Down
72 changes: 72 additions & 0 deletions test/blackbox/common/BlackboxTestsSecurity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <fstream>
#include <map>

#include <fastrtps/utils/IPFinder.h>
#include <gtest/gtest.h>

#include "PubSubReader.hpp"
Expand Down Expand Up @@ -5016,6 +5017,77 @@ TEST(Security, ValidateAuthenticationHandshakeProperties)
ASSERT_TRUE(auth_elapsed_time < max_time);
}

// Regression test for Redmine issue #20181
// Two simple secure participants with tcp transport and initial peers must match.
// It basically tests that the PDPSecurityInitiatorListener
// in PDPSimple answers back with the proxy data.
TEST(Security, security_with_initial_peers_over_tcpv4_correctly_behaves)
{
// Create
PubSubWriter<HelloWorldPubSubType> tcp_client("HelloWorldTopic_TCP");
PubSubReader<HelloWorldPubSubType> tcp_server("HelloWorldTopic_TCP");

// Search for a valid WAN address
LocatorList_t all_locators;
Locator_t wan_locator;
IPFinder::getIP4Address(&all_locators);

for (auto& locator : all_locators)
{
if (!IPLocator::isLocal(locator))
{
wan_locator = locator;
break;
}
}

uint16_t server_listening_port = 11810;
wan_locator.port = server_listening_port;
wan_locator.kind = LOCATOR_KIND_TCPv4;

auto tcp_client_transport_descriptor = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
LocatorList_t initial_peers;
initial_peers.push_back(wan_locator);
tcp_client.disable_builtin_transport()
.add_user_transport_to_pparams(tcp_client_transport_descriptor)
.initial_peers(initial_peers);

auto tcp_server_transport_descriptor = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
tcp_server_transport_descriptor->listening_ports.push_back(server_listening_port);
IPLocator::copyIPv4(wan_locator, tcp_server_transport_descriptor->wan_addr);

std::cout << "SETTING WAN address to " << wan_locator << std::endl;

tcp_server.disable_builtin_transport()
.add_user_transport_to_pparams(tcp_server_transport_descriptor);

// Configure security
const std::string governance_file("governance_helloworld_all_enable.smime");
const std::string permissions_file("permissions_helloworld.smime");
CommonPermissionsConfigure(tcp_server, tcp_client, governance_file, permissions_file);

tcp_server.init();
tcp_client.init();

ASSERT_TRUE(tcp_server.isInitialized());
ASSERT_TRUE(tcp_client.isInitialized());

tcp_server.waitAuthorized();
tcp_client.waitAuthorized();

tcp_server.wait_discovery();
tcp_client.wait_discovery();

ASSERT_TRUE(tcp_server.is_matched());
ASSERT_TRUE(tcp_client.is_matched());

auto data = default_helloworld_data_generator();
tcp_server.startReception(data);
tcp_client.send(data);
ASSERT_TRUE(data.empty());
tcp_server.block_for_all(std::chrono::seconds(10));
}


void blackbox_security_init()
{
Expand Down
Loading