CVE-2023-50257 (C, published 2024-02-19T20:15Z)
Description: value: eProsima Fast DDS (formerly Fast RTPS) is a C++ implementation of the Data Distribution Service standard of the Object Management Group. Even with the application of SROS2, due to the issue where the data (`p[UD]`) and `guid` values used to disconnect between nodes are not encrypted, a vulnerability has been discovered where a malicious attacker can forcibly disconnect a Subscriber and can deny a Subscriber attempting to connect. Afterwards, if the attacker sends the packet for disconnecting, which is data (`p[UD]`), to the Global Data Space (`239.255.0.1:7400`) using the said Publisher ID, all the Subscribers (Listeners) connected to the Publisher (Talker) will not receive any data and their connection will be disconnected. Moreover, if this disconnection packet is sent continuously, the Subscribers (Listeners) trying to connect will not be able to do so. Since the initial commit of the `SecurityManager.cpp` code (`init`, `on_process_handshake`) on Nov 8, 2016, the Disconnect Vulnerability in RTPS Packets Used by SROS2 has been present prior to versions 2.13.0, 2.12.2, 2.11.3, 2.10.3, and 2.6.7.
Severity: nan (CVSS v3 base score: )
Weakness: CWE-284 \u2014 Improper Access Control
The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
Repository: https://github.com/eProsima/Fast-DDS
Files changed:
include/fastrtps/config.h.in
include/fastrtps/rtps/common/Token.h
include/fastrtps/rtps/messages/CDRMessage.h
include/fastrtps/rtps/messages/CDRMessage.hpp
include/fastrtps/rtps/security/common/ParticipantGenericMessage.h
src/cpp/CMakeLists.txt
src/cpp/rtps/common/Token.cpp
src/cpp/rtps/security/SecurityManager.cpp
src/cpp/rtps/security/SecurityManager.h
test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h
test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h
test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h
test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h
test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h
test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h
test/unittest/rtps/security/CMakeLists.txt
test/unittest/rtps/security/SecurityAuthenticationTests.cpp
Commit message: Refs #1811. WIP SecurityManager.


Vulnerable code:
    if(msg->pos + 28 >= msg->max_size)
        return CDRMessage::addString(msg, property.name()) &&
            CDRMessage::addString(msg, property.value());
        return CDRMessage::addString(msg, binary_property.name()) &&
            CDRMessage::addOctetVector(msg, &binary_property.value());
    if(msg->pos + 4 <  msg->max_size)
        if(CDRMessage::addUInt32(msg, (uint32_t)properties.size()))
                returnedValue = CDRMessage::addProperty(msg, *it);
    if(msg->pos + 4 <  msg->max_size)
    if(msg->pos + 4 <  msg->max_size)
SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : participant_(participant),
        IdentityHandle* remote_identity_handle)
        returnedValue = on_request_not_send(remote_participant_key, remote_identity_handle);
bool SecurityManager::on_request_not_send(const GUID_t& remote_participant_key,
        IdentityHandle* remote_identity_handle)
    HandshakeHandle* handshake_handle = nullptr;
    ValidationResult_t ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
        restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
    assert(handshake_message);
    // Send hanshake message
    // 
    delete handshake_message;
    AuthenticationStatus auth_status = AUTHENTICATION_FAILED;

    switch(ret)
        case VALIDATION_OK:
            auth_status = AUTHENTICATION_OK;
            break;
        case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
            auth_status = AUTHENTICATION_WAITING_REPLY;
            break;
        case VALIDATION_OK_WITH_FINAL_MESSAGE:
            auth_status = AUTHENTICATION_OK;
            break;
        case VALIDATION_PENDING_RETRY:
            // TODO(Ricardo) Send event.
        default:
            restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
            return false;
    };
    // Store status
    std::unique_lock<std::mutex> lock(mutex_);
    auto dp_it = discovered_participants_.find(remote_participant_key);
    if(dp_it != discovered_participants_.end())
        assert(dp_it->second.get_auth_status() == AUTHENTICATION_REQUEST_NOT_SEND);
        dp_it->second.set_auth_status(auth_status);
        assert(dp_it->second.is_identity_handle_null());
        dp_it->second.set_identity_handle(remote_identity_handle);
        assert(dp_it->second.is_handshake_handle_null());
        dp_it->second.set_handshake_handle(handshake_handle);
    else
        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
        return false;
    return true;
    //mp_listener = new PDPSimpleListener(this);
    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, nullptr, participant_stateless_message_reader_entity_id, true, false))
    //delete(mp_listener);
    //mp_listener = nullptr;
                    auth_status_(auth_status){}
                IdentityHandle* remote_identity_handle);
        bool on_request_not_send(const GUID_t& remote_participant_key, IdentityHandle* remote_identity_handle);
class RTPSWriter;
class RTPSReader;
        MOCK_METHOD6(createWriter, bool (RTPSWriter** Writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
        MOCK_METHOD7(createReader, bool (RTPSReader** Reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
    return auth_plugin_;
    auth_plugin_ = nullptr;
            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
            EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
                WillOnce(Return(true));
            EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
                WillOnce(Return(true));
        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()), manager_(&participant_) {}
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK)));

Fixed code:
// Security
#ifndef SECURITY
#define SECURITY @HAVE_SECURITY@
#endif


        static size_t serialized_size(const DataHolder& data_holder, size_t current_alignment = 0);

        static size_t serialized_size(const DataHolderSeq& data_holders, size_t current_alignment = 0);

    private:

        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
