-
Couldn't load subscription status.
- Fork 872
Description
Is there an already existing issue for this?
- I have searched the existing issues
Expected behavior
While the authentication of the remote participant fails, the change for sending the request is released.
Current behavior
While the authentication of the remote participant fails, the change for sending the request isn't released.
Steps to reproduce
This issue was discovered in an environment using DDS-Router and Humble. Since the version of FastDDS used in Humble is no longer maintained, I compared code with the latest code of FastDDS and I think the problem likely still exists.
So, I’ll describe the scenario in which the issue occurs.
- SPDP find a new remote participant.
- In SecurityManager::on_process_handshake(), the authentication status of remote participant is AUTHENTICATION_REQUEST_NOT_SEND. FastDDS will prepare a handshake request message and send it.
Fast-DDS/src/cpp/rtps/security/SecurityManager.cpp
Lines 947 to 953 in 8e9292e
if (participant_stateless_message_writer_history_->add_change(change)) { handshake_message_send = true; expected_sequence_number = message.message_identity().sequence_number(); remote_participant_info->change_sequence_number_ = change->sequenceNumber; remote_participant_info->handshake_requests_sent_++; }
And this change will be hold. - At this time, the remote participant is removed.
- FastDDS will attempt to resend the Handshake Request until it reaches the maximum number of handshake requests (max_handshake_requests).
Refer toFast-DDS/src/cpp/rtps/security/SecurityManager.cpp
Lines 4223 to 4286 in 8e9292e
void SecurityManager::resend_handshake_message_token( const GUID_t& remote_participant_key) const { auto sentry = is_security_manager_initialized(); if (!sentry) { return; } shared_lock<shared_mutex> _(mutex_); auto dp_it = discovered_participants_.find(remote_participant_key); if (dp_it != discovered_participants_.end()) { SecurityManager::DiscoveredParticipantInfo::AuthUniquePtr remote_participant_info = dp_it->second->get_auth(); if (remote_participant_info) { if (remote_participant_info->handshake_requests_sent_ >= auth_handshake_props_.max_handshake_requests_) { if (remote_participant_info->auth_status_ != AUTHENTICATION_FAILED) { SecurityException exception; remote_participant_info->event_->cancel_timer(); remote_participant_info->auth_status_ = AUTHENTICATION_FAILED; on_validation_failed(dp_it->second->participant_data(), exception); } } else { if (remote_participant_info->change_sequence_number_ != SequenceNumber_t::unknown()) { CacheChange_t* p_change = participant_stateless_message_writer_history_->remove_change_and_reuse( remote_participant_info->change_sequence_number_); remote_participant_info->change_sequence_number_ = SequenceNumber_t::unknown(); if (p_change != nullptr) { EPROSIMA_LOG_INFO(SECURITY, "Authentication handshake resent to participant " << remote_participant_key); if (participant_stateless_message_writer_history_->add_change(p_change)) { remote_participant_info->change_sequence_number_ = p_change->sequenceNumber; remote_participant_info->handshake_requests_sent_++; } //TODO (Ricardo) What to do if not added? } } if (remote_participant_info->auth_status_ == AUTHENTICATION_WAITING_REPLY) { // Avoid DoS attack by exponentially increasing event interval auto time_ms = remote_participant_info->event_->getIntervalMilliSec(); remote_participant_info->event_->update_interval_millisec( time_ms * auth_handshake_props_.handshake_resend_period_gain_); remote_participant_info->event_->restart_timer(); } } dp_it->second->set_auth(remote_participant_info); } } } - When the max_handshake_requests is reached, the following code will be executed.
Fast-DDS/src/cpp/rtps/security/SecurityManager.cpp
Lines 4242 to 4251 in 8e9292e
if (remote_participant_info->handshake_requests_sent_ >= auth_handshake_props_.max_handshake_requests_) { if (remote_participant_info->auth_status_ != AUTHENTICATION_FAILED) { SecurityException exception; remote_participant_info->event_->cancel_timer(); remote_participant_info->auth_status_ = AUTHENTICATION_FAILED; on_validation_failed(dp_it->second->participant_data(), exception); } }
But the change for request isn't released.
The fix refers to #5935
Fast DDS version/commit
v3.3.0
Platform/Architecture
Other. Please specify in Additional context section.
Transport layer
Default configuration, UDPv4 & SHM
Additional context
Platform: Ubuntu 24.04 (x86_64)
XML configuration file
Relevant log output
Network traffic capture
No response