LCOV - code coverage report
Current view: top level - DCPS/security - AuthenticationBuiltInImpl.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 531 737 72.0 %
Date: 2023-04-30 01:32:43 Functions: 29 43 67.4 %

          Line data    Source code
       1             : /*
       2             : *
       3             : *
       4             : * Distributed under the OpenDDS License.
       5             : * See: http://www.opendds.org/license.html
       6             : */
       7             : 
       8             : #include "AuthenticationBuiltInImpl.h"
       9             : 
      10             : #include "CommonUtilities.h"
      11             : #include "TokenReader.h"
      12             : #include "TokenWriter.h"
      13             : #include "SSL/Utils.h"
      14             : 
      15             : #include "dds/DCPS/GuidUtils.h"
      16             : #include "dds/DCPS/LocalObject.h"
      17             : #include "dds/DCPS/Serializer.h"
      18             : 
      19             : #include "dds/DCPS/RTPS/RtpsCoreC.h"
      20             : #include "dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.h"
      21             : 
      22             : #include "ace/config-macros.h"
      23             : #include "ace/Guard_T.h"
      24             : 
      25             : #include <sstream>
      26             : #include <vector>
      27             : #include <algorithm>
      28             : #include <cstdio>
      29             : 
      30             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      31             : 
      32             : namespace OpenDDS {
      33             : namespace Security {
      34             : 
      35             : using CommonUtilities::set_security_error;
      36             : 
      37             : static bool challenges_match(const DDS::OctetSeq& c1, const DDS::OctetSeq& c2);
      38             : 
      39             : static void extract_participant_guid_from_cpdata(const DDS::OctetSeq& cpdata, DCPS::GUID_t& dst);
      40             : 
      41             : static bool validate_topic_data_guid(const DDS::OctetSeq& cpdata,
      42             :                                      const std::vector<unsigned char>& subject_name_hash,
      43             :                                      DDS::Security::SecurityException& ex);
      44             : 
      45             : const std::string Auth_Plugin_Name("DDS:Auth:PKI-DH");
      46             : const std::string Auth_Plugin_Major_Version("1");
      47             : const std::string Auth_Plugin_Minor_Version("0");
      48             : 
      49             : const std::string Auth_Request_Class_Ext("AuthReq");
      50             : const std::string Handshake_Request_Class_Ext("Req");
      51             : const std::string Handshake_Reply_Class_Ext("Reply");
      52             : const std::string Handshake_Final_Class_Ext("Final");
      53             : 
      54             : const char* AuthenticationBuiltInImpl::PROPERTY_HANDSHAKE_DEBUG = "opendds.sec.auth.handshake_debug";
      55             : 
      56             : struct SharedSecret : DCPS::LocalObject<DDS::Security::SharedSecretHandle> {
      57             : 
      58          10 :   SharedSecret(DDS::OctetSeq challenge1,
      59             :                DDS::OctetSeq challenge2,
      60             :                DDS::OctetSeq sharedSecret)
      61          20 :     : challenge1_(challenge1)
      62          10 :     , challenge2_(challenge2)
      63          20 :     , shared_secret_(sharedSecret)
      64          10 :   {}
      65             : 
      66           0 :   DDS::OctetSeq* challenge1() { return new DDS::OctetSeq(challenge1_); }
      67           0 :   DDS::OctetSeq* challenge2() { return new DDS::OctetSeq(challenge2_); }
      68           2 :   DDS::OctetSeq* sharedSecret() { return new DDS::OctetSeq(shared_secret_); }
      69             : 
      70             :   DDS::OctetSeq challenge1_, challenge2_, shared_secret_;
      71             : };
      72             : 
      73          32 : AuthenticationBuiltInImpl::AuthenticationBuiltInImpl()
      74          32 : : listener_ptr_()
      75          32 : , identity_mutex_()
      76          32 : , handshake_mutex_()
      77          32 : , handle_mutex_()
      78          32 : , next_handle_(1)
      79             : {
      80          32 : }
      81             : 
      82          32 : AuthenticationBuiltInImpl::~AuthenticationBuiltInImpl()
      83             : {
      84          32 :   if (DCPS::security_debug.bookkeeping) {
      85           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
      86             :                ACE_TEXT("AuthenticationBuiltInImpl::~AuthenticationBuiltInImpl local_participants_ %B handshake_data_ %B\n"),
      87             :                local_participants_.size(),
      88             :                handshake_data_.size()));
      89             :   }
      90          32 : }
      91             : 
      92          22 : ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::validate_local_identity(
      93             :   ::DDS::Security::IdentityHandle & local_identity_handle,
      94             :   ::OpenDDS::DCPS::GUID_t & adjusted_participant_guid,
      95             :   ::DDS::Security::DomainId_t /*domain_id*/,
      96             :   const ::DDS::DomainParticipantQos & participant_qos,
      97             :   const ::OpenDDS::DCPS::GUID_t & candidate_participant_guid,
      98             :   ::DDS::Security::SecurityException & ex)
      99             : {
     100          22 :   DDS::Security::ValidationResult_t result = DDS::Security::VALIDATION_FAILED;
     101             : 
     102          22 :   LocalAuthCredentialData::shared_ptr credentials = DCPS::make_rch<LocalAuthCredentialData>();
     103          22 :   if (!credentials->load_credentials(participant_qos.property.value, ex)) {
     104           0 :     return result;
     105             :   }
     106             : 
     107          22 :   if (credentials->validate()) {
     108          22 :     if (candidate_participant_guid != DCPS::GUID_UNKNOWN) {
     109             : 
     110          22 :       int err = SSL::make_adjusted_guid(candidate_participant_guid,
     111             :                                         adjusted_participant_guid,
     112             :                                         credentials->get_participant_cert());
     113          22 :       if (!err) {
     114          22 :         local_identity_handle = get_next_handle();
     115             : 
     116          22 :         LocalParticipantData::shared_ptr local_participant = DCPS::make_rch<LocalParticipantData>();
     117          22 :         local_participant->participant_guid = adjusted_participant_guid;
     118          22 :         local_participant->credentials = credentials;
     119         132 :         for (unsigned i = 0; i < participant_qos.property.value.length(); ++i) {
     120         220 :           if (std::strcmp(PROPERTY_HANDSHAKE_DEBUG,
     121         110 :                           participant_qos.property.value[i].name.in()) == 0) {
     122           0 :             local_participant->handshake_debug = true;
     123             :           }
     124             :         }
     125             : 
     126             :         {
     127          22 :           ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     128          22 :           local_participants_[local_identity_handle] = local_participant;
     129             : 
     130          22 :           if (DCPS::security_debug.bookkeeping) {
     131           0 :             ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     132             :                        ACE_TEXT("AuthenticationBuiltInImpl::validate_local_identity local_participants_ (total %B)\n"),
     133             :                        local_participants_.size()));
     134             :           }
     135          22 :         }
     136             : 
     137          22 :         result = DDS::Security::VALIDATION_OK;
     138             : 
     139          22 :       } else {
     140           0 :         set_security_error(ex, -1, 0, "SSL::make_adjusted_guid failed");
     141             :       }
     142             : 
     143             :     } else {
     144           0 :       set_security_error(ex, -1, 0, "GUID_UNKNOWN passed in for candidate_participant_guid");
     145             :     }
     146             : 
     147             :   } else {
     148           0 :     set_security_error(ex, -1, 0, "local-credential-data failed validation");
     149             :   }
     150             : 
     151          22 :   return result;
     152          22 : }
     153             : 
     154          21 : ::CORBA::Boolean AuthenticationBuiltInImpl::get_identity_token(
     155             :   ::DDS::Security::IdentityToken & identity_token,
     156             :   ::DDS::Security::IdentityHandle handle,
     157             :   ::DDS::Security::SecurityException & ex)
     158             : {
     159          21 :   ::CORBA::Boolean status = false;
     160             : 
     161          21 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     162             : 
     163          21 :   LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
     164          21 :   if (local_data) {
     165          21 :     const LocalAuthCredentialData& local_credential_data = *(local_data->credentials);
     166             : 
     167          21 :     const SSL::Certificate& pcert = local_credential_data.get_participant_cert();
     168          21 :     const SSL::Certificate& cacert = local_credential_data.get_ca_cert();
     169             : 
     170          21 :     std::string tmp;
     171             : 
     172          42 :     OpenDDS::Security::TokenWriter identity_wrapper(identity_token, Identity_Status_Token_Class_Id);
     173             : 
     174          21 :     pcert.subject_name_to_str(tmp);
     175          21 :     identity_wrapper.add_property(dds_cert_sn, tmp.c_str());
     176          21 :     identity_wrapper.add_property(dds_cert_algo, pcert.keypair_algo());
     177             : 
     178          21 :     cacert.subject_name_to_str(tmp);
     179          21 :     identity_wrapper.add_property(dds_ca_sn, tmp.c_str());
     180          21 :     identity_wrapper.add_property(dds_ca_algo, cacert.keypair_algo());
     181             : 
     182          21 :     status = true;
     183             : 
     184          21 :   } else {
     185           0 :     set_security_error(ex, -1, 0, "Unknown Identity handle");
     186             :   }
     187          21 :   return status;
     188          21 : }
     189             : 
     190           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::get_identity_status_token(
     191             :   ::DDS::Security::IdentityStatusToken&,
     192             :   ::DDS::Security::IdentityHandle handle,
     193             :   ::DDS::Security::SecurityException & ex)
     194             : {
     195           0 :   ::CORBA::Boolean status = false;
     196             : 
     197           0 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     198             : 
     199             :   // Populate a simple version of an IdentityStatusToken as long as the handle is known
     200           0 :   LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
     201           0 :   if (local_data) {
     202             : 
     203             :     // TODO: Pending AuthenticationListener support (see security spec. 8.3.2.2).
     204             :     // This routine will most likely populate the IdentityStatusToken with
     205             :     // useful data once this has been completed. For now it's a glorified no-op!
     206             : 
     207           0 :     status = true;
     208             :   } else {
     209           0 :     set_security_error(ex, -1, 0, "Unknown Identity handle");
     210             :   }
     211             : 
     212           0 :   return status;
     213           0 : }
     214             : 
     215           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::set_permissions_credential_and_token(
     216             :   ::DDS::Security::IdentityHandle handle,
     217             :   const ::DDS::Security::PermissionsCredentialToken & permissions_credential,
     218             :   const ::DDS::Security::PermissionsToken & permissions_token,
     219             :   ::DDS::Security::SecurityException & ex)
     220             : {
     221             :   ACE_UNUSED_ARG(permissions_token);
     222             : 
     223           0 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     224             : 
     225           0 :   LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
     226           0 :   if (! local_data) {
     227           0 :     set_security_error(ex, -1, 0, "Identity handle not recognized");
     228           0 :     return false;
     229             :   }
     230             : 
     231           0 :   return local_data->credentials->load_access_permissions(permissions_credential, ex);
     232           0 : }
     233             : 
     234          16 : ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::validate_remote_identity(
     235             :   ::DDS::Security::IdentityHandle & remote_identity_handle,
     236             :   ::DDS::Security::AuthRequestMessageToken & local_auth_request_token,
     237             :   const ::DDS::Security::AuthRequestMessageToken & remote_auth_request_token,
     238             :   ::DDS::Security::IdentityHandle local_identity_handle,
     239             :   const ::DDS::Security::IdentityToken & remote_identity_token,
     240             :   const ::OpenDDS::DCPS::GUID_t & remote_participant_guid,
     241             :   ::DDS::Security::SecurityException & ex)
     242             : {
     243          16 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     244             : 
     245          16 :   LocalParticipantData::shared_ptr local_data = get_local_participant(local_identity_handle);
     246             : 
     247          16 :   if (!local_data) {
     248           0 :     set_security_error(ex, -1, 0, "Local participant ID not found");
     249           0 :     return DDS::Security::VALIDATION_FAILED;
     250             :   }
     251             : 
     252          16 :   if (!check_class_versions(remote_identity_token.class_id)) {
     253           0 :     set_security_error(ex, -1, 0, "Remote class ID is not compatible");
     254           0 :     return DDS::Security::VALIDATION_FAILED;
     255             :   }
     256             : 
     257             :   // Make sure that a remote_participant_guid has not already been assigned a
     258             :   // remote-identity-handle before creating a new one.
     259          16 :   RemoteParticipantMap::iterator begin = local_data->validated_remotes.begin(),
     260          16 :     end = local_data->validated_remotes.end(),
     261          16 :     found = std::find_if(begin, end,
     262             :                          was_guid_validated(remote_participant_guid));
     263             : 
     264          16 :   if (found == end) {
     265             :     // Generate local token.
     266          16 :     DDS::OctetSeq nonce;
     267          16 :     int err = SSL::make_nonce_256(nonce);
     268          16 :     if (err) {
     269           0 :       set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for future_challenge property");
     270           0 :       return DDS::Security::VALIDATION_FAILED;
     271             :     }
     272             : 
     273          16 :     TokenWriter auth_req_wrapper(local_auth_request_token, build_class_id(Auth_Request_Class_Ext));
     274          16 :     auth_req_wrapper.add_bin_property("future_challenge", nonce);
     275             : 
     276             :     // Retain all of the data needed for a handshake with the remote participant
     277          16 :     RemoteParticipantData::shared_ptr remote_participant = DCPS::make_rch<RemoteParticipantData>();
     278          16 :     remote_participant->participant_guid = remote_participant_guid;
     279          16 :     remote_participant->local_participant = local_identity_handle;
     280          16 :     remote_participant->local_auth_request = local_auth_request_token;
     281             : 
     282          16 :     remote_identity_handle = get_next_handle();
     283          16 :     found = local_data->validated_remotes.insert(std::make_pair(remote_identity_handle, remote_participant)).first;
     284             : 
     285          16 :     if (DCPS::security_debug.bookkeeping) {
     286           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     287             :                  ACE_TEXT("AuthenticationBuiltInImpl::validate_remote_identity validated_remotes (total %B)\n"),
     288             :                  local_data->validated_remotes.size()));
     289             :     }
     290          16 :   }
     291             : 
     292             :   // Update the remote token.
     293          16 :   found->second->remote_auth_request = remote_auth_request_token;
     294             : 
     295             :   // Set return values.
     296          16 :   remote_identity_handle = found->first;
     297             : 
     298             :   // Don't need to send the local token if we have a remote token.
     299          16 :   TokenReader remote_request(remote_auth_request_token);
     300          16 :   if (remote_request.is_nil()) {
     301          10 :     local_auth_request_token = found->second->local_auth_request;
     302             :   } else {
     303           6 :     local_auth_request_token = DDS::Security::Token();
     304             :   }
     305             : 
     306          16 :   if (is_handshake_initiator(local_data->participant_guid, remote_participant_guid)) {
     307           9 :     return DDS::Security::VALIDATION_PENDING_HANDSHAKE_REQUEST;
     308             :   } else {
     309           7 :     return DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
     310             :   }
     311          16 : }
     312             : 
     313           7 : ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::begin_handshake_request(
     314             :   ::DDS::Security::HandshakeHandle & handshake_handle,
     315             :   ::DDS::Security::HandshakeMessageToken & handshake_message,
     316             :   ::DDS::Security::IdentityHandle initiator_identity_handle,
     317             :   ::DDS::Security::IdentityHandle replier_identity_handle,
     318             :   const ::DDS::OctetSeq & serialized_local_participant_data,
     319             :   ::DDS::Security::SecurityException & ex)
     320             : {
     321           7 :   if (serialized_local_participant_data.length() == 0) {
     322           0 :     set_security_error(ex, -1, 0, "No participant data provided");
     323           0 :     return DDS::Security::VALIDATION_FAILED;
     324             :   }
     325             : 
     326           7 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     327             : 
     328           7 :   HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
     329             : 
     330           7 :   if (! handshake_data.first) {
     331           0 :     set_security_error(ex, -1, 0, "Unknown local participant");
     332           0 :     return DDS::Security::VALIDATION_FAILED;
     333             :   }
     334             : 
     335           7 :   if (! handshake_data.second) {
     336           0 :     set_security_error(ex, -1, 0, "Unknown remote participant");
     337           0 :     return DDS::Security::VALIDATION_FAILED;
     338             :   }
     339             : 
     340           7 :   const LocalParticipantData& local_data = *handshake_data.first;
     341           7 :   RemoteParticipantData& remote_data = *handshake_data.second;
     342             : 
     343           7 :   const LocalAuthCredentialData& local_credential_data = *local_data.credentials;
     344             : 
     345           7 :   SSL::DiffieHellman::unique_ptr diffie_hellman(new SSL::DiffieHellman(new SSL::ECDH_PRIME_256_V1_CEUM));
     346             : 
     347           7 :   OpenDDS::Security::TokenWriter message_out(handshake_message, build_class_id(Handshake_Request_Class_Ext));
     348             : 
     349             :   // Compute hash_c1 and store for later
     350             : 
     351           7 :   DDS::OctetSeq hash_c1;
     352             : 
     353             :   {
     354             :     CredentialHash hash(local_credential_data.get_participant_cert(),
     355           7 :                         *diffie_hellman,
     356             :                         serialized_local_participant_data,
     357          14 :                         local_credential_data.get_access_permissions());
     358             : 
     359           7 :     int err = hash(hash_c1);
     360           7 :     if (err) {
     361           0 :       set_security_error(ex, -1, 0, "Failed to generate credential-hash 'hash_c1'");
     362           0 :       return DDS::Security::VALIDATION_FAILED;
     363             :     }
     364             :   }
     365             : 
     366           7 :   message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
     367           7 :   message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
     368           7 :   message_out.add_bin_property("c.pdata", serialized_local_participant_data);
     369           7 :   message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
     370           7 :   message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
     371           7 :   if (local_data.handshake_debug) {
     372           0 :     message_out.add_bin_property("hash_c1", hash_c1);
     373             :   }
     374             : 
     375           7 :   DDS::OctetSeq dhpub;
     376           7 :   diffie_hellman->pub_key(dhpub);
     377           7 :   message_out.add_bin_property("dh1", dhpub);
     378             : 
     379           7 :   OpenDDS::Security::TokenReader auth_wrapper(remote_data.local_auth_request);
     380           7 :   if (auth_wrapper.is_nil()) {
     381           0 :     DDS::OctetSeq nonce;
     382           0 :     int err = SSL::make_nonce_256(nonce);
     383           0 :     if (! err) {
     384           0 :       message_out.add_bin_property("challenge1", nonce);
     385             : 
     386             :     } else {
     387           0 :       set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for challenge1 property");
     388           0 :       return DDS::Security::VALIDATION_FAILED;
     389             :     }
     390             : 
     391           0 :   } else {
     392           7 :     const DDS::OctetSeq& challenge_data = auth_wrapper.get_bin_property_value("future_challenge");
     393           7 :     message_out.add_bin_property("challenge1", challenge_data);
     394             :   }
     395             : 
     396           7 :   remote_data.initiator_identity = initiator_identity_handle;
     397           7 :   remote_data.replier_identity = replier_identity_handle;
     398           7 :   remote_data.state = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
     399           7 :   remote_data.request = handshake_message;
     400           7 :   remote_data.reply = DDS::Security::Token();
     401           7 :   remote_data.diffie_hellman = DCPS::move(diffie_hellman);
     402           7 :   remote_data.hash_c1 = hash_c1;
     403             : 
     404           7 :   if (handshake_handle == DDS::HANDLE_NIL) {
     405           7 :     handshake_handle = get_next_handle();
     406             :   }
     407             : 
     408             :   {
     409           7 :     ACE_Guard<ACE_Thread_Mutex> identity_data_guard(handshake_mutex_);
     410           7 :     handshake_data_[handshake_handle] = handshake_data;
     411             : 
     412           7 :     if (DCPS::security_debug.bookkeeping) {
     413           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     414             :                  ACE_TEXT("AuthenticationBuiltInImpl::begin_handshake_request handshake_data_ (total %B)\n"),
     415             :                  handshake_data_.size()));
     416             :     }
     417           7 :   }
     418             : 
     419           7 :   return DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
     420           7 : }
     421             : 
     422          12 : void extract_participant_guid_from_cpdata(const DDS::OctetSeq& cpdata, DCPS::GUID_t& dst)
     423             : {
     424          12 :   dst = DCPS::GUID_UNKNOWN;
     425             : 
     426          12 :   ACE_Message_Block buffer(reinterpret_cast<const char*>(cpdata.get_buffer()), cpdata.length());
     427          12 :   buffer.wr_ptr(cpdata.length());
     428             :   OpenDDS::DCPS::Serializer serializer(&buffer,
     429             :                                        DCPS::Encoding::KIND_XCDR1,
     430          12 :                                        DCPS::ENDIAN_BIG);
     431          12 :   RTPS::ParameterList params;
     432             : 
     433          12 :   if (serializer >> params) {
     434          12 :     for (unsigned int i = 0; i < params.length(); ++i) {
     435          12 :       const RTPS::Parameter& p = params[i];
     436             : 
     437          12 :       if (p._d() == RTPS::PID_PARTICIPANT_GUID) {
     438          12 :         dst = p.guid();
     439          12 :         break;
     440             :       }
     441             :     }
     442             : 
     443             :   } else {
     444           0 :     ACE_ERROR((LM_WARNING,
     445             :                ACE_TEXT("(%P|%t) WARNING: extract_participant_guid_from_cpdata, ")
     446             :                ACE_TEXT("failed to deserialize guid from cpdata.\n")));
     447             :   }
     448             : 
     449          12 : }
     450             : 
     451          12 : bool validate_topic_data_guid(const DDS::OctetSeq& cpdata,
     452             :                               const std::vector<unsigned char>& subject_name_hash,
     453             :                               DDS::Security::SecurityException& ex)
     454             : {
     455          12 :   if (cpdata.length() > 5u) { /* Enough to withstand the hash-comparison below */
     456             : 
     457             :     DCPS::GUID_t remote_participant_guid;
     458          12 :     extract_participant_guid_from_cpdata(cpdata, remote_participant_guid);
     459             : 
     460          12 :     const DCPS::GuidPrefix_t& prefix = remote_participant_guid.guidPrefix;
     461             : 
     462             :     /* Make sure first bit is set */
     463             : 
     464          12 :     if ((prefix[0] & 0x80) != 0x80) {
     465           0 :       set_security_error(ex, -1, 0, "Malformed participant_guid in 'c.pdata'; First bit must be set.");
     466           0 :       return false;
     467             :     }
     468             : 
     469             :     /* Check the following 47 bits match the subject-hash */
     470             : 
     471             :     /* First byte needs to remove the manually-set first-bit before comparison */
     472          12 :     if ((prefix[0] & 0x7F) != SSL::offset_1bit(&subject_name_hash[0], 0)) {
     473           0 :       set_security_error(ex, -1, 0, "First byte of participant_guid in 'c.pdata' does not match bits of subject-name hash in 'c.id'");
     474           0 :       return false;
     475             :     }
     476          72 :     for (size_t i = 1; i <= 5u; ++i) { /* Compare remaining 5 bytes */
     477          60 :       if (prefix[i] != SSL::offset_1bit(&subject_name_hash[0], i)) { /* Slide the hash to the right 1 so it aligns with the guid prefix */
     478           0 :         set_security_error(ex, -1, 0, "Bits 2 - 48 of 'c.pdata' participant_guid does not match first 47 bits of subject-name hash in 'c.id'");
     479           0 :         return false;
     480             :       }
     481             :     }
     482             : 
     483             :   } else {
     484           0 :     set_security_error(ex, -1, 0, "Data missing in 'c.pdata'");
     485           0 :     return false;
     486             :   }
     487             : 
     488          12 :   return true;
     489             : }
     490             : 
     491          12 : static void make_reply_signature_sequence(const DDS::OctetSeq& hash_c2,
     492             :                                           const DDS::OctetSeq& challenge2,
     493             :                                           const DDS::OctetSeq& dh2,
     494             :                                           const DDS::OctetSeq& challenge1,
     495             :                                           const DDS::OctetSeq& dh1,
     496             :                                           const DDS::OctetSeq& hash_c1,
     497             :                                           DDS::BinaryPropertySeq& dst)
     498             : {
     499          12 :   DCPS::SequenceBackInsertIterator<DDS::BinaryPropertySeq> inserter(dst);
     500             : 
     501             :   {
     502          12 :     DDS::BinaryProperty_t p;
     503          12 :     p.name = "hash_c2";
     504          12 :     p.value = hash_c2;
     505          12 :     p.propagate = true;
     506          12 :     *inserter = p;
     507          12 :   }
     508             : 
     509             :   {
     510          12 :     DDS::BinaryProperty_t p;
     511          12 :     p.name = "challenge2";
     512          12 :     p.value = challenge2;
     513          12 :     p.propagate = true;
     514          12 :     *inserter = p;
     515          12 :   }
     516             : 
     517             :   {
     518          12 :     DDS::BinaryProperty_t p;
     519          12 :     p.name = "dh2";
     520          12 :     p.value = dh2;
     521          12 :     p.propagate = true;
     522          12 :     *inserter = p;
     523          12 :   }
     524             : 
     525             :   {
     526          12 :     DDS::BinaryProperty_t p;
     527          12 :     p.name = "challenge1";
     528          12 :     p.value = challenge1;
     529          12 :     p.propagate = true;
     530          12 :     *inserter = p;
     531          12 :   }
     532             : 
     533             :   {
     534          12 :     DDS::BinaryProperty_t p;
     535          12 :     p.name = "dh1";
     536          12 :     p.value = dh1;
     537          12 :     p.propagate = true;
     538          12 :     *inserter = p;
     539          12 :   }
     540             : 
     541             :   {
     542          12 :     DDS::BinaryProperty_t p;
     543          12 :     p.name = "hash_c1";
     544          12 :     p.value = hash_c1;
     545          12 :     p.propagate = true;
     546          12 :     *inserter = p;
     547          12 :   }
     548          12 : }
     549             : 
     550          10 : static void make_final_signature_sequence(const DDS::OctetSeq& hash_c1,
     551             :                                           const DDS::OctetSeq& challenge1,
     552             :                                           const DDS::OctetSeq& dh1,
     553             :                                           const DDS::OctetSeq& challenge2,
     554             :                                           const DDS::OctetSeq& dh2,
     555             :                                           const DDS::OctetSeq& hash_c2,
     556             :                                           DDS::BinaryPropertySeq& dst)
     557             : {
     558          10 :   DCPS::SequenceBackInsertIterator<DDS::BinaryPropertySeq> inserter(dst);
     559             : 
     560             :   {
     561          10 :     DDS::BinaryProperty_t p;
     562          10 :     p.name = "hash_c1";
     563          10 :     p.value = hash_c1;
     564          10 :     p.propagate = true;
     565          10 :     *inserter = p;
     566          10 :   }
     567             : 
     568             :   {
     569          10 :     DDS::BinaryProperty_t p;
     570          10 :     p.name = "challenge1";
     571          10 :     p.value = challenge1;
     572          10 :     p.propagate = true;
     573          10 :     *inserter = p;
     574          10 :   }
     575             : 
     576             :   {
     577          10 :     DDS::BinaryProperty_t p;
     578          10 :     p.name = "dh1";
     579          10 :     p.value = dh1;
     580          10 :     p.propagate = true;
     581          10 :     *inserter = p;
     582          10 :   }
     583             : 
     584             :   {
     585          10 :     DDS::BinaryProperty_t p;
     586          10 :     p.name = "challenge2";
     587          10 :     p.value = challenge2;
     588          10 :     p.propagate = true;
     589          10 :     *inserter = p;
     590          10 :   }
     591             : 
     592             :   {
     593          10 :     DDS::BinaryProperty_t p;
     594          10 :     p.name = "dh2";
     595          10 :     p.value = dh2;
     596          10 :     p.propagate = true;
     597          10 :     *inserter = p;
     598          10 :   }
     599             : 
     600             :   {
     601          10 :     DDS::BinaryProperty_t p;
     602          10 :     p.name = "hash_c2";
     603          10 :     p.value = hash_c2;
     604          10 :     p.propagate = true;
     605          10 :     *inserter = p;
     606          10 :   }
     607          10 : }
     608             : 
     609           7 : ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::begin_handshake_reply(
     610             :   ::DDS::Security::HandshakeHandle & handshake_handle,
     611             :   ::DDS::Security::HandshakeMessageToken & handshake_message_out,
     612             :   ::DDS::Security::IdentityHandle initiator_identity_handle,
     613             :   ::DDS::Security::IdentityHandle replier_identity_handle,
     614             :   const ::DDS::OctetSeq & serialized_local_participant_data,
     615             :   ::DDS::Security::SecurityException & ex)
     616             : {
     617             :   using OpenDDS::Security::TokenWriter;
     618             :   using OpenDDS::Security::TokenReader;
     619             : 
     620           7 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
     621             : 
     622             :   // Copy the "in" part of the inout param
     623           7 :   const DDS::Security::HandshakeMessageToken request_token = handshake_message_out;
     624           7 :   handshake_message_out = DDS::Security::HandshakeMessageToken();
     625             : 
     626           7 :   DDS::OctetSeq challenge1, challenge2, dh2, cperm, hash_c1, hash_c2;
     627             : 
     628           7 :   SSL::Certificate::unique_ptr remote_cert(new SSL::Certificate);
     629           7 :   SSL::DiffieHellman::unique_ptr diffie_hellman;
     630             : 
     631           7 :   const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED,
     632           7 :                                           Pending = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
     633             : 
     634           7 :   if (serialized_local_participant_data.length() == 0) {
     635           0 :     set_security_error(ex, -1, 0, "No participant data provided");
     636           0 :     return Failure;
     637             :   }
     638             : 
     639           7 :   HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
     640             : 
     641           7 :   if (! handshake_data.first) {
     642           0 :     set_security_error(ex, -1, 0, "Unknown local participant");
     643           0 :     return Failure;
     644             :   }
     645             : 
     646           7 :   if (! handshake_data.second) {
     647           0 :     set_security_error(ex, -1, 0, "Unknown remote participant");
     648           0 :     return Failure;
     649             :   }
     650             : 
     651           7 :   const LocalParticipantData& local_data = *handshake_data.first;
     652           7 :   RemoteParticipantData& remote_data = *handshake_data.second;
     653             : 
     654           7 :   DDS::Security::HandshakeMessageToken message_data_in(request_token);
     655           7 :   TokenReader message_in(message_data_in);
     656           7 :   if (message_in.is_nil()) {
     657           0 :     set_security_error(ex, -1, 0, "Handshake_message_out is an inout param and must not be nil");
     658           0 :     return Failure;
     659             : 
     660             :   }
     661           7 :   challenge1 = message_in.get_bin_property_value("challenge1");
     662             : 
     663           7 :   TokenReader initiator_remote_auth_request(remote_data.remote_auth_request);
     664           7 :   if (! initiator_remote_auth_request.is_nil()) {
     665           6 :     const DDS::OctetSeq& future_challenge = initiator_remote_auth_request.get_bin_property_value("future_challenge");
     666             : 
     667           6 :     if (! challenges_match(challenge1, future_challenge)) {
     668           0 :       return Failure;
     669             :     }
     670             :   }
     671             : 
     672           7 :   const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
     673             : 
     674           7 :   const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
     675           7 :   if (cid.length() > 0) {
     676             : 
     677           7 :     remote_cert->deserialize(cid);
     678           7 :     if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
     679             :     {
     680           0 :       set_security_error(ex, -1, 0, "Certificate validation failed");
     681           0 :       return Failure;
     682             :     }
     683             : 
     684             :   } else {
     685           0 :     set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
     686           0 :     return Failure;
     687             :   }
     688             : 
     689             :   /* Validate participant_guid in c.pdata */
     690             : 
     691           7 :   const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
     692             : 
     693           7 :   std::vector<unsigned char> hash;
     694           7 :   if (0 != remote_cert->subject_name_digest(hash)) {
     695           0 :     set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
     696           0 :     return Failure;
     697             :   }
     698             : 
     699           7 :   if (! validate_topic_data_guid(cpdata, hash, ex)) {
     700           0 :     return Failure;
     701             :   }
     702             : 
     703           7 :   cperm = message_in.get_bin_property_value("c.perm");
     704             : 
     705           7 :   const DDS::OctetSeq& dh_algo = message_in.get_bin_property_value("c.kagree_algo");
     706           7 :   diffie_hellman.reset(SSL::DiffieHellman::factory(dh_algo));
     707             : 
     708             :   /* Compute hash_c1 and store for later */
     709             : 
     710             :   {
     711           7 :     CredentialHash hash(*remote_cert,
     712           7 :                         *diffie_hellman,
     713             :                         cpdata,
     714           7 :                         cperm);
     715           7 :     int err = hash(hash_c1);
     716           7 :     if (err) {
     717           0 :       set_security_error(ex, -1, 0, "Failed to compute hash_c1.");
     718           0 :       return Failure;
     719             :     }
     720             :   }
     721             : 
     722             :   /* Compute hash_c2 and store for later */
     723             : 
     724             :   {
     725             :     CredentialHash hash(local_credential_data.get_participant_cert(),
     726           7 :                         *diffie_hellman,
     727             :                         serialized_local_participant_data,
     728          14 :                         local_credential_data.get_access_permissions());
     729           7 :     int err = hash(hash_c2);
     730           7 :     if (err) {
     731           0 :       set_security_error(ex, -1, 0, "Failed to compute hash_c2.");
     732           0 :       return Failure;
     733             :     }
     734             :   }
     735             : 
     736             :   // TODO: Currently support for OCSP is optional in the security spec and
     737             :   // so it has been deferred to a post-beta release.
     738             :   // Add OCSP checks when "ocsp_status" property is given in message_in.
     739             :   // Most of this logic would probably be placed in the Certificate directly
     740             :   // or an OCSP abstraction that the Certificate uses.
     741             : 
     742           7 :   const DDS::OctetSeq& dh1 = message_in.get_bin_property_value("dh1");
     743             : 
     744           7 :   TokenWriter message_out(handshake_message_out, build_class_id(Handshake_Reply_Class_Ext));
     745             : 
     746           7 :   message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
     747           7 :   message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
     748           7 :   message_out.add_bin_property("c.pdata", serialized_local_participant_data);
     749           7 :   message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
     750           7 :   message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
     751             : 
     752           7 :   if (local_data.handshake_debug) {
     753           0 :     message_out.add_bin_property("hash_c2", hash_c2);
     754             :   }
     755             : 
     756           7 :   diffie_hellman->pub_key(dh2);
     757           7 :   message_out.add_bin_property("dh2", dh2);
     758             : 
     759           7 :   if (local_data.handshake_debug) {
     760           0 :     message_out.add_bin_property("hash_c1", hash_c1);
     761           0 :     message_out.add_bin_property("dh1", dh1);
     762             :   }
     763             : 
     764           7 :   message_out.add_bin_property("challenge1", challenge1);
     765             : 
     766           7 :   TokenReader initiator_local_auth_request(remote_data.local_auth_request);
     767           7 :   if (! initiator_local_auth_request.is_nil()) {
     768           7 :     const DDS::OctetSeq& future_challenge = initiator_local_auth_request.get_bin_property_value("future_challenge");
     769           7 :     message_out.add_bin_property("challenge2", future_challenge);
     770           7 :     challenge2 = future_challenge;
     771             : 
     772             :   } else {
     773           0 :     int err = SSL::make_nonce_256(challenge2);
     774           0 :     if (! err) {
     775           0 :       message_out.add_bin_property("challenge2", challenge2);
     776             : 
     777             :     } else {
     778           0 :       set_security_error(ex, -1, 0, "SSL::make_nonce_256 failed.");
     779           0 :       return Failure;
     780             :     }
     781             :   }
     782             : 
     783           7 :   DDS::BinaryPropertySeq sign_these;
     784           7 :   make_reply_signature_sequence(hash_c2,
     785             :                                 challenge2,
     786             :                                 dh2,
     787             :                                 challenge1,
     788             :                                 dh1,
     789             :                                 hash_c1,
     790             :                                 sign_these);
     791             : 
     792           7 :   DDS::OctetSeq signature;
     793           7 :   SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), signature);
     794           7 :   message_out.add_bin_property("signature", signature);
     795             : 
     796           7 :   remote_data.replier_identity = replier_identity_handle;
     797           7 :   remote_data.initiator_identity = initiator_identity_handle;
     798           7 :   remote_data.state = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
     799           7 :   remote_data.diffie_hellman = DCPS::move(diffie_hellman);
     800           7 :   remote_data.certificate = DCPS::move(remote_cert);
     801           7 :   remote_data.c_perm = cperm;
     802           7 :   remote_data.reply = handshake_message_out;
     803           7 :   remote_data.request = request_token;
     804           7 :   remote_data.hash_c1 = hash_c1;
     805           7 :   remote_data.hash_c2 = hash_c2;
     806             : 
     807           7 :   if (handshake_handle == DDS::HANDLE_NIL) {
     808           6 :     handshake_handle = get_next_handle();
     809             :   }
     810             : 
     811             :   {
     812           7 :     ACE_Guard<ACE_Thread_Mutex> guard(handshake_mutex_);
     813           7 :     handshake_data_[handshake_handle] = handshake_data;
     814             : 
     815           7 :     if (DCPS::security_debug.bookkeeping) {
     816           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     817             :                  ACE_TEXT("AuthenticationBuiltInImpl::begin_handshake_reply handshake_data_ (total %B)\n"),
     818             :                  handshake_data_.size()));
     819             :     }
     820           7 :   }
     821             : 
     822           7 :   return Pending;
     823           7 : }
     824             : 
     825          10 : ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_handshake(
     826             :   ::DDS::Security::HandshakeMessageToken & handshake_message_out,
     827             :   const ::DDS::Security::HandshakeMessageToken & handshake_message_in,
     828             :   ::DDS::Security::HandshakeHandle handshake_handle,
     829             :   ::DDS::Security::SecurityException & ex)
     830             : {
     831          10 :   const std::string incoming_class_ext = get_extension(handshake_message_in.class_id);
     832             : 
     833          10 :   if (Handshake_Reply_Class_Ext == incoming_class_ext) {
     834           5 :     return process_handshake_reply(handshake_message_out, handshake_message_in, handshake_handle, ex);
     835             : 
     836           5 :   } else if (Handshake_Final_Class_Ext == incoming_class_ext) {
     837           5 :     return process_final_handshake(handshake_message_in, handshake_handle, ex);
     838             :   }
     839             : 
     840           0 :   return DDS::Security::VALIDATION_PENDING_RETRY;
     841          10 : }
     842             : 
     843           2 : ::DDS::Security::SharedSecretHandle* AuthenticationBuiltInImpl::get_shared_secret(
     844             :   ::DDS::Security::HandshakeHandle handshake_handle,
     845             :   ::DDS::Security::SecurityException & ex)
     846             : {
     847             :   using namespace DDS::Security;
     848             : 
     849           2 :   SharedSecretHandle* result = 0;
     850             : 
     851           2 :   ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
     852             : 
     853           2 :   HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
     854           2 :   if (handshake_data.first && handshake_data.second) {
     855             : 
     856           2 :     ValidationResult_t state = handshake_data.second->state;
     857           2 :     if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
     858           2 :       SharedSecretHandle_var handle = handshake_data.second->shared_secret;
     859           2 :       result = handle._retn();
     860             : 
     861           2 :     } else {
     862           0 :       set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
     863             :     }
     864             : 
     865             :   } else {
     866           0 :     set_security_error(ex, -1, 0, "Unknown handshake handle");
     867             :   }
     868             : 
     869           2 :   return result;
     870           2 : }
     871             : 
     872           2 : ::CORBA::Boolean AuthenticationBuiltInImpl::get_authenticated_peer_credential_token(
     873             :   ::DDS::Security::AuthenticatedPeerCredentialToken & peer_credential_token,
     874             :   ::DDS::Security::HandshakeHandle handshake_handle,
     875             :   ::DDS::Security::SecurityException & ex)
     876             : {
     877             :   using namespace DDS::Security;
     878           2 :   ::CORBA::Boolean result = false;
     879             : 
     880           2 :   ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
     881             : 
     882           2 :   HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
     883           2 :   if (handshake_data.first && handshake_data.second) {
     884           2 :     ValidationResult_t state = handshake_data.second->state;
     885           2 :     if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
     886           4 :       OpenDDS::Security::TokenWriter peer_token(peer_credential_token, Auth_Peer_Cred_Token_Class_Id);
     887             : 
     888           2 :       DDS::BinaryPropertySeq& props = peer_credential_token.binary_properties;
     889           2 :       props.length(2);
     890             : 
     891           2 :       DDS::BinaryProperty_t p1;
     892           2 :       p1.name = "c.id";
     893           2 :       p1.value = handshake_data.second->certificate->original_bytes();
     894           2 :       p1.propagate = true;
     895             : 
     896           2 :       DDS::BinaryProperty_t p2;
     897           2 :       p2.name = "c.perm";
     898           2 :       p2.value = handshake_data.second->c_perm;
     899           2 :       p2.propagate = true;
     900             : 
     901           2 :       props[0] = p1;
     902           2 :       props[1] = p2;
     903             : 
     904           2 :       result = true;
     905             : 
     906           2 :     } else {
     907           0 :       set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
     908             :     }
     909             : 
     910             :   } else {
     911           0 :     set_security_error(ex, -1, 0, "Unknown handshake handle");
     912             :   }
     913             : 
     914           2 :   return result;
     915           2 : }
     916             : 
     917           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::set_listener(
     918             :   ::DDS::Security::AuthenticationListener_ptr listener,
     919             :   ::DDS::Security::SecurityException & ex)
     920             : {
     921           0 :   ::CORBA::Boolean results = false;
     922             : 
     923           0 :   if (!listener) {
     924           0 :     set_security_error(ex, -1, 0, "Null listener provided");
     925             :   } else {
     926           0 :     results = true;
     927           0 :     listener_ptr_ = listener;
     928             :   }
     929           0 :   return results;
     930             : }
     931             : 
     932           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_token(
     933             :   const ::DDS::Security::IdentityToken & token,
     934             :   ::DDS::Security::SecurityException & ex)
     935             : {
     936             :   // Nothing to do here yet
     937             :   ACE_UNUSED_ARG(token);
     938             :   ACE_UNUSED_ARG(ex);
     939           0 :   return true;
     940             : }
     941             : 
     942             : 
     943           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_status_token(
     944             :   const ::DDS::Security::IdentityStatusToken & token,
     945             :   ::DDS::Security::SecurityException & ex)
     946             : {
     947             :   // Nothing to do here yet
     948             :   ACE_UNUSED_ARG(token);
     949             :   ACE_UNUSED_ARG(ex);
     950           0 :   return true;
     951             : }
     952             : 
     953             : 
     954           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_authenticated_peer_credential_token(
     955             :   const ::DDS::Security::AuthenticatedPeerCredentialToken & peer_credential_token,
     956             :   ::DDS::Security::SecurityException & ex)
     957             : {
     958             :   // Nothing to do here yet
     959             :   ACE_UNUSED_ARG(peer_credential_token);
     960             :   ACE_UNUSED_ARG(ex);
     961           0 :   return true;
     962             : }
     963             : 
     964           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_handshake_handle(
     965             :   ::DDS::Security::HandshakeHandle handshake_handle,
     966             :   ::DDS::Security::SecurityException & ex)
     967             : {
     968           0 :   ACE_Guard<ACE_Thread_Mutex> guard(handshake_mutex_);
     969             : 
     970           0 :   HandshakeDataMap::iterator found = handshake_data_.find(handshake_handle);
     971           0 :   if (found != handshake_data_.end()) {
     972           0 :     handshake_data_.erase(found);
     973             : 
     974           0 :     if (DCPS::security_debug.bookkeeping) {
     975           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     976             :                  ACE_TEXT("AuthenticationBuiltInImpl::return_handshake_handle handshake_data_ (total %B)\n"),
     977             :                  handshake_data_.size()));
     978             :     }
     979             : 
     980           0 :     return true;
     981             :   }
     982             : 
     983           0 :   set_security_error(ex, -1, 0, "Handshake handle not recognized");
     984           0 :   return false;
     985           0 : }
     986             : 
     987           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_handle(
     988             :   ::DDS::Security::IdentityHandle identity_handle,
     989             :   ::DDS::Security::SecurityException & ex)
     990             : {
     991           0 :   ACE_Guard<ACE_Thread_Mutex> guard(identity_mutex_);
     992             : 
     993           0 :   LocalParticipantMap::iterator local = local_participants_.find(identity_handle);
     994             : 
     995           0 :   if (local != local_participants_.end()) {
     996             : 
     997             :     {
     998           0 :       ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
     999             : 
    1000           0 :       for (HandshakeDataMap::iterator it = handshake_data_.begin(); it != handshake_data_.end(); /* increment in loop*/) {
    1001           0 :         if (it->second.first == local->second) {
    1002           0 :           handshake_data_.erase(it++);
    1003             :         } else {
    1004           0 :           ++it;
    1005             :         }
    1006             :       }
    1007           0 :     }
    1008             : 
    1009           0 :     local_participants_.erase(local);
    1010             : 
    1011           0 :     if (DCPS::security_debug.bookkeeping) {
    1012           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1013             :                  ACE_TEXT("AuthenticationBuiltInImpl::return_identity_handle local_participants_ (total %B)\n"),
    1014             :                  local_participants_.size()));
    1015             :     }
    1016             : 
    1017           0 :     return true;
    1018             :   }
    1019             : 
    1020           0 :   local = std::find_if(local_participants_.begin(), local_participants_.end(),
    1021             :                        local_has_remote_handle(identity_handle));
    1022             : 
    1023           0 :   if (local != local_participants_.end()) {
    1024             : 
    1025           0 :     const RemoteParticipantMap::iterator remote = local->second->validated_remotes.find(identity_handle);
    1026             : 
    1027             :     {
    1028           0 :       ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
    1029             : 
    1030           0 :       for (HandshakeDataMap::iterator it = handshake_data_.begin(); it != handshake_data_.end(); /* increment in loop*/) {
    1031           0 :         if (it->second.second == remote->second) {
    1032           0 :           handshake_data_.erase(it++);
    1033             :         } else {
    1034           0 :           ++it;
    1035             :         }
    1036             :       }
    1037           0 :     }
    1038             : 
    1039           0 :     local->second->validated_remotes.erase(remote);
    1040             : 
    1041           0 :     if (DCPS::security_debug.bookkeeping) {
    1042           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1043             :                  ACE_TEXT("AuthenticationBuiltInImpl::return_identity_handle validated_remotes (total %B)\n"),
    1044             :                  local->second->validated_remotes.size()));
    1045             :     }
    1046             : 
    1047           0 :     return true;
    1048             :   }
    1049             : 
    1050           0 :   set_security_error(ex, -1, 0, "Identity handle not recognized");
    1051           0 :   return false;
    1052           0 : }
    1053             : 
    1054           0 : ::CORBA::Boolean AuthenticationBuiltInImpl::return_sharedsecret_handle(
    1055             :   ::DDS::Security::SharedSecretHandle* sharedsecret_handle,
    1056             :   ::DDS::Security::SecurityException & ex)
    1057             : {
    1058             :   // Nothing to do here in the stub version
    1059             :   ACE_UNUSED_ARG(sharedsecret_handle);
    1060             :   ACE_UNUSED_ARG(ex);
    1061           0 :   return true;
    1062             : }
    1063             : 
    1064             : 
    1065           5 : DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_handshake_reply(
    1066             :   DDS::Security::HandshakeMessageToken & handshake_message_out,
    1067             :   const DDS::Security::HandshakeMessageToken & handshake_message_in,
    1068             :   DDS::Security::HandshakeHandle handshake_handle,
    1069             :   DDS::Security::SecurityException & ex)
    1070             : {
    1071           5 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
    1072           5 :   ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
    1073             : 
    1074           5 :   DDS::OctetSeq challenge1, hash_c2;
    1075           5 :   SSL::Certificate::unique_ptr remote_cert(new SSL::Certificate);
    1076             : 
    1077           5 :   const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED;
    1078           5 :   const DDS::Security::ValidationResult_t FinalMessage = DDS::Security::VALIDATION_OK_FINAL_MESSAGE;
    1079             : 
    1080           5 :   HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
    1081           5 :   if (!handshake_data.first || !handshake_data.second) {
    1082           0 :     set_security_error(ex, -1, 0, "Unknown handshake handle");
    1083           0 :     return Failure;
    1084             :   }
    1085             : 
    1086           5 :   LocalParticipantData& local_data = *(handshake_data.first);
    1087           5 :   RemoteParticipantData& remote_data = *(handshake_data.second);
    1088             : 
    1089           5 :   if (remote_data.state != DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE) {
    1090           0 :     set_security_error(ex, -1, 0, "Handshake state is not valid");
    1091           0 :     return Failure;
    1092             :   }
    1093             : 
    1094           5 :   TokenReader message_in(handshake_message_in);
    1095           5 :   if (message_in.is_nil()) {
    1096           0 :     set_security_error(ex, -1, 0, "Handshake_message_in must not be nil");
    1097           0 :     return Failure;
    1098             :   }
    1099             : 
    1100           5 :   const DDS::OctetSeq& challenge2 = message_in.get_bin_property_value("challenge2");
    1101             : 
    1102           5 :   TokenReader auth_wrapper(remote_data.remote_auth_request);
    1103           5 :   if (! auth_wrapper.is_nil()) {
    1104           0 :     const DDS::OctetSeq& future_challenge = auth_wrapper.get_bin_property_value("future_challenge");
    1105             : 
    1106           0 :     if (! challenges_match(challenge2, future_challenge)) {
    1107           0 :       set_security_error(ex, -1, 0, "challenge2 does not match future_challenge");
    1108           0 :       return Failure;
    1109             :     }
    1110             :   }
    1111             : 
    1112           5 :   const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
    1113             : 
    1114           5 :   const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
    1115           5 :   if (cid.length() > 0) {
    1116             : 
    1117           5 :       remote_cert->deserialize(cid);
    1118             : 
    1119           5 :     if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
    1120             :     {
    1121           0 :       set_security_error(ex, -1, 0, "Certificate validation failed");
    1122           0 :       return Failure;
    1123             :     }
    1124             : 
    1125             :   } else {
    1126           0 :     set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
    1127           0 :     return Failure;
    1128             :   }
    1129             : 
    1130             :   /* Check that challenge1 on message_in matches the one sent in HandshakeRequestMessageToken */
    1131             : 
    1132           5 :   TokenReader handshake_request_token(remote_data.request);
    1133           5 :   if (handshake_request_token.is_nil()) {
    1134           0 :     set_security_error(ex, -1, 0, "Handshake-request-token is nil");
    1135           0 :     return Failure;
    1136             : 
    1137             :   } else {
    1138           5 :     challenge1 = handshake_request_token.get_bin_property_value("challenge1");
    1139           5 :     const DDS::OctetSeq& challenge1_reply =  message_in.get_bin_property_value("challenge1");
    1140             : 
    1141           5 :     if (! challenges_match(challenge1, challenge1_reply)) {
    1142           0 :       set_security_error(ex, -1, 0, "handshake-request challenge1 value does not match local challenge1");
    1143           0 :       return Failure;
    1144             :     }
    1145             :   }
    1146             : 
    1147             :   /* Validate participant_guid in c.pdata */
    1148             : 
    1149           5 :   const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
    1150             : 
    1151           5 :   std::vector<unsigned char> hash;
    1152           5 :   if (0 != remote_cert->subject_name_digest(hash)) {
    1153           0 :     set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
    1154           0 :     return Failure;
    1155             :   }
    1156             : 
    1157           5 :   if (! validate_topic_data_guid(cpdata, hash, ex)) {
    1158           0 :     return Failure;
    1159             :   }
    1160             : 
    1161             :   /* Compute/Store the Diffie-Hellman shared-secret */
    1162             : 
    1163           5 :   const DDS::OctetSeq& dh2 = message_in.get_bin_property_value("dh2");
    1164           5 :   if (0 != remote_data.diffie_hellman->gen_shared_secret(dh2)) {
    1165           0 :     set_security_error(ex, -1, 0, "Failed to generate shared secret from dh1 and dh2");
    1166           0 :     return Failure;
    1167             :   }
    1168             : 
    1169           5 :   const DDS::OctetSeq& cperm = message_in.get_bin_property_value("c.perm");
    1170             : 
    1171             :   /* Compute hash_c2 and store for later (hash_c1 was already computed in request) */
    1172             : 
    1173             :   {
    1174           5 :     CredentialHash hash(*remote_cert,
    1175           5 :                         *remote_data.diffie_hellman,
    1176             :                         cpdata,
    1177           5 :                         cperm);
    1178           5 :     int err = hash(hash_c2);
    1179           5 :     if (err) {
    1180           0 :       set_security_error(ex, -1, 0, "Computing hash_c2 failed");
    1181           0 :       return Failure;
    1182             :     }
    1183             :   }
    1184             : 
    1185             :   /* Validate Signature field */
    1186           5 :   const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
    1187             : 
    1188           5 :   DDS::BinaryPropertySeq verify_these;
    1189           5 :   make_reply_signature_sequence(hash_c2,
    1190             :                                 challenge2,
    1191             :                                 dh2,
    1192             :                                 challenge1,
    1193             :                                 dh1,
    1194           5 :                                 remote_data.hash_c1,
    1195             :                                 verify_these);
    1196             : 
    1197           5 :   const DDS::OctetSeq& remote_signature = message_in.get_bin_property_value("signature");
    1198             : 
    1199           5 :   int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
    1200           5 :   if (err) {
    1201           0 :     set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
    1202           0 :     return Failure;
    1203             :   }
    1204             : 
    1205           5 :   OpenDDS::Security::TokenWriter final_msg(handshake_message_out, build_class_id(Handshake_Final_Class_Ext));
    1206             : 
    1207           5 :   if (local_data.handshake_debug) {
    1208           0 :     final_msg.add_bin_property("hash_c1", remote_data.hash_c1);
    1209           0 :     final_msg.add_bin_property("hash_c2", hash_c2);
    1210           0 :     final_msg.add_bin_property("dh1", dh1);
    1211           0 :     final_msg.add_bin_property("dh2", dh2);
    1212             :   }
    1213             : 
    1214           5 :   final_msg.add_bin_property("challenge1", challenge1);
    1215           5 :   final_msg.add_bin_property("challenge2", challenge2);
    1216             : 
    1217           5 :   DDS::BinaryPropertySeq sign_these;
    1218           5 :   make_final_signature_sequence(remote_data.hash_c1,
    1219             :                                 challenge1,
    1220             :                                 dh1,
    1221             :                                 challenge2,
    1222             :                                 dh2,
    1223             :                                 hash_c2,
    1224             :                                 sign_these);
    1225             : 
    1226           5 :   DDS::OctetSeq tmp;
    1227           5 :   SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), tmp);
    1228           5 :   final_msg.add_bin_property("signature", tmp);
    1229             : 
    1230           5 :   remote_data.certificate = DCPS::move(remote_cert);
    1231           5 :   remote_data.state = FinalMessage;
    1232           5 :   remote_data.c_perm = message_in.get_bin_property_value("c.perm");
    1233           5 :   remote_data.hash_c2 = hash_c2;
    1234          10 :   remote_data.shared_secret = new SharedSecret(challenge1,
    1235             :                                                challenge2,
    1236           5 :                                                remote_data.diffie_hellman->get_shared_secret());
    1237           5 :   return FinalMessage;
    1238           5 : }
    1239             : 
    1240          21 : bool challenges_match(const DDS::OctetSeq& c1, const DDS::OctetSeq& c2)
    1241             : {
    1242          21 :   if ((c1.length()) < 1 || (c2.length() < 1)) {
    1243           0 :     return false;
    1244             :   }
    1245          21 :   if (c1.length() != c2.length()) {
    1246           0 :     return false;
    1247             :   }
    1248             : 
    1249          21 :   if (0 != std::memcmp(c1.get_buffer(), c2.get_buffer(), c2.length())) {
    1250           0 :     return false;
    1251             :   }
    1252             : 
    1253          21 :   return true;
    1254             : }
    1255             : 
    1256           5 : DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_final_handshake(
    1257             :   const DDS::Security::HandshakeMessageToken & handshake_message_in, /* Final message token */
    1258             :   DDS::Security::HandshakeHandle handshake_handle,
    1259             :   DDS::Security::SecurityException & ex)
    1260             : {
    1261           5 :   const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED;
    1262           5 :   const DDS::Security::ValidationResult_t ValidationOkay = DDS::Security::VALIDATION_OK;
    1263             : 
    1264           5 :   ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
    1265           5 :   ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
    1266             : 
    1267           5 :   HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
    1268           5 :   if (!handshake_data.first || !handshake_data.second) {
    1269           0 :     set_security_error(ex, -1, 0, "Unknown handshake handle");
    1270           0 :     return Failure;
    1271             :   }
    1272             : 
    1273           5 :   RemoteParticipantData& remote_data = *(handshake_data.second);
    1274             : 
    1275           5 :   if (remote_data.state != DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE) {
    1276           0 :     set_security_error(ex, -1, 0, "Handshake state is not valid");
    1277           0 :     return Failure;
    1278             :   }
    1279             : 
    1280             :   /* Check challenge1 and challenge2 match what was sent with the reply-message-token */
    1281             : 
    1282           5 :   TokenReader handshake_final_token(handshake_message_in);
    1283           5 :   if (handshake_final_token.is_nil()) {
    1284           0 :     set_security_error(ex, -1, 0, "Handshake-final-token is nil");
    1285           0 :     return Failure;
    1286             :   }
    1287             : 
    1288           5 :   TokenReader handshake_reply_token(remote_data.reply);
    1289           5 :   if (handshake_reply_token.is_nil()) {
    1290           0 :     set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
    1291           0 :     return Failure;
    1292             :   }
    1293             : 
    1294             :   /* Per the spec, dh1 is optional in all _but_ the request token so it's grabbed from the request */
    1295           5 :   TokenReader handshake_request_token(remote_data.request);
    1296           5 :   if (handshake_reply_token.is_nil()) {
    1297           0 :     set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
    1298           0 :     return Failure;
    1299             :   }
    1300             : 
    1301           5 :   const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
    1302           5 :   const DDS::OctetSeq& dh2 = handshake_reply_token.get_bin_property_value("dh2");
    1303             : 
    1304           5 :   const DDS::OctetSeq& challenge1_reply = handshake_reply_token.get_bin_property_value("challenge1");
    1305           5 :   const DDS::OctetSeq& challenge2_reply = handshake_reply_token.get_bin_property_value("challenge2");
    1306             : 
    1307           5 :   const DDS::OctetSeq& challenge1_final = handshake_final_token.get_bin_property_value("challenge1");
    1308           5 :   const DDS::OctetSeq& challenge2_final = handshake_final_token.get_bin_property_value("challenge2");
    1309             : 
    1310           5 :   if (! challenges_match(challenge1_reply, challenge1_final) || ! challenges_match(challenge2_reply, challenge2_final)) {
    1311           0 :       return Failure;
    1312             :   }
    1313             : 
    1314             :   /* Validate Signature field */
    1315             : 
    1316           5 :   const SSL::Certificate::unique_ptr& remote_cert = remote_data.certificate;
    1317             : 
    1318           5 :   DDS::BinaryPropertySeq verify_these;
    1319           5 :   make_final_signature_sequence(remote_data.hash_c1,
    1320             :                                 challenge1_reply,
    1321             :                                 dh1,
    1322             :                                 challenge2_reply,
    1323             :                                 dh2,
    1324           5 :                                 remote_data.hash_c2,
    1325             :                                 verify_these);
    1326             : 
    1327           5 :   const DDS::OctetSeq& remote_signature = handshake_final_token.get_bin_property_value("signature");
    1328             : 
    1329           5 :   int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
    1330           5 :   if (err) {
    1331           0 :     set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
    1332           0 :     return Failure;
    1333             :   }
    1334             : 
    1335             :   /* Compute/Store the Diffie-Hellman shared-secret */
    1336             : 
    1337           5 :   if (0 != remote_data.diffie_hellman->gen_shared_secret(dh1)) {
    1338           0 :     set_security_error(ex, -1, 0, "Failed to generate shared secret from dh2 and dh1");
    1339           0 :     return Failure;
    1340             :   }
    1341             : 
    1342           5 :   remote_data.state = DDS::Security::VALIDATION_OK;
    1343          10 :   remote_data.shared_secret = new SharedSecret(challenge1_reply,
    1344             :                                                  challenge2_reply,
    1345           5 :                                                  remote_data.diffie_hellman->get_shared_secret());
    1346             : 
    1347           5 :   return ValidationOkay;
    1348           5 : }
    1349             : 
    1350             : AuthenticationBuiltInImpl::LocalParticipantData::shared_ptr
    1351          37 : AuthenticationBuiltInImpl::get_local_participant(DDS::Security::IdentityHandle handle)
    1352             : {
    1353          37 :   LocalParticipantMap::iterator found = local_participants_.find(handle);
    1354          37 :   if (found != local_participants_.end()) {
    1355          37 :     return found->second;
    1356             :   }
    1357             : 
    1358           0 :   return LocalParticipantData::shared_ptr();
    1359             : }
    1360             : 
    1361          44 : AuthenticationBuiltInImpl::LocalParticipantData::~LocalParticipantData()
    1362             : {
    1363          22 :   if (DCPS::security_debug.bookkeeping) {
    1364           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1365             :                ACE_TEXT("LocalParticipantData::~LocalParticipantData validated_remotes %B\n"),
    1366             :                validated_remotes.size()));
    1367             :   }
    1368          44 : }
    1369             : 
    1370             : AuthenticationBuiltInImpl::HandshakeDataPair
    1371          14 : AuthenticationBuiltInImpl::get_handshake_data(DDS::Security::HandshakeHandle handle)
    1372             : {
    1373          14 :   HandshakeDataMap::iterator found = handshake_data_.find(handle);
    1374          14 :   if (found != handshake_data_.end()) {
    1375          14 :     return found->second;
    1376             :   }
    1377             : 
    1378           0 :   return HandshakeDataPair();
    1379             : }
    1380             : 
    1381             : AuthenticationBuiltInImpl::HandshakeDataPair
    1382          14 : AuthenticationBuiltInImpl::make_handshake_pair(DDS::Security::IdentityHandle h1,
    1383             :                                                DDS::Security::IdentityHandle h2)
    1384             : {
    1385          14 :   DDS::Security::IdentityHandle other = DDS::HANDLE_NIL;
    1386             : 
    1387          14 :   LocalParticipantMap::iterator found_local = local_participants_.find(h1);
    1388          14 :   if (found_local != local_participants_.end()) {
    1389           7 :     other = h2;
    1390             : 
    1391             :   } else {
    1392           7 :     found_local = local_participants_.find(h2);
    1393           7 :     if (found_local != local_participants_.end()) {
    1394           7 :       other = h1;
    1395             : 
    1396             :     } else {
    1397           0 :       return HandshakeDataPair();
    1398             :     }
    1399             :   }
    1400             : 
    1401          14 :   RemoteParticipantMap::iterator found_remote = found_local->second->validated_remotes.find(other);
    1402          14 :   if (found_remote != found_local->second->validated_remotes.end()) {
    1403          14 :     return std::make_pair(found_local->second, found_remote->second);
    1404             :   }
    1405             : 
    1406           0 :   return HandshakeDataPair();
    1407             : }
    1408             : 
    1409          16 : bool AuthenticationBuiltInImpl::is_handshake_initiator(
    1410             :   const OpenDDS::DCPS::GUID_t& local, const OpenDDS::DCPS::GUID_t& remote)
    1411             : {
    1412          16 :   const unsigned char* local_ = reinterpret_cast<const unsigned char*>(&local);
    1413          16 :   const unsigned char* remote_ = reinterpret_cast<const unsigned char*>(&remote);
    1414             : 
    1415             :   using DCPS::SecurityDebug;
    1416          16 :   if (DCPS::security_debug.force_auth_role != SecurityDebug::FORCE_AUTH_ROLE_NORMAL) {
    1417           0 :     return DCPS::security_debug.force_auth_role == SecurityDebug::FORCE_AUTH_ROLE_LEADER;
    1418             :   }
    1419             : 
    1420             :   /* if remote > local, pending request; else pending handshake message */
    1421          16 :   return std::lexicographical_compare(local_, local_ + sizeof(local),
    1422          16 :                                       remote_, remote_ + sizeof(remote));
    1423             : 
    1424             : }
    1425             : 
    1426          16 : bool AuthenticationBuiltInImpl::check_class_versions(const char* remote_class_id)
    1427             : {
    1428          16 :   if (!remote_class_id) {
    1429           0 :     return false;
    1430             :   }
    1431          16 :   bool class_matches = false;
    1432             : 
    1433             :   // Slow, but this is just for the stub
    1434          16 :   std::string class_id_str(remote_class_id);
    1435             : 
    1436             :   // Class name is the text prior to the final ':'
    1437          16 :   size_t colon_pos = class_id_str.find_last_of(':');
    1438          16 :   if (std::string::npos != colon_pos && colon_pos > 0) {
    1439             :     // Compare the class name vs the expected class name
    1440          16 :     std::string remote_class_name  = class_id_str.substr(0, colon_pos);
    1441          16 :     if (0 == Auth_Plugin_Name.compare(remote_class_name)) {
    1442             :       // Major version is the text between the final : and a  .
    1443          16 :       size_t major_start = colon_pos + 1;
    1444          16 :       size_t period_pos = class_id_str.find_first_of('.', major_start);
    1445          16 :       if (std::string::npos != period_pos && period_pos > major_start) {
    1446          16 :         std::string major_version = class_id_str.substr(major_start, period_pos - major_start);
    1447          16 :         if (0 == Auth_Plugin_Major_Version.compare(major_version)) {
    1448          16 :           class_matches = true;
    1449             :         }
    1450          16 :       }
    1451             :     }
    1452          16 :   }
    1453             : 
    1454          16 :   return class_matches;
    1455          16 : }
    1456             : 
    1457          35 : std::string AuthenticationBuiltInImpl::build_class_id(const std::string& message_ext)
    1458             : {
    1459          35 :   std::string class_id_stream = Auth_Plugin_Name +
    1460          70 :     + ":" + Auth_Plugin_Major_Version
    1461          70 :     + "." + Auth_Plugin_Minor_Version
    1462          70 :     + "+" + message_ext;
    1463             : 
    1464          35 :   return class_id_stream;
    1465             : }
    1466             : 
    1467          10 : std::string AuthenticationBuiltInImpl::get_extension(const char* class_id)
    1468             : {
    1469          10 :   std::string ext_string("");
    1470             : 
    1471          10 :   std::string class_id_str(class_id);
    1472          10 :   size_t extension_delim_pos = class_id_str.find_last_of('+');
    1473          10 :   if (extension_delim_pos != std::string::npos) {
    1474          10 :     size_t start_ext_pos = extension_delim_pos + 1;
    1475          10 :     if (start_ext_pos < class_id_str.length()) {
    1476          10 :     ext_string = class_id_str.substr(start_ext_pos);
    1477             :     }
    1478             :   }
    1479             : 
    1480          20 :   return ext_string;
    1481          10 : }
    1482             : 
    1483          51 : CORBA::Long AuthenticationBuiltInImpl::get_next_handle()
    1484             : {
    1485          51 :   ACE_Guard<ACE_Thread_Mutex> guard(handle_mutex_);
    1486         102 :   return CommonUtilities::increment_handle(next_handle_);
    1487          51 : }
    1488             : 
    1489             : } // namespace Security
    1490             : } // namespace OpenDDS
    1491             : 
    1492             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16