#ifdef SECURITY
#include "../security/common/ParticipantGenericMessage.h"
#endif

	  inline bool readInt64(CDRMessage_t* msg, int64_t* lolo);

      inline bool readProperty(CDRMessage_t* msg, Property& property);
      inline bool readBinaryProperty(CDRMessage_t* msg, BinaryProperty& binary_property);
      inline bool readPropertySeq(CDRMessage_t* msg, PropertySeq& properties);
      inline bool readBinaryPropertySeq(CDRMessage_t* msg, BinaryPropertySeq& binary_properties);
      inline bool readDataHolder(CDRMessage_t* msg, DataHolder& data_holder);
      inline bool readDataHolderSeq(CDRMessage_t* msg, DataHolderSeq& data_holders);
      inline bool readMessageIdentity(CDRMessage_t* msg, ::security::MessageIdentity& message_identity);
      inline bool readParticipantGenericMessage(CDRMessage_t* msg, ::security::ParticipantGenericMessage& message);
      inline bool addDataHolder(CDRMessage_t* msg, const DataHolder& data_holder);
      inline bool addDataHolderSeq(CDRMessage_t* msg, const DataHolderSeq& data_holders);
      inline bool addMessageIdentity(CDRMessage_t* msg, const ::security::MessageIdentity& message_identity);
      inline bool addParticipantGenericMessage(CDRMessage_t* msg, const ::security::ParticipantGenericMessage& message);
inline bool CDRMessage::readInt64(CDRMessage_t* msg, int64_t* lolo)
{
    if(msg->pos+8 > msg->length)
        return false;

    octet* dest = (octet*)lolo;
    if(msg->msg_endian == DEFAULT_ENDIAN)
    {
        for(uint8_t i = 0; i < 8; ++i)
            dest[i] = msg->buffer[msg->pos+i];

        msg->pos+=8;
    }
    else
    {
        readDataReversed(msg, dest, 8);
    }

    return true;
}

    if(msg->pos + 28 > msg->max_size)
    assert(msg);

        if(!CDRMessage::addString(msg, property.name()))
            return false;
        if(!CDRMessage::addString(msg, property.value()))
            return false;
inline bool CDRMessage::readProperty(CDRMessage_t* msg, Property& property)
{
    assert(msg);

    if(!CDRMessage::readString(msg, &property.name()))
        return false;
    if(!CDRMessage::readString(msg, &property.value()))
        return false;

    return true;
}

    assert(msg);

    {
        if(!CDRMessage::addString(msg, binary_property.name()))
            return false;
        if(!CDRMessage::addOctetVector(msg, &binary_property.value()))
            return false;
    }

    return true;
}

inline bool CDRMessage::readBinaryProperty(CDRMessage_t* msg, BinaryProperty& binary_property)
{
    assert(msg);

    if(!CDRMessage::readString(msg, &binary_property.name()))
        return false;
    if(!CDRMessage::readOctetVector(msg, &binary_property.value()))
        return false;
    assert(msg);

    if(msg->pos + 4 <=  msg->max_size)
        uint32_t number_to_serialize = 0;
        for(auto it = properties.begin(); it != properties.end(); ++it)
            if(it->propagate())
                ++number_to_serialize;

        if(CDRMessage::addUInt32(msg, number_to_serialize))
            returnedValue = true;
                if(it->propagate())
                    returnedValue = CDRMessage::addProperty(msg, *it);
inline bool CDRMessage::readPropertySeq(CDRMessage_t* msg, PropertySeq& properties)
{
    assert(msg);

    uint32_t length = 0;
    if(!CDRMessage::readUInt32(msg, &length))
        return false;

    properties.resize(length);
    bool returnedValue = true;
    for(uint32_t i = 0; returnedValue && i < length; ++i)
        returnedValue = CDRMessage::readProperty(msg, properties.at(i));

    return returnedValue;

}

    assert(msg);

    if(msg->pos + 4 <=  msg->max_size)
    assert(msg);

    if(msg->pos + 4 <=  msg->max_size)
inline bool CDRMessage::readBinaryPropertySeq(CDRMessage_t* msg, BinaryPropertySeq& binary_properties)
{
    assert(msg);

    uint32_t length = 0;
    if(!CDRMessage::readUInt32(msg, &length))
        return false;

    binary_properties.resize(length);
    bool returnedValue = true;
    for(uint32_t i = 0; returnedValue && i < length; ++i)
        returnedValue = CDRMessage::readBinaryProperty(msg, binary_properties.at(i));

    return returnedValue;
}

inline bool CDRMessage::addDataHolder(CDRMessage_t* msg, const DataHolder& data_holder)
{
    assert(msg);

    if(!CDRMessage::addString(msg, data_holder.class_id()))
        return false;
    if(!CDRMessage::addPropertySeq(msg, data_holder.properties()))
        return false;
    if(!CDRMessage::addBinaryPropertySeq(msg, data_holder.binary_properties()))
        return false;

    return true;
}

inline bool CDRMessage::readDataHolder(CDRMessage_t* msg, DataHolder& data_holder)
{
    assert(msg);

    if(!CDRMessage::readString(msg, &data_holder.class_id()))
        return false;
    if(!CDRMessage::readPropertySeq(msg, data_holder.properties()))
        return false;
    if(!CDRMessage::readBinaryPropertySeq(msg, data_holder.binary_properties()))
        return false;

    return true;

}

inline bool CDRMessage::addDataHolderSeq(CDRMessage_t* msg, const DataHolderSeq& data_holders)
{
    assert(msg);

    bool returnedValue = false;

    if(msg->pos + 4 <=  msg->max_size)
    {
        if(CDRMessage::addUInt32(msg, data_holders.size()))
        {
            returnedValue = true;
            for(auto data_holder = data_holders.begin(); returnedValue && data_holder != data_holders.end(); ++data_holder)
                returnedValue = CDRMessage::addDataHolder(msg, *data_holder);
        }
    }

    return returnedValue;
}

inline bool CDRMessage::readDataHolderSeq(CDRMessage_t* msg, DataHolderSeq& data_holders)
{
    assert(msg);

    uint32_t length = 0;
    if(!CDRMessage::readUInt32(msg, &length))
        return false;

    data_holders.resize(length);
    bool returnedValue = true;
    for(uint32_t i = 0; returnedValue && i < length; ++i)
        returnedValue = CDRMessage::readDataHolder(msg, data_holders.at(i));

    return returnedValue;
}

inline bool CDRMessage::addMessageIdentity(CDRMessage_t* msg, const ::security::MessageIdentity& message_identity)
{
    assert(msg);

    if(!CDRMessage::addData(msg, message_identity.source_guid().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::addData(msg, message_identity.source_guid().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::addInt64(msg, message_identity.sequence_number()))
        return false;

    return true;
}

inline bool CDRMessage::readMessageIdentity(CDRMessage_t* msg, ::security::MessageIdentity& message_identity)
{
    assert(msg);

    if(!CDRMessage::readData(msg, message_identity.source_guid().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::readData(msg, message_identity.source_guid().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::readInt64(msg, &message_identity.sequence_number()))
        return false;

    return true;
}

inline bool CDRMessage::addParticipantGenericMessage(CDRMessage_t* msg, const ::security::ParticipantGenericMessage& message)
{
    assert(msg);

    if(!CDRMessage::addMessageIdentity(msg, message.message_identity()))
        return false;
    if(!CDRMessage::addMessageIdentity(msg, message.related_message_identity()))
        return false;
    if(!CDRMessage::addData(msg, message.destination_participant_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::addData(msg, message.destination_participant_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::addData(msg, message.destination_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::addData(msg, message.destination_endpoint_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::addData(msg, message.source_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::addData(msg, message.source_endpoint_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::addString(msg, message.message_class_id()))
        return false;
    if(!CDRMessage::addDataHolderSeq(msg, message.message_data()))
        return false;

    return true;
}

inline bool CDRMessage::readParticipantGenericMessage(CDRMessage_t* msg, ::security::ParticipantGenericMessage& message)
{
    assert(msg);

    if(!CDRMessage::readMessageIdentity(msg, message.message_identity()))
        return false;
    if(!CDRMessage::readMessageIdentity(msg, message.related_message_identity()))
        return false;
    if(!CDRMessage::readData(msg, message.destination_participant_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::readData(msg, message.destination_participant_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::readData(msg, message.destination_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::readData(msg, message.destination_endpoint_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::readData(msg, message.source_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
        return false;
    if(!CDRMessage::readData(msg, message.source_endpoint_key().entityId.value, EntityId_t::size))
        return false;
    if(!CDRMessage::readString(msg, &message.message_class_id()))
        return false;
    if(!CDRMessage::readDataHolderSeq(msg, message.message_data()))
        return false;

    return true;
}

// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_
#define _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_

#include "../../common/Guid.h"
#include "../../common/Token.h"

namespace eprosima {
namespace fastrtps {
namespace rtps {
namespace security {

class MessageIdentity
{
    public:

        MessageIdentity() : sequence_number_(0) {}

        MessageIdentity(const MessageIdentity& mi) :
            source_guid_(mi.source_guid_),
            sequence_number_(mi.sequence_number_)
        {
        }

        MessageIdentity(MessageIdentity&& mi) :
            source_guid_(std::move(mi.source_guid_)),
            sequence_number_(mi.sequence_number_)
        {
        }

        MessageIdentity& operator=(const MessageIdentity& mi)
        {
            source_guid_ = mi.source_guid_;
            sequence_number_ = mi.sequence_number_;
            return *this;
        }

        MessageIdentity& operator=(MessageIdentity&& mi)
        {
            source_guid_ = std::move(mi.source_guid_);
            sequence_number_ = mi.sequence_number_;
            return *this;
        }

        void source_guid(const GUID_t& source_guid)
        {
            source_guid_ = source_guid;
        }

        void source_guid(GUID_t&& source_guid)
        {
            source_guid_ = std::move(source_guid);
        }

        const GUID_t& source_guid() const
        {
            return source_guid_;
        }

        GUID_t& source_guid()
        {
            return source_guid_;
        }

        void sequence_number(int64_t sequence_number)
        {
            sequence_number_ = sequence_number;
        }

        int64_t sequence_number() const
        {
            return sequence_number_;
        }

        int64_t& sequence_number()
        {
            return sequence_number_;
        }

    private:

        GUID_t source_guid_;
        int64_t sequence_number_;
};

class MessageIdentityHelper
{
    public:

        static size_t serialized_size(const MessageIdentity& /*message*/, size_t current_alignment = 0)
        {
            size_t initial_alignment = current_alignment;

            current_alignment += 16;
            current_alignment +=  alignment(current_alignment, 8) + 8;

            return current_alignment - initial_alignment;
        }

    private:

        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
};

class ParticipantGenericMessage
{
    public:

        ParticipantGenericMessage() {}

        ParticipantGenericMessage(const ParticipantGenericMessage& message) :
            message_identity_(message.message_identity_),
            related_message_identity_(message.related_message_identity_),
            destination_participant_key_(message.destination_participant_key_),
            destination_endpoint_key_(message.destination_endpoint_key_),
            source_endpoint_key_(message.source_endpoint_key_),
            message_class_id_(message.message_class_id_),
            message_data_(message.message_data_)
        {}

        ParticipantGenericMessage(ParticipantGenericMessage&& message) :
            message_identity_(std::move(message.message_identity_)),
            related_message_identity_(std::move(message.related_message_identity_)),
            destination_participant_key_(std::move(message.destination_participant_key_)),
            destination_endpoint_key_(std::move(message.destination_endpoint_key_)),
            source_endpoint_key_(std::move(message.source_endpoint_key_)),
            message_class_id_(std::move(message.message_class_id_)),
            message_data_(std::move(message.message_data_))
        {}

        ParticipantGenericMessage& operator=(const ParticipantGenericMessage& message)
        {
            message_identity_ = message.message_identity_;
            related_message_identity_ = message.related_message_identity_;
            destination_participant_key_ = message.destination_participant_key_;
            destination_endpoint_key_ = message.destination_endpoint_key_;
            source_endpoint_key_ = message.source_endpoint_key_;
            message_class_id_ = message.message_class_id_;
            message_data_ = message.message_data_;
            return *this;
        }

        ParticipantGenericMessage& operator=(ParticipantGenericMessage&& message)
        {
            message_identity_ = std::move(message.message_identity_);
            related_message_identity_ = std::move(message.related_message_identity_);
            destination_participant_key_ = std::move(message.destination_participant_key_);
            destination_endpoint_key_ = std::move(message.destination_endpoint_key_);
            source_endpoint_key_ = std::move(message.source_endpoint_key_);
            message_class_id_ = std::move(message.message_class_id_);
            message_data_ = std::move(message.message_data_);
            return *this;
        }

        void message_identity(const MessageIdentity& message_identity)
        {
            message_identity_ = message_identity;
        }

        void message_identity(MessageIdentity&& message_identity)
        {
            message_identity_ = std::move(message_identity);
        }

        const MessageIdentity& message_identity() const
        {
            return message_identity_;
        }

        MessageIdentity& message_identity()
        {
            return message_identity_;
        }

        void related_message_identity(const MessageIdentity& related_message_identity)
        {
            related_message_identity_ = related_message_identity;
        }

        void related_message_identity(MessageIdentity&& related_message_identity)
        {
            related_message_identity_ = std::move(related_message_identity);
        }

        const MessageIdentity& related_message_identity() const
        {
            return related_message_identity_;
        }

        MessageIdentity& related_message_identity()
        {
            return related_message_identity_;
        }

        void destination_participant_key(const GUID_t& destination_participant_key)
        {
            destination_participant_key_ = destination_participant_key;
        }

        void destination_participant_key(GUID_t&& destination_participant_key)
        {
            destination_participant_key_ = std::move(destination_participant_key);
        }

        const GUID_t& destination_participant_key() const
        {
            return destination_participant_key_;
        }

        GUID_t& destination_participant_key()
        {
            return destination_participant_key_;
        }

        void destination_endpoint_key(const GUID_t& destination_endpoint_key)
        {
            destination_endpoint_key_ = destination_endpoint_key;
        }

        void destination_endpoint_key(GUID_t&& destination_endpoint_key)
        {
            destination_endpoint_key_ = std::move(destination_endpoint_key);
        }

        const GUID_t& destination_endpoint_key() const
        {
            return destination_endpoint_key_;
        }

        GUID_t& destination_endpoint_key()
        {
            return destination_endpoint_key_;
        }

        void source_endpoint_key(const GUID_t& source_endpoint_key)
        {
            source_endpoint_key_ = source_endpoint_key;
        }

        void source_endpoint_key(GUID_t&& source_endpoint_key)
        {
            source_endpoint_key_ = std::move(source_endpoint_key);
        }

        const GUID_t& source_endpoint_key() const
        {
            return source_endpoint_key_;
        }

        GUID_t& source_endpoint_key()
        {
            return source_endpoint_key_;
        }

        void message_class_id(const std::string& message_class_id)
        {
            message_class_id_ = message_class_id;
        }

        void message_class_id(std::string&& message_class_id)
        {
            message_class_id_ = std::move(message_class_id);
        }

        const std::string& message_class_id() const
        {
            return message_class_id_;
        }

        std::string& message_class_id()
        {
            return message_class_id_;
        }

        void message_data(const DataHolderSeq& message_data)
        {
            message_data_ = message_data;
        }

        void message_data(DataHolderSeq&& message_data)
        {
            message_data_ = std::move(message_data);
        }

        const DataHolderSeq& message_data() const
        {
            return message_data_;
        }

        DataHolderSeq& message_data()
        {
            return message_data_;
        }

    private:

        MessageIdentity message_identity_;
        MessageIdentity related_message_identity_;
        GUID_t destination_participant_key_;
        GUID_t destination_endpoint_key_;
        GUID_t source_endpoint_key_;
        std::string message_class_id_;
        DataHolderSeq message_data_;
};

class ParticipantGenericMessageHelper
{
    public:

        static size_t serialized_size(const ParticipantGenericMessage& message, size_t current_alignment = 0)
        {
            size_t initial_alignment = current_alignment;

            current_alignment += MessageIdentityHelper::serialized_size(message.message_identity(), current_alignment);
            current_alignment += MessageIdentityHelper::serialized_size(message.related_message_identity(), current_alignment);
            current_alignment += 16 * 3;
            current_alignment += 4 + alignment(current_alignment, 4) + message.message_class_id().size() + 1;
            current_alignment += DataHolderHelper::serialized_size(message.message_data(), current_alignment);

            return current_alignment - initial_alignment;
        }

    private:

        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
};

} //namespace security
} //namespace rtps
} //namespace fastrtps
} //namespace eprosima

#endif // _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_

    set(HAVE_SECURITY 1)
else()
    set(HAVE_SECURITY 0)

size_t DataHolderHelper::serialized_size(const DataHolder& data_holder, size_t current_alignment)
{
    size_t initial_alignment = current_alignment;

    current_alignment += 4 + alignment(current_alignment, 4) + data_holder.class_id().size() + 1;
    current_alignment += PropertyHelper::serialized_size(data_holder.properties(), current_alignment);
    current_alignment += BinaryPropertyHelper::serialized_size(data_holder.binary_properties(), current_alignment);

    return current_alignment - initial_alignment;
}

size_t DataHolderHelper::serialized_size(const DataHolderSeq& data_holders, size_t current_alignment)
{
    size_t initial_alignment = current_alignment;

    current_alignment += 4 + alignment(current_alignment, 4);
    for(auto data_holder = data_holders.begin(); data_holder != data_holders.end(); ++data_holder)
        current_alignment += serialized_size(*data_holder, current_alignment);

    return current_alignment - initial_alignment;
}
#define AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE "dds.sec.auth"

// TODO(Ricardo) Add event because stateless messages can be not received.
// TODO(Ricardo) Add following of sequence in stateless messages.

SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : 
    participant_stateless_message_listener_(*this),
    participant_(participant),
    {
        SecurityException exception;

        for(auto& dp_it : discovered_participants_)
        {
            if(!dp_it.second.is_handshake_handle_null())
            {
                HandshakeHandle* handle = dp_it.second.get_handshake_handle();
                authentication_plugin_->return_handshake_handle(handle, exception);
            }

            if(!dp_it.second.is_identity_handle_null())
            {
                IdentityHandle* handle = dp_it.second.get_identity_handle();
                authentication_plugin_->return_identity_handle(handle, exception);
            }
        }

        if(local_identity_handle_ != nullptr)
            authentication_plugin_->return_identity_handle(local_identity_handle_, exception);

        delete_entities();

    }
        IdentityHandle* remote_identity_handle,
        HandshakeHandle* handshake_handle)
        assert(dp_it->second.is_handshake_handle_null());
        dp_it->second.set_handshake_handle(handshake_handle);
    {

        if(handshake_handle)
            authentication_plugin_->return_handshake_handle(handshake_handle, exception);
    }
    if(authentication_plugin_ == nullptr)
        return true;

    int64_t last_sequence_number = 0;

        last_sequence_number = dp_it->second.get_last_sequence_number();

        returnedValue = on_process_handshake(remote_participant_key, AUTHENTICATION_REQUEST_NOT_SEND,
                MessageIdentity(), HandshakeMessageToken(),
                remote_identity_handle, nullptr, last_sequence_number);
bool SecurityManager::on_process_handshake(const GUID_t& remote_participant_key,
        AuthenticationStatus pre_auth_status,
        MessageIdentity&& message_identity,
        HandshakeMessageToken&& message_in,
        IdentityHandle* remote_identity_handle,
        HandshakeHandle* handshake_handle, int64_t last_sequence_number)
    ValidationResult_t ret = VALIDATION_FAILED;
    
    if(pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
    {
        ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
    }
    else if(pre_auth_status == AUTHENTICATION_WAITING_REQUEST)
    {
        assert(!handshake_handle);
        ret = authentication_plugin_->begin_handshake_reply(&handshake_handle,
                &handshake_message,
                std::move(message_in),
                *remote_identity_handle,
                *local_identity_handle_,
                exception);
    }
    else if(pre_auth_status == AUTHENTICATION_WAITING_REPLY ||
            pre_auth_status == AUTHENTICATION_WAITING_FINAL)
    {
        assert(handshake_handle);
        ret = authentication_plugin_->process_handshake(&handshake_message,
                std::move(message_in),
                *handshake_handle, 
                exception);
    }
        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
    bool handshake_message_send = true;
    if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE ||
            ret == VALIDATION_OK_WITH_FINAL_MESSAGE)
        handshake_message_send = false;
        assert(handshake_message);
        // Send hanshake message
        // Create message
        ParticipantGenericMessage message = generate_authentication_message(last_sequence_number,
                std::move(message_identity), remote_participant_key, std::move(*handshake_message));

        CacheChange_t* change = participant_stateless_message_writer_->new_change([&message]() -> uint32_t
                {
                return ParticipantGenericMessageHelper::serialized_size(message);
                }
                , ALIVE, c_InstanceHandle_Unknown);

        if(change != nullptr)
        {
            // Serialize message
            CDRMessage_t aux_msg(0);
            aux_msg.wraps = true;
            aux_msg.buffer = change->serializedPayload.data;
            aux_msg.length = change->serializedPayload.length;
            aux_msg.max_size = change->serializedPayload.max_size;
            aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;

            if(CDRMessage::addParticipantGenericMessage(&aux_msg, message))
            {
                // Send
                if(participant_stateless_message_writer_history_->add_change(change))
                {
                    handshake_message_send = true;
                }
                else
                {
                    logError(SECURITY, "WriterHistory cannot add the CacheChange_t");
                }
            }
            else
            {
                logError(SECURITY, "Cannot serialize ParticipantGenericMessage");
            }
        }
        else
        {
            logError(SECURITY, "WriterHistory cannot retrieve a CacheChange_t");
        }
    }

    bool returnedValue = false;

    if(handshake_message_send)
        AuthenticationStatus auth_status = AUTHENTICATION_FAILED;

        switch(ret)
        {
            case VALIDATION_OK:
            case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
            case VALIDATION_OK_WITH_FINAL_MESSAGE:
                {
                    auth_status = AUTHENTICATION_OK;
                    if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE)
                    {
                        if(pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
                            auth_status = AUTHENTICATION_WAITING_REPLY;
                        else if(pre_auth_status == AUTHENTICATION_WAITING_REQUEST)
                            auth_status = AUTHENTICATION_WAITING_FINAL;
                    }

                    // Store status
                    std::unique_lock<std::mutex> lock(mutex_);

                    auto dp_it = discovered_participants_.find(remote_participant_key);

                    if(dp_it != discovered_participants_.end())
                    {
                        assert(dp_it->second.get_auth_status() == pre_auth_status);
                        dp_it->second.set_auth_status(auth_status);
                        assert(dp_it->second.is_identity_handle_null());
                        dp_it->second.set_identity_handle(remote_identity_handle);
                        remote_identity_handle = nullptr;
                        assert(dp_it->second.is_handshake_handle_null());
                        dp_it->second.set_handshake_handle(handshake_handle);
                        handshake_handle = nullptr;
                        if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE ||
                                ret == VALIDATION_OK_WITH_FINAL_MESSAGE)
                            dp_it->second.set_last_sequence_number(++last_sequence_number);

                        returnedValue = true;
                    }
                    else
                    {
                        authentication_plugin_->return_handshake_handle(handshake_handle, exception);
                        handshake_handle = nullptr;
                        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
                        remote_identity_handle = nullptr;
                    }
                }
                break;
            case VALIDATION_PENDING_RETRY:
                // TODO(Ricardo) Send event.
            default:
                break;
        };

    if(handshake_handle != nullptr && (pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND ||
                pre_auth_status == AUTHENTICATION_WAITING_REQUEST))
        handshake_handle = nullptr;
    if(remote_identity_handle != nullptr)
        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
    delete handshake_message;

    return returnedValue;
void SecurityManager::delete_entities()
{
    delete_participant_stateless_message_entities();
}

        auth_source_guid = participant_stateless_message_writer_->getGuid();
    {
        participant_stateless_message_writer_ = nullptr;
    }
    {
        participant_stateless_message_writer_history_ = nullptr;
    }
    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, &participant_stateless_message_listener_,
                participant_stateless_message_reader_entity_id, true, false))
    {
        participant_stateless_message_reader_ = nullptr;
    }
    {
        participant_stateless_message_reader_history_ = nullptr;
    }
}

ParticipantGenericMessage SecurityManager::generate_authentication_message(int64_t sequence_number,
        const MessageIdentity& related_message_identity,
        const GUID_t& destination_participant_key,
        HandshakeMessageToken&& handshake_message)
{
    ParticipantGenericMessage message;

    message.message_identity().source_guid(auth_source_guid);
    message.message_identity().sequence_number(sequence_number);
    message.related_message_identity(related_message_identity);
    message.destination_participant_key(destination_participant_key);
    message.message_class_id(AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE);
    message.message_data().push_back(std::move(handshake_message));

    return message;
}

void SecurityManager::process_participant_stateless_message(const CacheChange_t* const change)
{
    assert(change);

    // Deserialize message
    ParticipantGenericMessage message;
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.length = change->serializedPayload.length;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;

    CDRMessage::readParticipantGenericMessage(&aux_msg, message);

    if(message.message_class_id().compare(AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE) == 0)
    {
        if(message.destination_endpoint_key() != GUID_t::unknown())
        {
            logInfo(SECURITY, "Bad ParticipantGenericMessage. destination_endpoint_key is not GUID_t::unknown()");
            return;
        }
        if(message.source_endpoint_key() != GUID_t::unknown())
        {
            logInfo(SECURITY, "Bad ParticipantGenericMessage. source_endpoint_key is not GUID_t::unknown()");
            return;
        }

        const GUID_t& remote_participant_key = message.destination_participant_key();
        AuthenticationStatus auth_status;
        IdentityHandle* remote_identity_handle = nullptr;
        HandshakeHandle* handshake_handle = nullptr;
        int64_t last_sequence_number = 0;

        mutex_.lock();
        auto dp_it = discovered_participants_.find(remote_participant_key);

        if(dp_it != discovered_participants_.end())
        {
            auth_status = dp_it->second.get_auth_status();
            remote_identity_handle = dp_it->second.get_identity_handle();
            handshake_handle = dp_it->second.get_handshake_handle();
            last_sequence_number = dp_it->second.get_last_sequence_number();
        }
        else
        {
            logInfo(SECURITY, "Received Authentication message but not found related remote_participant_key");
        }
        mutex_.unlock();

        if(remote_identity_handle != nullptr)
        {
            if(auth_status == AUTHENTICATION_WAITING_REQUEST)
            {
                assert(!handshake_handle);

                // Preconditions
                if(message.message_identity().source_guid() == GUID_t::unknown())
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_identity.source_guid is GUID_t::unknown()");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
                    return;
                }
                if(message.related_message_identity().source_guid() != GUID_t::unknown())
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. related_message_identity.source_guid is not GUID_t::unknown()");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
                    return;
                }
                if(message.message_data().size() != 1)
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_data size is not 1");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
                    return;
                }
            }
            else if(auth_status == AUTHENTICATION_WAITING_REPLY ||
                    auth_status == AUTHENTICATION_WAITING_FINAL)
            {
                assert(handshake_handle);

                // Preconditions
                if(message.message_identity().source_guid() == GUID_t::unknown())
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_identity.source_guid is GUID_t::unknown()");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
                    return;
                }
                if(message.related_message_identity().source_guid() == GUID_t::unknown())
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. related_message_identity.source_guid is GUID_t::unknown()");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
                    return;
                }
                if(message.message_data().size() != 1)
                {
                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_data size is not 1");
                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
                    return;
                }
            }
            else
            {
                restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
                return;
            }

            on_process_handshake(remote_participant_key, auth_status, std::move(message.related_message_identity()),
                    std::move(message.message_data().at(0)), remote_identity_handle,
                    handshake_handle, last_sequence_number);
        }
    }
    else
    {
        logInfo(SECURITY, "Discarted ParticipantGenericMessage with class id " << message.message_class_id());
    }
}

void SecurityManager::ParticipantStatelessMessageListener::onNewCacheChangeAdded(RTPSReader* reader,
        const CacheChange_t* const change)
{
    manager_.process_participant_stateless_message(change);

    ReaderHistory *history = reader->getHistory();
    assert(history);
    history->remove_change((CacheChange_t*)change);
#include <fastrtps/rtps/security/common/ParticipantGenericMessage.h>
#include <fastrtps/rtps/reader/ReaderListener.h>
                    auth_status_(auth_status), last_sequence_number_(1)
                {}
                void set_last_sequence_number(int64_t sequence_number)
                {
                    last_sequence_number_ = sequence_number;
                }

                int64_t get_last_sequence_number()
                {
                    return last_sequence_number_;
                }


                int64_t last_sequence_number_;
        class ParticipantStatelessMessageListener: public eprosima::fastrtps::rtps::ReaderListener
        {
            public:
                ParticipantStatelessMessageListener(SecurityManager &manager) : manager_(manager) {};

                ~ParticipantStatelessMessageListener(){};

                void onNewCacheChangeAdded(RTPSReader* reader, const CacheChange_t* const change);

            private:

                ParticipantStatelessMessageListener& operator=(const ParticipantStatelessMessageListener&) NON_COPYABLE_CXX11;

                SecurityManager &manager_;
        } participant_stateless_message_listener_;

                IdentityHandle* remote_identity_handle,
                HandshakeHandle* handshake_handle = nullptr);
        void process_participant_stateless_message(const CacheChange_t* const change);

        bool on_process_handshake(const GUID_t& remote_participant_key,
                AuthenticationStatus pre_auth_status,
                MessageIdentity&& message_identity,
                HandshakeMessageToken&& message,
                IdentityHandle* remote_identity_handle,
                HandshakeHandle* handshake_handle,
                int64_t last_sequence_number);

        ParticipantGenericMessage generate_authentication_message(int64_t sequence_number,
                const MessageIdentity& related_message_identity,
                const GUID_t& destination_participant_key,
                HandshakeMessageToken&& handshake_message);
        GUID_t auth_source_guid;

#include <fastrtps/rtps/writer/RTPSWriter.h>
#include <fastrtps/rtps/reader/RTPSReader.h>
        MOCK_METHOD6(createWriter_mock, bool (RTPSWriter** writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
        MOCK_METHOD7(createReader_mock, bool (RTPSReader** reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,

        bool createWriter(RTPSWriter** writer, WriterAttributes& param, WriterHistory* hist, WriterListener* listen,
                const EntityId_t& entityId, bool isBuiltin)
        {
            bool ret = createWriter_mock(writer, param , hist, listen, entityId, isBuiltin);
            if(*writer != nullptr)
                (*writer)->history_ = hist;
            return ret;
        }

        bool createReader(RTPSReader** reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
                const EntityId_t& entityId, bool isBuiltin, bool enable)
        {
            bool ret = createReader_mock(reader, param, hist, listen, entityId, isBuiltin, enable);
            if(*reader != nullptr)
            {
                (*reader)->history_ = hist;
                (*reader)->listener_ = listen;
            }
            return ret;
        }
#include <fastrtps/rtps/history/ReaderHistory.h>
#include <fastrtps/rtps/reader/ReaderListener.h>

#include <gmock/gmock.h>


        MOCK_METHOD0(getHistory_mock, ReaderHistory*());

        ReaderHistory* getHistory()
        {
            getHistory_mock();
            return history_;
        }

        ReaderHistory* history_;

        ReaderListener* listener_;
#include <gmock/gmock.h>

class WriterHistory;


        MOCK_METHOD3(new_change, CacheChange_t*(const std::function<uint32_t()>&,
            ChangeKind_t, InstanceHandle_t));

        WriterHistory* history_;
#include <gmock/gmock.h>


        MOCK_METHOD1(remove_change, bool(CacheChange_t*));
    Authentication* ret =  auth_plugin_;
    auth_plugin_ = nullptr;
    return ret;
    if(auth_plugin_ != nullptr)
    {
        delete auth_plugin_;
        auth_plugin_ = nullptr;
    }

        MOCK_METHOD0(getGuid, const GUID_t&());

        MOCK_METHOD1(add_change, bool(CacheChange_t*));
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Token.cpp
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
#include <fastrtps/rtps/writer/StatelessWriter.h>
#include <fastrtps/rtps/history/WriterHistory.h>
#include <fastrtps/rtps/reader/StatelessReader.h>
#include <fastrtps/rtps/history/ReaderHistory.h>
void fill_participant_key(GUID_t& participant_key)
{
    participant_key.guidPrefix.value[0] = 1;
    participant_key.guidPrefix.value[1] = 2;
    participant_key.guidPrefix.value[2] = 3;
    participant_key.guidPrefix.value[3] = 4;
    participant_key.guidPrefix.value[4] = 5;
    participant_key.guidPrefix.value[5] = 6;
    participant_key.guidPrefix.value[6] = 7;
    participant_key.guidPrefix.value[7] = 8;
    participant_key.guidPrefix.value[8] = 9;
    participant_key.guidPrefix.value[9] = 10;
    participant_key.guidPrefix.value[10] = 11;
    participant_key.guidPrefix.value[11] = 12;
    participant_key.entityId.value[0] = 13;
    participant_key.entityId.value[1] = 14;
    participant_key.entityId.value[2] = 15;
    participant_key.entityId.value[3] = 16;
}

            fill_participant_key(guid);
            stateless_writer_ = new NiceMock<StatelessWriter>();
            stateless_reader_ = new NiceMock<StatelessReader>();
            EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(stateless_writer_), Return(true)));
            EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(stateless_reader_), Return(true)));
        void request_process_ok()
        {
            initialization_ok();

            MockIdentityHandle identity_handle;
            MockIdentityHandle* p_identity_handle = &identity_handle;
            MockHandshakeHandle handshake_handle;
            MockHandshakeHandle* p_handshake_handle = &handshake_handle;
            HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
            CacheChange_t* change = new CacheChange_t(200);

            EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
            EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                            SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
            EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
                WillOnce(Return(change));
            EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
                WillOnce(Return(true));

            GUID_t remote_participant_key;
            fill_participant_key(remote_participant_key);
            ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

            delete change;
        }

        void reply_process_ok()
        {
            initialization_ok();

            MockIdentityHandle identity_handle;
            MockIdentityHandle* p_identity_handle = &identity_handle;

            EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

            GUID_t remote_participant_key;
            fill_participant_key(remote_participant_key);
            ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

            ParticipantGenericMessage message;
            message.message_identity().source_guid(remote_participant_key);
            message.destination_participant_key(remote_participant_key);
            message.message_class_id("dds.sec.auth");
            HandshakeMessageToken token;
            message.message_data().push_back(token);
            CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
            CDRMessage_t aux_msg(0);
            aux_msg.wraps = true;
            aux_msg.buffer = change->serializedPayload.data;
            aux_msg.max_size = change->serializedPayload.max_size;
            aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
            ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
            change->serializedPayload.length = aux_msg.length;

            MockHandshakeHandle handshake_handle;
            MockHandshakeHandle* p_handshake_handle = &handshake_handle;
            HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
            CacheChange_t* change2 = new CacheChange_t(200);

            EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
                WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                            SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
            EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
                WillOnce(Return(change2));
            EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
                WillOnce(Return(true));
            EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
                WillOnce(Return(true));

            stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

            delete change2;
        }
        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()),
        stateless_writer_(nullptr), stateless_reader_(nullptr), manager_(&participant_) {}

        ~SecurityAuthenticationTest()
        {
        }

        NiceMock<StatelessWriter>* stateless_writer_;
        NiceMock<StatelessReader>* stateless_reader_;
    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(stateless_writer), Return(true)));
    EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
    NiceMock<StatelessReader>* stateless_reader = new NiceMock<StatelessReader>();
    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(stateless_writer), Return(true)));
    EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(stateless_reader), Return(true)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
                    Return(ValidationResult_t::VALIDATION_OK)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_new_change_fail)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;
    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(nullptr));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
}

TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_add_change_fail)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;
    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
    CacheChange_t* change = new CacheChange_t(200);

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
        WillOnce(Return(false));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    delete change;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_pending_message)
{
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    request_process_ok();
}

    CacheChange_t* change = new CacheChange_t(200);
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    delete change;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_not_remote_participant_key)
{
    initialization_ok();

    ParticipantGenericMessage message;
    message.message_class_id("dds.sec.auth");
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_bad_message_class_id)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_not_expecting_request)
{
    initialization_ok();
    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_begin_handshake_reply)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_begin_handshake_reply)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;

    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    Return(ValidationResult_t::VALIDATION_OK)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_new_change_fail)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();

    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(nullptr));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_add_change_fail)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
    CacheChange_t* change2 = new CacheChange_t(200);

    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change2));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
        WillOnce(Return(false));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change2;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_pending_handshake_reply_pending_message)
{
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    reply_process_ok();
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_pending_handshake_reply_ok_with_final_message)
{
    initialization_ok();

    MockIdentityHandle identity_handle;
    MockIdentityHandle* p_identity_handle = &identity_handle;

    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);
    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    MockHandshakeHandle handshake_handle;
    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
    CacheChange_t* change2 = new CacheChange_t(200);

    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change2));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change2;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_process_handshake_reply)
{
    request_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_process_handshake_reply)
{
    request_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_new_change_fail)
{
    request_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(nullptr));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_add_change_fail)
{
    request_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
    CacheChange_t* change2 = new CacheChange_t(200);

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change2));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
        WillOnce(Return(false));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change2;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_ok_with_final_message)
{
    request_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
    CacheChange_t* change2 = new CacheChange_t(200);

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
        WillOnce(Return(change2));
    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change2;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_process_handshake_final)
{
    reply_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);

    delete change;
}

TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_process_handshake_final)
{
    reply_process_ok();

    GUID_t remote_participant_key;
    fill_participant_key(remote_participant_key);

    ParticipantGenericMessage message;
    message.message_identity().source_guid(remote_participant_key);
    message.related_message_identity().source_guid(remote_participant_key);
    message.destination_participant_key(remote_participant_key);
    message.message_class_id("dds.sec.auth");
    HandshakeMessageToken token;
    message.message_data().push_back(token);
    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
    CDRMessage_t aux_msg(0);
    aux_msg.wraps = true;
    aux_msg.buffer = change->serializedPayload.data;
    aux_msg.max_size = change->serializedPayload.max_size;
    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
    change->serializedPayload.length = aux_msg.length;

    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
        WillOnce(Return(true));

    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);