LCOV - code coverage report
Current view: top level - DCPS/security - AccessControlBuiltInImpl.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 505 797 63.4 %
Date: 2023-04-30 01:32:43 Functions: 41 50 82.0 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.opendds.org/license.html
       4             :  */
       5             : 
       6             : #include "AccessControlBuiltInImpl.h"
       7             : 
       8             : #include "AuthenticationBuiltInImpl.h"
       9             : #include "CommonUtilities.h"
      10             : #include "TokenWriter.h"
      11             : #include "SSL/SubjectName.h"
      12             : 
      13             : #include <dds/DCPS/Service_Participant.h>
      14             : 
      15             : #include <dds/DdsDcpsInfrastructureC.h>
      16             : 
      17             : #include <ace/ACE.h>
      18             : #include <ace/config-macros.h>
      19             : #include <ace/OS_NS_strings.h>
      20             : #include <ace/Reactor.h>
      21             : 
      22             : #include <time.h>
      23             : #include <fstream>
      24             : #include <sstream>
      25             : #include <iostream>
      26             : #include <stdexcept>
      27             : #include <iterator>
      28             : #include <cstring>
      29             : #include <iomanip>
      30             : 
      31             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      32             : 
      33             : namespace OpenDDS {
      34             : namespace Security {
      35             : 
      36             : using DCPS::TimeDuration;
      37             : 
      38             : typedef Governance::GovernanceAccessRules::iterator gov_iter;
      39             : typedef Permissions::Grants::iterator grant_iter;
      40             : typedef Permissions::Rules::iterator perm_topic_rules_iter;
      41             : typedef Permissions::Actions::iterator perm_topic_actions_iter;
      42             : 
      43             : static const std::string PermissionsTokenClassId("DDS:Access:Permissions:1.0");
      44             : static const std::string AccessControl_Plugin_Name("DDS:Access:Permissions");
      45             : static const std::string AccessControl_Major_Version("1");
      46             : static const std::string AccessControl_Minor_Version("0");
      47             : 
      48             : static const std::string PermissionsCredentialTokenClassId("DDS:Access:PermissionsCredential");
      49             : 
      50          32 : bool AccessControlBuiltInImpl::pattern_match(const char* string, const char* pattern)
      51             : {
      52          32 :   return ACE::wild_match(string, pattern, true, true);
      53             : }
      54             : 
      55          55 : AccessControlBuiltInImpl::AccessControlBuiltInImpl()
      56          55 :   : handle_mutex_()
      57          55 :   , gen_handle_mutex_()
      58          55 :   , next_handle_(1)
      59          55 :   , listener_ptr_(0)
      60          55 : {  }
      61             : 
      62          55 : AccessControlBuiltInImpl::~AccessControlBuiltInImpl()
      63             : {
      64          55 :   if (DCPS::security_debug.bookkeeping) {
      65           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
      66             :                ACE_TEXT("AccessControlBuiltInImpl::~AccessControlBuiltInImpl local_ac_perms_ %B local_identity_map_ %B\n"),
      67             :                local_ac_perms_.size(),
      68             :                local_identity_map_.size()));
      69             :   }
      70          55 : }
      71             : 
      72          24 : ::DDS::Security::PermissionsHandle AccessControlBuiltInImpl::validate_local_permissions(
      73             :   ::DDS::Security::Authentication_ptr auth_plugin,
      74             :   ::DDS::Security::IdentityHandle identity,
      75             :   ::DDS::Security::DomainId_t domain_id,
      76             :   const ::DDS::DomainParticipantQos & participant_qos,
      77             :   ::DDS::Security::SecurityException & ex)
      78             : {
      79          24 :   if (0 == auth_plugin) {
      80           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_local_permissions: Null Authentication plugin");
      81           1 :     return DDS::HANDLE_NIL;
      82             :   }
      83             : 
      84          23 :   if (DDS::HANDLE_NIL == identity) {
      85           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_local_permissions: Invalid identity");
      86           1 :     return DDS::HANDLE_NIL;
      87             :   }
      88             : 
      89          22 :   DDS::Security::IdentityToken id_token;
      90             : 
      91          22 :   if (!auth_plugin->get_identity_token(id_token, identity, ex)) {
      92           0 :     return DDS::HANDLE_NIL;
      93             :   }
      94             : 
      95          22 :   LocalAccessCredentialData::shared_ptr local_access_credential_data = DCPS::make_rch<LocalAccessCredentialData>();
      96             : 
      97          22 :   if (! local_access_credential_data->load(participant_qos.property.value, ex)) {
      98           0 :     return DDS::HANDLE_NIL;
      99             :   }
     100             : 
     101          22 :   if (!local_access_credential_data->verify(ex)) {
     102           0 :     return DDS::HANDLE_NIL;
     103             :   }
     104             : 
     105          22 :   const SSL::SignedDocument& local_gov = local_access_credential_data->get_governance_doc();
     106          22 :   Governance::shared_ptr governance = DCPS::make_rch<Governance>();
     107             : 
     108          22 :   if (governance->load(local_gov)) {
     109           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_local_permissions: Invalid governance file");
     110           0 :     return DDS::HANDLE_NIL;
     111             :   }
     112             : 
     113          22 :   const SSL::SignedDocument& local_perm = local_access_credential_data->get_permissions_doc();
     114          22 :   Permissions::shared_ptr permissions = DCPS::make_rch<Permissions>();
     115             : 
     116          22 :   if (permissions->load(local_perm)) {
     117           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_local_permissions: Invalid permission file");
     118           0 :     return DDS::HANDLE_NIL;
     119             :   }
     120             : 
     121          22 :   TokenReader tr(id_token);
     122          22 :   const char* id_sn = tr.get_property_value(dds_cert_sn);
     123             : 
     124          22 :   OpenDDS::Security::SSL::SubjectName sn_id;
     125             : 
     126          22 :   if (!id_sn || sn_id.parse(id_sn) != 0 || !permissions->has_grant(sn_id)) {
     127           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_local_permissions: No permissions subject name matches identity subject name");
     128           0 :     return DDS::HANDLE_NIL;
     129             :   }
     130             : 
     131             :   // Set and store the permissions credential token while we have the raw content
     132          22 :   DDS::Security::PermissionsCredentialToken permissions_cred_token;
     133          22 :   TokenWriter pctWriter(permissions_cred_token, PermissionsCredentialTokenClassId);
     134             : 
     135          22 :   pctWriter.add_property("dds.perm.cert", local_perm.original());
     136             : 
     137             :   // Set and store the permissions token
     138          22 :   DDS::Security::PermissionsToken permissions_token;
     139          22 :   TokenWriter writer(permissions_token, PermissionsTokenClassId);
     140             : 
     141             :   // If all checks are successful load the content into cache
     142          22 :   permissions->perm_token_ = permissions_token;
     143          22 :   permissions->perm_cred_token_ = permissions_cred_token;
     144             : 
     145          22 :   const int perm_handle = generate_handle();
     146             : 
     147          22 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, DDS::HANDLE_NIL);
     148             : 
     149          22 :   AccessData cache_this;
     150          22 :   cache_this.identity = identity;
     151          22 :   cache_this.subject = sn_id;
     152          22 :   cache_this.domain_id = domain_id;
     153          22 :   cache_this.perm = permissions;
     154          22 :   cache_this.gov = governance;
     155          22 :   cache_this.local_access_credential_data = local_access_credential_data;
     156             : 
     157          22 :   local_ac_perms_.insert(std::make_pair(perm_handle, cache_this));
     158          22 :   if (DCPS::security_debug.bookkeeping) {
     159           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     160             :                ACE_TEXT("AccessControlBuiltInImpl::validate_local_permissions local_ac_perms_ (total %B)\n"),
     161             :                local_ac_perms_.size()));
     162             :   }
     163          22 :   local_identity_map_.insert(std::make_pair(identity, perm_handle));
     164          22 :   if (DCPS::security_debug.bookkeeping) {
     165           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     166             :                ACE_TEXT("AccessControlBuiltInImpl::validate_local_permissions local_identity_map_ (total %B)\n"),
     167             :                local_identity_map_.size()));
     168             :   }
     169             : 
     170          22 :   return perm_handle;
     171          22 : }
     172             : 
     173           9 : ::DDS::Security::PermissionsHandle AccessControlBuiltInImpl::validate_remote_permissions(
     174             :   ::DDS::Security::Authentication_ptr auth_plugin,
     175             :   ::DDS::Security::IdentityHandle local_identity_handle,
     176             :   ::DDS::Security::IdentityHandle remote_identity_handle,
     177             :   const ::DDS::Security::PermissionsToken & remote_permissions_token,
     178             :   const ::DDS::Security::AuthenticatedPeerCredentialToken & remote_credential_token,
     179             :   ::DDS::Security::SecurityException & ex)
     180             : {
     181           9 :   if (0 == auth_plugin) {
     182           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: Null Authentication plugin");
     183           1 :     return DDS::HANDLE_NIL;
     184             :   }
     185             : 
     186           8 :   if (DDS::HANDLE_NIL == local_identity_handle) {
     187           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: Invalid Local Identity");
     188           1 :     return DDS::HANDLE_NIL;
     189             :   }
     190             : 
     191           7 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, DDS::HANDLE_NIL);
     192             : 
     193           7 :   ACIdentityMap::iterator iter = local_identity_map_.find(local_identity_handle);
     194             : 
     195           7 :   if (iter == local_identity_map_.end()) {
     196           1 :     CommonUtilities::set_security_error(ex,-1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: No matching local identity handle present");
     197           1 :     return DDS::HANDLE_NIL;
     198             :   }
     199             : 
     200           6 :   ACPermsMap::iterator piter = local_ac_perms_.find(iter->second);
     201             : 
     202           6 :   if (piter == local_ac_perms_.end()) {
     203           0 :     CommonUtilities::set_security_error(ex,-1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: No matching local permissions handle present");
     204           0 :     return DDS::HANDLE_NIL;
     205             :   }
     206             : 
     207             :   // permissions file
     208           6 :   TokenReader remote_perm_wrapper(remote_credential_token);
     209          12 :   SSL::SignedDocument remote_perm_doc(remote_perm_wrapper.get_bin_property_value("c.perm"));
     210             : 
     211           6 :   const LocalAccessCredentialData::shared_ptr& local_access_credential_data = piter->second.local_access_credential_data;
     212             : 
     213             :   // Validate the signature of the remote permissions
     214           6 :   const SSL::Certificate& local_ca = local_access_credential_data->get_ca_cert();
     215           6 :   std::string ca_subject;
     216             : 
     217           6 :   local_ca.subject_name_to_str(ca_subject);
     218             : 
     219           6 :   if (!remote_perm_doc.verify(local_ca)) {
     220           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: Remote permissions signature not verified");
     221           0 :     return DDS::HANDLE_NIL;
     222             :   }
     223             : 
     224             :   // The remote permissions signature is verified
     225           6 :   if (DCPS::DCPS_debug_level) {
     226           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT(
     227             :       "(%P|%t) AccessControlBuiltInImpl::validate_remote_permissions: Remote permissions document verified.\n")));
     228             :   }
     229             : 
     230           6 :   Permissions::shared_ptr remote_permissions = DCPS::make_rch<Permissions>();
     231           6 :   if (remote_permissions->load(remote_perm_doc)) {
     232           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: Invalid permission file");
     233           0 :     return DDS::HANDLE_NIL;
     234             :   }
     235             : 
     236             :   //Extract and compare the remote subject name for validation
     237           6 :   TokenReader remote_credential_tr(remote_credential_token);
     238           6 :   const DDS::OctetSeq& cid = remote_credential_tr.get_bin_property_value("c.id");
     239             : 
     240           6 :   if (cid.length() == 0) {
     241           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: Invalid remote credential identity");
     242           0 :     return DDS::HANDLE_NIL;
     243             :   }
     244             : 
     245           6 :   SSL::Certificate::unique_ptr remote_cert(new SSL::Certificate);
     246           6 :   remote_cert->deserialize(cid);
     247             : 
     248           6 :   std::string remote_identity_sn;
     249           6 :   remote_cert->subject_name_to_str(remote_identity_sn);
     250             : 
     251           6 :   SSL::SubjectName sn_id_remote;
     252             : 
     253           6 :   if (remote_identity_sn.empty() || sn_id_remote.parse(remote_identity_sn) != 0 || !remote_permissions->has_grant(sn_id_remote)) {
     254           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::validate_remote_permissions: "
     255             :                                         "Remote identity subject name does not match any subject name in remote permissions grants");
     256           0 :     return DDS::HANDLE_NIL;
     257             :   }
     258             : 
     259             :   // Set and store the permissions credential token while we have the raw content
     260           6 :   remote_permissions->perm_token_ = remote_permissions_token;
     261           6 :   remote_permissions->perm_cred_token_ = remote_credential_token;
     262             : 
     263             : 
     264           6 :   AccessData cache_this;
     265           6 :   cache_this.identity = remote_identity_handle;
     266           6 :   cache_this.subject = sn_id_remote;
     267           6 :   cache_this.domain_id = piter->second.domain_id;
     268           6 :   cache_this.perm = remote_permissions;
     269           6 :   cache_this.gov = piter->second.gov;
     270           6 :   cache_this.local_access_credential_data = local_access_credential_data;
     271             : 
     272           6 :   const int perm_handle = generate_handle();
     273           6 :   local_ac_perms_.insert(std::make_pair(perm_handle, cache_this));
     274           6 :   if (DCPS::security_debug.bookkeeping) {
     275           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
     276             :                ACE_TEXT("AccessControlBuiltInImpl::validate_remote_permissions local_ac_perms_ (total %B)\n"),
     277             :                local_ac_perms_.size()));
     278             :   }
     279           6 :   return perm_handle;
     280           7 : }
     281             : 
     282           2 : ::CORBA::Boolean AccessControlBuiltInImpl::check_create_participant(
     283             :   ::DDS::Security::PermissionsHandle permissions_handle,
     284             :   ::DDS::Security::DomainId_t domain_id,
     285             :   const ::DDS::DomainParticipantQos & /*qos*/,
     286             :   ::DDS::Security::SecurityException & ex)
     287             : {
     288           2 :   if (DDS::HANDLE_NIL == permissions_handle) {
     289           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_participant: Invalid permissions handle");
     290             :   }
     291             : 
     292             : /*
     293             :  *  The rules of this method need to be evaluated in this order, however, we need to check
     294             :  *  to make sure the permission handle exists in our store prior to assessing these rules
     295             : */
     296             :   /* From Table 63 of the spec.
     297             :      This operation shall use the permissions_handle to retrieve
     298             :      the cached Permissions and Governance information.
     299             :              If the Governance specifies any topics on the
     300             :      DomainParticipant domain_id with
     301             :      enable_read_access_control set to FALSE or with
     302             :      enable_write_access_control set to FALSE, then the
     303             :      operation shall succeed and return TRUE.
     304             :              If the ParticipantSecurityAttributes has
     305             :      is_access_protected set to FALSE, then the operation shall
     306             :      succeed and return TRUE.
     307             :              Otherwise the operation shall return FALSE.
     308             :  */
     309             : 
     310           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     311             : 
     312           1 :   ACPermsMap::iterator piter = local_ac_perms_.find(permissions_handle);
     313             : 
     314           1 :   if (piter == local_ac_perms_.end()) {
     315           0 :     return CommonUtilities::set_security_error(ex, -1, 0,
     316             :       "AccessControlBuiltInImpl::check_create_participant: "
     317           0 :       "No matching permissions handle present");
     318             :   }
     319             : 
     320           1 :   if (domain_id != piter->second.domain_id) {
     321           0 :     return CommonUtilities::set_security_error(ex, -1, 0,
     322             :       "AccessControlBuiltInImpl::check_create_participant: "
     323           0 :       "Domain does not match validated permissions handle");
     324             :   }
     325             : 
     326           1 :   gov_iter begin = piter->second.gov->access_rules().begin();
     327           1 :   gov_iter end = piter->second.gov->access_rules().end();
     328             : 
     329           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
     330             : 
     331           1 :     if (giter->domains.has(domain_id)) {
     332           1 :       Governance::TopicAccessRules::iterator tr_iter;
     333             : 
     334           1 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     335           1 :         if (!tr_iter->topic_attrs.is_read_protected || !tr_iter->topic_attrs.is_write_protected) {
     336           1 :           return true;
     337             :         }
     338             :       }
     339             : 
     340           0 :       if (!giter->domain_attrs.is_access_protected) {
     341           0 :         return true;
     342             :       }
     343             :     }
     344             :   }
     345             : 
     346           0 :   return CommonUtilities::set_security_error(ex, -1, 0,
     347             :     "AccessControlBuiltInImpl::check_create_participant: "
     348           0 :     "No governance exists for this domain");
     349           1 : }
     350             : 
     351           5 : ::CORBA::Boolean AccessControlBuiltInImpl::check_create_datawriter(
     352             :   ::DDS::Security::PermissionsHandle permissions_handle,
     353             :   ::DDS::Security::DomainId_t domain_id,
     354             :   const char * topic_name,
     355             :   const ::DDS::DataWriterQos & /*qos*/,
     356             :   const ::DDS::PartitionQosPolicy & partition,
     357             :   const ::DDS::Security::DataTags & /*data_tag*/,
     358             :   ::DDS::Security::SecurityException & ex)
     359             : {
     360           5 :   if (DDS::HANDLE_NIL == permissions_handle) {
     361           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datawriter: Invalid permissions handle");
     362             :   }
     363           4 :   if (0 == topic_name) {
     364           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datawriter: Invalid Topic Name");
     365             :   }
     366             : 
     367           3 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     368             : 
     369           3 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     370             : 
     371           3 :   if (ac_iter == local_ac_perms_.end()) {
     372           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datawriter: No matching permissions handle present");
     373             :   }
     374             : 
     375           3 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     376           3 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     377             : 
     378           6 :   for (gov_iter giter = begin; giter != end; ++giter) {
     379             : 
     380           3 :     if (giter->domains.has(domain_id)) {
     381           3 :       Governance::TopicAccessRules::iterator tr_iter;
     382             : 
     383          12 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     384           9 :         if (pattern_match(topic_name, tr_iter->topic_expression.c_str())) {
     385           2 :           if (!tr_iter->topic_attrs.is_write_protected) {
     386           0 :             return true;
     387             :           }
     388             :         }
     389             :       }
     390             :     }
     391             :   }
     392             : 
     393             :   // Check the Permissions file
     394             : 
     395           3 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     396           3 :   if (!grant) {
     397           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datawriter: Permissions grant not found");
     398             :   }
     399             : 
     400           3 :   if (!validate_date_time(grant->validity, ex)) {
     401           1 :     return false;
     402             :   }
     403             : 
     404           2 :   if (!search_permissions(topic_name, domain_id, partition, Permissions::PUBLISH, *grant, ex)) {
     405           0 :     return false;
     406             :   }
     407             : 
     408           2 :   make_task(local_rp_task_)->insert(permissions_handle, grant->validity.not_after);
     409             : 
     410           2 :   return true;
     411           3 : }
     412             : 
     413           5 : ::CORBA::Boolean AccessControlBuiltInImpl::check_create_datareader(
     414             :   ::DDS::Security::PermissionsHandle permissions_handle,
     415             :   ::DDS::Security::DomainId_t domain_id,
     416             :   const char * topic_name,
     417             :   const ::DDS::DataReaderQos & /*qos*/,
     418             :   const ::DDS::PartitionQosPolicy & partition,
     419             :   const ::DDS::Security::DataTags & /*data_tag*/,
     420             :   ::DDS::Security::SecurityException & ex)
     421             : {
     422           5 :   if (DDS::HANDLE_NIL == permissions_handle) {
     423           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datareader: Invalid permissions handle");
     424             :   }
     425             : 
     426           4 :   if (0 == topic_name) {
     427           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datareader: Invalid Topic Name");
     428             :   }
     429             : 
     430           3 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     431             : 
     432           3 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     433             : 
     434           3 :   if (ac_iter == local_ac_perms_.end()) {
     435           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datareader: No matching permissions handle present");
     436             :   }
     437             : 
     438           3 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     439           3 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     440             : 
     441           6 :   for (gov_iter giter = begin; giter != end; ++giter) {
     442             : 
     443           3 :     if (giter->domains.has(domain_id)) {
     444           3 :       Governance::TopicAccessRules::iterator tr_iter;
     445             : 
     446          12 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     447           9 :         if (pattern_match(topic_name, tr_iter->topic_expression.c_str())) {
     448           2 :           if (!tr_iter->topic_attrs.is_read_protected) {
     449           0 :             return true;
     450             :           }
     451             :         }
     452             :       }
     453             :     }
     454             :   }
     455             : 
     456             :   // Check the Permissions file
     457             : 
     458           3 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     459           3 :   if (!grant) {
     460           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datareader: Permissions grant not found");
     461             :   }
     462             : 
     463           3 :   if (!validate_date_time(grant->validity, ex)) {
     464           0 :     return false;
     465             :   }
     466             : 
     467           3 :   if (!search_permissions(topic_name, domain_id, partition, Permissions::SUBSCRIBE, *grant, ex)) {
     468           0 :     return false;
     469             :   }
     470             : 
     471           3 :   make_task(local_rp_task_)->insert(permissions_handle, grant->validity.not_after);
     472             : 
     473           3 :   return true;
     474           3 : }
     475             : 
     476           4 : ::CORBA::Boolean AccessControlBuiltInImpl::check_create_topic(
     477             :   ::DDS::Security::PermissionsHandle permissions_handle,
     478             :   ::DDS::Security::DomainId_t domain_id,
     479             :   const char * topic_name,
     480             :   const ::DDS::TopicQos & /*qos*/,
     481             :   ::DDS::Security::SecurityException & ex)
     482             : {
     483           4 :   if (DDS::HANDLE_NIL == permissions_handle) {
     484           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: Invalid permissions handle");
     485             :   }
     486           3 :   if (0 == topic_name) {
     487           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: Invalid Topic Name");
     488             :   }
     489             : 
     490           2 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     491             : 
     492           2 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     493             : 
     494           2 :   if (ac_iter == local_ac_perms_.end()) {
     495           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: No matching permissions handle present");
     496             :   }
     497             : 
     498             :   // Check the Governance file for allowable topic attributes
     499             : 
     500           2 :   if (domain_id != ac_iter->second.domain_id) {
     501           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: Requested domain ID does not match permissions handle");
     502             :   }
     503             : 
     504           2 :   ::DDS::Security::DomainId_t domain_to_find = ac_iter->second.domain_id;
     505             : 
     506           2 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     507           2 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     508             : 
     509           2 :   for (gov_iter giter = begin; giter != end; ++giter) {
     510             : 
     511           2 :     if (giter->domains.has(domain_to_find)) {
     512           2 :       Governance::TopicAccessRules::iterator tr_iter;
     513             : 
     514           2 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     515           2 :         if (pattern_match(topic_name, tr_iter->topic_expression.c_str())) {
     516           2 :           if (!tr_iter->topic_attrs.is_read_protected || !tr_iter->topic_attrs.is_write_protected) {
     517           2 :             return true;
     518             :           }
     519             :         }
     520             :       }
     521             :     }
     522             :   }
     523             : 
     524           0 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     525           0 :   if (!grant) {
     526           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: grant not found");
     527             :   }
     528             : 
     529           0 :   if (!validate_date_time(grant->validity, ex)) {
     530           0 :     return false;
     531             :   }
     532             : 
     533             :   Permissions::PublishSubscribe_t denied_type;
     534           0 :   bool found_deny = false;
     535             :   // Iterate over allow / deny rules
     536           0 :   for (perm_topic_rules_iter ptr_iter = grant->rules.begin(); ptr_iter != grant->rules.end(); ++ptr_iter) {
     537             : 
     538           0 :     if (ptr_iter->domains.has(domain_to_find)) {
     539             : 
     540           0 :       perm_topic_actions_iter tpsr_iter;
     541           0 :       for (tpsr_iter = ptr_iter->actions.begin(); tpsr_iter != ptr_iter->actions.end(); ++tpsr_iter) {
     542             : 
     543           0 :         std::vector<std::string>::iterator tl_iter;
     544           0 :         for (tl_iter = tpsr_iter->topics.begin(); tl_iter != tpsr_iter->topics.end(); ++tl_iter) {
     545             : 
     546           0 :           if (pattern_match(topic_name, tl_iter->c_str())) {
     547           0 :             if (ptr_iter->ad_type == Permissions::ALLOW) {
     548           0 :               return true;
     549             :             }
     550           0 :             if (found_deny && denied_type != tpsr_iter->ps_type) {
     551           0 :               return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: Both publish and subscribe are denied for this topic.");
     552           0 :             } else if (!found_deny) {
     553           0 :               found_deny = true;
     554           0 :               denied_type = tpsr_iter->ps_type;
     555             :             }
     556             :           }
     557             :         }
     558             :       }
     559             :     }
     560             :   }
     561             : 
     562             :   // There is no matching rule for topic_name so use the value in default_permission
     563           0 :   if (grant->default_permission == Permissions::ALLOW) {
     564           0 :     return true;
     565             :   } else {
     566           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_topic: No matching rule for topic, default permission is DENY.");
     567             :   }
     568           2 : }
     569             : 
     570           4 : ::CORBA::Boolean AccessControlBuiltInImpl::check_local_datawriter_register_instance(
     571             :   ::DDS::Security::PermissionsHandle permissions_handle,
     572             :   ::DDS::DataWriter_ptr writer,
     573             :   ::DDS::DynamicData_ptr key,
     574             :   ::DDS::Security::SecurityException & ex)
     575             : {
     576           4 :   if (DDS::HANDLE_NIL == permissions_handle) {
     577           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_register_instance: Invalid permissions handle");
     578             :   }
     579           3 :   if (0 == writer) {
     580           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_register_instance: Invalid Writer");
     581             :   }
     582           2 :   if (0 == key) {
     583           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_register_instance: Invalid Topic Key");
     584             :   }
     585             : 
     586           1 :   return true;
     587             : }
     588             : 
     589           4 : ::CORBA::Boolean AccessControlBuiltInImpl::check_local_datawriter_dispose_instance(
     590             :   ::DDS::Security::PermissionsHandle permissions_handle,
     591             :   ::DDS::DataWriter_ptr writer,
     592             :   ::DDS::DynamicData_ptr key,
     593             :   ::DDS::Security::SecurityException & ex)
     594             : {
     595           4 :   if (DDS::HANDLE_NIL == permissions_handle) {
     596           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_dispose_instance: Invalid permissions handle");
     597             :   }
     598           3 :   if (0 == writer) {
     599           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_dispose_instance: Invalid Writer");
     600             :   }
     601           2 :   if (0 == key) {
     602           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_dispose_instance: Invalid Topic Key");
     603             :   }
     604             : 
     605           1 :   return true;
     606             : }
     607             : 
     608           3 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_participant(
     609             :   ::DDS::Security::PermissionsHandle permissions_handle,
     610             :   ::DDS::Security::DomainId_t domain_id,
     611             :   const ::DDS::Security::ParticipantBuiltinTopicDataSecure & participant_data,
     612             :   ::DDS::Security::SecurityException & ex)
     613             : {
     614           3 :   if (DDS::HANDLE_NIL == permissions_handle) {
     615           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Invalid permissions handle");
     616             :   }
     617             : 
     618           2 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     619             : 
     620           2 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     621             : 
     622           2 :   if (ac_iter == local_ac_perms_.end()) {
     623           0 :     return CommonUtilities::set_security_error(ex,-1, 0, "AccessControlBuiltInImpl::check_remote_participant: No matching permissions handle present");
     624             :   }
     625             : 
     626           2 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     627           2 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     628             : 
     629           3 :   for (gov_iter giter = begin; giter != end; ++giter) {
     630           2 :     if (giter->domains.has(domain_id) && !giter->domain_attrs.is_access_protected) {
     631           1 :       return true;
     632             :     }
     633             :   }
     634             : 
     635             :   // Check the PluginClassName and MajorVersion of the local permissions vs. remote  See Table 63 of spec
     636           1 :   const std::string remote_class_id = participant_data.base.permissions_token.class_id.in();
     637             : 
     638           1 :   std::string local_plugin_class_name,
     639           1 :               remote_plugin_class_name;
     640           1 :   int local_major_ver = 0,
     641             :       local_minor_ver,
     642             :       remote_major_ver,
     643             :       remote_minor_ver;
     644             : 
     645           1 :   if (remote_class_id.length() > 0) {
     646           1 :     parse_class_id(remote_class_id, remote_plugin_class_name, remote_major_ver, remote_minor_ver);
     647             :   } else {
     648           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Invalid remote class ID");
     649             :   }
     650             : 
     651           1 :   for (ACPermsMap::iterator local_iter = local_ac_perms_.begin(); local_iter != local_ac_perms_.end(); ++local_iter) {
     652           1 :     if (local_iter->second.domain_id == domain_id && local_iter->first != permissions_handle) {
     653           1 :       const std::string local_class_id = local_iter->second.perm->perm_token_.class_id.in();
     654             : 
     655           1 :       if (local_class_id.length() > 0) {
     656           1 :         parse_class_id(local_class_id, local_plugin_class_name, local_major_ver, local_minor_ver);
     657           1 :         break;
     658             :       } else {
     659           0 :         return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Invalid local class ID");
     660             :       }
     661           1 :     }
     662             :   }
     663             : 
     664           1 :   if (strcmp(local_plugin_class_name.c_str(), remote_plugin_class_name.c_str())) {
     665           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Class ID plugin class name do not match");
     666             :   }
     667             : 
     668           1 :   if (local_major_ver != remote_major_ver) {
     669           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Class ID major versions do not match");
     670             :   }
     671             : 
     672           1 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     673           1 :   if (!grant) {
     674           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Permissions grant not found");
     675             :   }
     676             : 
     677           1 :   for (perm_topic_rules_iter ptr_iter = grant->rules.begin(); ptr_iter != grant->rules.end(); ++ptr_iter) {
     678           1 :     if (ptr_iter->domains.has(domain_id) && ptr_iter->ad_type == Permissions::ALLOW) {
     679           1 :       return true;
     680             :     }
     681             :   }
     682             : 
     683           0 :   if (grant->default_permission == Permissions::ALLOW) {
     684           0 :     return true; // DDSSEC12-85
     685             :   }
     686             : 
     687           0 :   return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_participant: Not authorized for domain");
     688           2 : }
     689             : 
     690           2 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_datawriter(
     691             :   ::DDS::Security::PermissionsHandle permissions_handle,
     692             :   ::DDS::Security::DomainId_t domain_id,
     693             :   const ::DDS::Security::PublicationBuiltinTopicDataSecure & publication_data,
     694             :   ::DDS::Security::SecurityException & ex)
     695             : {
     696           2 :   if (DDS::HANDLE_NIL == permissions_handle) {
     697           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter: Invalid permissions handle");
     698             :   }
     699             : 
     700           1 :   if (publication_data.base.base.topic_name[0] == 0) {
     701           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter: Invalid topic name");
     702             :   }
     703             : 
     704           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     705             : 
     706           1 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     707             : 
     708           1 :   if (ac_iter == local_ac_perms_.end()) {
     709           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter: No matching permissions handle present");
     710             :   }
     711             : 
     712           1 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     713           1 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     714             : 
     715           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
     716             : 
     717           1 :     if (giter->domains.has(domain_id)) {
     718           1 :       Governance::TopicAccessRules::iterator tr_iter;
     719             : 
     720           1 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     721           1 :         if (pattern_match(publication_data.base.base.topic_name, tr_iter->topic_expression.c_str())) {
     722           1 :           if (!tr_iter->topic_attrs.is_write_protected) {
     723           1 :             return true;
     724             :           }
     725             :         }
     726             :       }
     727             :     }
     728             :   }
     729             : 
     730           0 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     731           0 :   if (!grant) {
     732           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter: Permissions grant not found");
     733             :   }
     734             : 
     735           0 :   if (!validate_date_time(grant->validity, ex)) {
     736           0 :     return false;
     737             :   }
     738             : 
     739           0 :   if (!search_permissions(publication_data.base.base.topic_name, domain_id,
     740           0 :                           publication_data.base.base.partition, Permissions::PUBLISH,
     741           0 :                           *grant, ex)) {
     742           0 :     return false;
     743             :   }
     744             : 
     745           0 :   make_task(remote_rp_task_)->insert(permissions_handle, grant->validity.not_after);
     746             : 
     747           0 :   return true;
     748           1 : }
     749             : 
     750           2 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_datareader(
     751             :   ::DDS::Security::PermissionsHandle permissions_handle,
     752             :   ::DDS::Security::DomainId_t domain_id,
     753             :   const ::DDS::Security::SubscriptionBuiltinTopicDataSecure & subscription_data,
     754             :   ::CORBA::Boolean & relay_only,
     755             :   ::DDS::Security::SecurityException & ex)
     756             : {
     757           2 :   if (DDS::HANDLE_NIL == permissions_handle) {
     758           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datareader: Invalid permissions handle");
     759             :   }
     760             : 
     761           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     762             : 
     763           1 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     764             : 
     765           1 :   if (ac_iter == local_ac_perms_.end()) {
     766           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_create_datareader: No matching permissions handle present");
     767             :   }
     768             : 
     769             :   // Default this to false for now
     770           1 :   relay_only = false;
     771             : 
     772           1 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     773           1 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     774             : 
     775           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
     776             : 
     777           1 :     if (giter->domains.has(domain_id)) {
     778           1 :       Governance::TopicAccessRules::iterator tr_iter;
     779             : 
     780           1 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     781           1 :         if (pattern_match(subscription_data.base.base.topic_name, tr_iter->topic_expression.c_str())) {
     782           1 :           if (!tr_iter->topic_attrs.is_read_protected) {
     783           1 :             return true;
     784             :           }
     785             :         }
     786             :       }
     787             :     }
     788             :   }
     789             : 
     790           0 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     791           0 :   if (!grant) {
     792           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datareader: Permissions grant not found");
     793             :   }
     794             : 
     795           0 :   if (!validate_date_time(grant->validity, ex)) {
     796           0 :     return false;
     797             :   }
     798             : 
     799           0 :   if (!search_permissions(subscription_data.base.base.topic_name, domain_id,
     800           0 :                           subscription_data.base.base.partition, Permissions::SUBSCRIBE,
     801           0 :                           *grant, ex)) {
     802           0 :     return false;
     803             :   }
     804             : 
     805           0 :   make_task(remote_rp_task_)->insert(permissions_handle, grant->validity.not_after);
     806             : 
     807           0 :   return true;
     808           1 : }
     809             : 
     810           2 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_topic(
     811             :   ::DDS::Security::PermissionsHandle permissions_handle,
     812             :   ::DDS::Security::DomainId_t domain_id,
     813             :   const ::DDS::TopicBuiltinTopicData & topic_data,
     814             :   ::DDS::Security::SecurityException & ex)
     815             : {
     816             :   // NOTE: permissions_handle is for the remote DomainParticipant.
     817           2 :   if (DDS::HANDLE_NIL == permissions_handle) {
     818           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Invalid permissions handle");
     819             :   }
     820             : 
     821           1 :   if (topic_data.name[0] == 0) {
     822           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Invalid topic data");
     823             :   }
     824             : 
     825           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
     826             : 
     827           1 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
     828             : 
     829           1 :   if (ac_iter == local_ac_perms_.end()) {
     830           0 :     return CommonUtilities::set_security_error(ex,-1, 0, "AccessControlBuiltInImpl::check_remote_topic: No matching permissions handle present");
     831             :   }
     832             : 
     833             :   // Compare the PluginClassName and MajorVersion of the local permissions_token
     834             :   // with those in the remote_permissions_token.
     835           1 :   const std::string remote_class_id = ac_iter->second.perm->perm_token_.class_id.in();
     836             : 
     837           1 :   std::string local_plugin_class_name,
     838           1 :               remote_plugin_class_name;
     839           1 :   int local_major_ver = 0,
     840             :       local_minor_ver,
     841             :       remote_major_ver,
     842             :       remote_minor_ver;
     843             : 
     844           1 :   if (remote_class_id.length() > 0) {
     845           1 :     parse_class_id(remote_class_id, remote_plugin_class_name, remote_major_ver, remote_minor_ver);
     846             :   } else {
     847           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Invalid remote class ID");
     848             :   }
     849             : 
     850           1 :   for (ACPermsMap::iterator local_iter = local_ac_perms_.begin(); local_iter != local_ac_perms_.end(); ++local_iter) {
     851           1 :     if (local_iter->second.domain_id == domain_id && local_iter->first != permissions_handle) {
     852           1 :       const std::string local_class_id = local_iter->second.perm->perm_token_.class_id.in();
     853             : 
     854           1 :       if (local_class_id.length() > 0) {
     855           1 :         parse_class_id(local_class_id, local_plugin_class_name, local_major_ver, local_minor_ver);
     856           1 :         break;
     857             :       } else {
     858           0 :         return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Invalid local class ID");
     859             :       }
     860           1 :     }
     861             :   }
     862             : 
     863           1 :   if (strcmp(local_plugin_class_name.c_str(), remote_plugin_class_name.c_str())) {
     864           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Class ID plugin class name do not match");
     865             :   }
     866             : 
     867           1 :   if (local_major_ver != remote_major_ver) {
     868           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Class ID major versions do not match");
     869             :   }
     870             : 
     871             :   // Check the Governance file for allowable topic attributes
     872             : 
     873           1 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
     874           1 :   gov_iter end = ac_iter->second.gov->access_rules().end();
     875             : 
     876           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
     877             : 
     878           1 :     if (giter->domains.has(domain_id)) {
     879           1 :       Governance::TopicAccessRules::iterator tr_iter;
     880             : 
     881           1 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
     882           1 :         if (pattern_match(topic_data.name, tr_iter->topic_expression.c_str())) {
     883           1 :           if (!tr_iter->topic_attrs.is_read_protected || !tr_iter->topic_attrs.is_write_protected) {
     884           1 :             return true;
     885             :           }
     886             :         }
     887             :       }
     888             :     }
     889             :   }
     890             : 
     891           0 :   const Permissions::Grant_rch grant = ac_iter->second.perm->find_grant(ac_iter->second.subject);
     892           0 :   if (!grant) {
     893           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: grant not found");
     894             :   }
     895             : 
     896           0 :   if (!validate_date_time(grant->validity, ex)) {
     897           0 :     return false;
     898             :   }
     899             : 
     900             :   Permissions::PublishSubscribe_t denied_type;
     901           0 :   bool found_deny = false;
     902           0 :   for (perm_topic_rules_iter ptr_iter = grant->rules.begin(); ptr_iter != grant->rules.end(); ++ptr_iter) {
     903             : 
     904           0 :     if (ptr_iter->domains.has(domain_id)) {
     905             : 
     906             :       // Iterate over pub / sub rules
     907           0 :       perm_topic_actions_iter tpsr_iter;
     908           0 :       for (tpsr_iter = ptr_iter->actions.begin(); tpsr_iter != ptr_iter->actions.end(); ++tpsr_iter) {
     909             : 
     910             :         // Check to make sure they can publish or subscribe to the topic
     911             :         // TODO Add support for relay permissions once relay only key exchange is supported
     912           0 :         if (tpsr_iter->ps_type == Permissions::PUBLISH || tpsr_iter->ps_type == Permissions::SUBSCRIBE) {
     913             : 
     914           0 :           std::vector<std::string>::iterator tl_iter;
     915           0 :           for (tl_iter = tpsr_iter->topics.begin(); tl_iter != tpsr_iter->topics.end(); ++tl_iter) {
     916             : 
     917           0 :             if (pattern_match(topic_data.name, tl_iter->c_str())) {
     918           0 :               if (ptr_iter->ad_type == Permissions::ALLOW) {
     919           0 :                 return true;
     920             :               }
     921           0 :               if (found_deny && denied_type != tpsr_iter->ps_type) {
     922           0 :                 return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: Both publish and subscribe are denied for this topic.");
     923           0 :               } else if (!found_deny) {
     924           0 :                 found_deny = true;
     925           0 :                 denied_type = tpsr_iter->ps_type;
     926             :               }
     927             :             }
     928             :           }
     929             :         }
     930             :       }
     931             :     }
     932             :   }
     933             : 
     934             :   // There is no matching rule for topic_name so use the value in default_permission
     935           0 :   if (grant->default_permission == Permissions::ALLOW) {
     936           0 :     return true;
     937             :   } else {
     938           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_topic: No matching rule for topic, default permission is DENY.");
     939             :   }
     940           1 : }
     941             : 
     942           3 : ::CORBA::Boolean AccessControlBuiltInImpl::check_local_datawriter_match(
     943             :   ::DDS::Security::PermissionsHandle writer_permissions_handle,
     944             :   ::DDS::Security::PermissionsHandle reader_permissions_handle,
     945             :   const ::DDS::Security::PublicationBuiltinTopicDataSecure & /*publication_data*/,
     946             :   const ::DDS::Security::SubscriptionBuiltinTopicDataSecure & /*subscription_data*/,
     947             :   ::DDS::Security::SecurityException & ex)
     948             : {
     949           3 :   if (DDS::HANDLE_NIL == writer_permissions_handle) {
     950           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_match: Invalid writer permissions handle");
     951             :   }
     952           2 :   if (DDS::HANDLE_NIL == reader_permissions_handle) {
     953           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datawriter_match: Invalid reader permissions handle");
     954             :   }
     955             : 
     956           1 :   return true;
     957             : }
     958             : 
     959           3 : ::CORBA::Boolean AccessControlBuiltInImpl::check_local_datareader_match(
     960             :   ::DDS::Security::PermissionsHandle reader_permissions_handle,
     961             :   ::DDS::Security::PermissionsHandle writer_permissions_handle,
     962             :   const ::DDS::Security::SubscriptionBuiltinTopicDataSecure & /*subscription_data*/,
     963             :   const ::DDS::Security::PublicationBuiltinTopicDataSecure & /*publication_data*/,
     964             :   ::DDS::Security::SecurityException & ex)
     965             : {
     966           3 :   if (DDS::HANDLE_NIL == writer_permissions_handle) {
     967           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datareader_match: Invalid writer permissions handle");
     968             :   }
     969           2 :   if (DDS::HANDLE_NIL == reader_permissions_handle) {
     970           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_local_datareader_match: Invalid reader permissions handle");
     971             :   }
     972             : 
     973           1 :   return true;
     974             : }
     975             : 
     976           4 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_datawriter_register_instance(
     977             :   ::DDS::Security::PermissionsHandle permissions_handle,
     978             :   ::DDS::DataReader_ptr reader,
     979             :   ::DDS::InstanceHandle_t publication_handle,
     980             :   ::DDS::DynamicData_ptr key,
     981             :   ::DDS::Security::SecurityException & ex)
     982             : {
     983           4 :   if (DDS::HANDLE_NIL == permissions_handle ||
     984             :       DDS::HANDLE_NIL == publication_handle) {
     985           2 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter_register_instance: Invalid handle");
     986             :   }
     987           2 :   if (0 == reader) {
     988           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter_register_instance: Invalid Reader pointer");
     989             :   }
     990             :   // Key could be null if we don't have complete type objects
     991             :   ACE_UNUSED_ARG(key);
     992           1 :   return true;
     993             : }
     994             : 
     995           3 : ::CORBA::Boolean AccessControlBuiltInImpl::check_remote_datawriter_dispose_instance(
     996             :   ::DDS::Security::PermissionsHandle permissions_handle,
     997             :   ::DDS::DataReader_ptr reader,
     998             :   ::DDS::InstanceHandle_t publication_handle,
     999             :   ::DDS::DynamicData_ptr key,
    1000             :   ::DDS::Security::SecurityException & ex)
    1001             : {
    1002           3 :   if (DDS::HANDLE_NIL == permissions_handle ||
    1003             :       DDS::HANDLE_NIL == publication_handle) {
    1004           2 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter_dispose_instance: Invalid handle");
    1005             :   }
    1006           1 :   if (0 == reader) {
    1007           1 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::check_remote_datawriter_dispose_instance: Invalid Reader pointer");
    1008             :   }
    1009             :   // Key could be null if we don't have complete type objects
    1010             :   ACE_UNUSED_ARG(key);
    1011           0 :   return true;
    1012             : }
    1013             : 
    1014           2 : ::CORBA::Boolean AccessControlBuiltInImpl::get_permissions_token(
    1015             :   ::DDS::Security::PermissionsToken & permissions_token,
    1016             :   ::DDS::Security::PermissionsHandle handle,
    1017             :   ::DDS::Security::SecurityException & ex)
    1018             : {
    1019           2 :   if (DDS::HANDLE_NIL == handle) {
    1020           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_permissions_token: Invalid permissions handle");
    1021           1 :     return false;
    1022             :   }
    1023             : 
    1024           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
    1025             : 
    1026           1 :   ACPermsMap::iterator iter = local_ac_perms_.find(handle);
    1027             : 
    1028           1 :   if (iter != local_ac_perms_.end()) {
    1029           1 :     permissions_token = iter->second.perm->perm_token_;
    1030           1 :     return true;
    1031             :   } else {
    1032           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_permissions_token: No PermissionToken found");
    1033           0 :     return false;
    1034             :   }
    1035           1 : }
    1036             : 
    1037           2 : ::CORBA::Boolean AccessControlBuiltInImpl::get_permissions_credential_token(
    1038             :   ::DDS::Security::PermissionsCredentialToken & permissions_credential_token,
    1039             :   ::DDS::Security::PermissionsHandle handle,
    1040             :   ::DDS::Security::SecurityException & ex)
    1041             : {
    1042           2 :   if (DDS::HANDLE_NIL == handle) {
    1043           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_permissions_credential_token: Invalid permissions handle");
    1044           1 :     return false;
    1045             :   }
    1046             : 
    1047           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
    1048             : 
    1049           1 :   ACPermsMap::iterator iter = local_ac_perms_.find(handle);
    1050             : 
    1051           1 :   if (iter != local_ac_perms_.end()) {
    1052           1 :     permissions_credential_token = iter->second.perm->perm_cred_token_;
    1053           1 :     return true;
    1054             :   } else {
    1055           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_permissions_credential_token: No PermissionToken found");
    1056           0 :     return false;
    1057             :   }
    1058           1 : }
    1059             : 
    1060           2 : ::CORBA::Boolean AccessControlBuiltInImpl::set_listener(
    1061             :   ::DDS::Security::AccessControlListener_ptr listener,
    1062             :   ::DDS::Security::SecurityException & ex)
    1063             : {
    1064           2 :   if (0 == listener) {
    1065           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::set_listener: Invalid Listener pointer");
    1066           1 :     return false;
    1067             :   }
    1068             : 
    1069           1 :   ACE_Guard<ACE_Thread_Mutex> guard(handle_mutex_);
    1070             : 
    1071           1 :   listener_ptr_ = listener;
    1072           1 :   return true;
    1073           1 : }
    1074             : 
    1075           0 : ::CORBA::Boolean AccessControlBuiltInImpl::return_permissions_handle(
    1076             :     ::DDS::Security::PermissionsHandle handle,
    1077             :     ::DDS::Security::SecurityException& ex)
    1078             : {
    1079           0 :   if (DDS::HANDLE_NIL == handle) {
    1080           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::return_permissiosn_handle: Invalid permissions handle");
    1081           0 :     return false;
    1082             :   }
    1083             : 
    1084           0 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(handle);
    1085             : 
    1086           0 :   if (ac_iter == local_ac_perms_.end()) {
    1087           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::return_permissions_handle: No matching permissions handle present");
    1088           0 :     return false;
    1089             :   }
    1090             : 
    1091           0 :   local_ac_perms_.erase(ac_iter);
    1092           0 :   if (DCPS::security_debug.bookkeeping) {
    1093           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1094             :                ACE_TEXT("AccessControlBuiltInImpl::return_permissions_handle local_ac_perms_ (total %B)\n"),
    1095             :                local_ac_perms_.size()));
    1096             :   }
    1097           0 :   make_task(local_rp_task_)->erase(handle);
    1098           0 :   make_task(remote_rp_task_)->erase(handle);
    1099             : 
    1100           0 :   return true;
    1101             : }
    1102             : 
    1103           1 : ::CORBA::Boolean AccessControlBuiltInImpl::return_permissions_token(
    1104             :   const ::DDS::Security::PermissionsToken & token,
    1105             :   ::DDS::Security::SecurityException & ex)
    1106             : {
    1107             :   ACE_UNUSED_ARG(token);
    1108             :   ACE_UNUSED_ARG(ex);
    1109             : 
    1110           1 :   return true;
    1111             : }
    1112             : 
    1113           1 : ::CORBA::Boolean AccessControlBuiltInImpl::return_permissions_credential_token(
    1114             :   const ::DDS::Security::PermissionsCredentialToken & permissions_credential_token,
    1115             :   ::DDS::Security::SecurityException & ex)
    1116             : {
    1117             :   ACE_UNUSED_ARG(permissions_credential_token);
    1118             :   ACE_UNUSED_ARG(ex);
    1119             : 
    1120           1 :   return true;
    1121             : }
    1122             : 
    1123           2 : ::CORBA::Boolean AccessControlBuiltInImpl::get_participant_sec_attributes(
    1124             :   ::DDS::Security::PermissionsHandle permissions_handle,
    1125             :   ::DDS::Security::ParticipantSecurityAttributes & attributes,
    1126             :   ::DDS::Security::SecurityException & ex)
    1127             : {
    1128           2 :   if (DDS::HANDLE_NIL == permissions_handle) {
    1129           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_participant_sec_attributes: Invalid permissions handle");
    1130           1 :     return false;
    1131             :   }
    1132             : 
    1133           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
    1134             : 
    1135           1 :   ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
    1136             : 
    1137           1 :   if (ac_iter == local_ac_perms_.end()) {
    1138           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_participant_sec_attributes: No matching permissions handle present");
    1139           0 :     return false;
    1140             :   }
    1141             : 
    1142           1 :   gov_iter begin = ac_iter->second.gov->access_rules().begin();
    1143           1 :   gov_iter end = ac_iter->second.gov->access_rules().end();
    1144             : 
    1145           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
    1146             : 
    1147           1 :     if (giter->domains.has(ac_iter->second.domain_id)) {
    1148           1 :       attributes = giter->domain_attrs;
    1149           1 :       return true;
    1150             :     }
    1151             :   }
    1152             : 
    1153           0 :   CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_participant_sec_attributes: No matching domain in governance");
    1154           0 :   return false;
    1155           1 : }
    1156             : 
    1157           3 : ::CORBA::Boolean AccessControlBuiltInImpl::get_topic_sec_attributes(
    1158             :   ::DDS::Security::PermissionsHandle permissions_handle,
    1159             :   const char * topic_name,
    1160             :   ::DDS::Security::TopicSecurityAttributes & attributes,
    1161             :   ::DDS::Security::SecurityException & ex)
    1162             : {
    1163           3 :   if (DDS::HANDLE_NIL == permissions_handle) {
    1164           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_topic_sec_attributes: Invalid permissions handle");
    1165           1 :     return false;
    1166             :   }
    1167           2 :   if (0 == topic_name) {
    1168           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_topic_sec_attributes: Invalid topic name");
    1169           1 :     return false;
    1170             :   }
    1171             : 
    1172             :   // Extract Governance and the permissions data for the requested handle
    1173             : 
    1174           1 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
    1175             : 
    1176           1 :   ACPermsMap::iterator piter = local_ac_perms_.find(permissions_handle);
    1177             : 
    1178           1 :   if (piter == local_ac_perms_.end()) {
    1179           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_topic_sec_attributes: No matching permissions handle present");
    1180           0 :     return false;
    1181             :   }
    1182             : 
    1183           1 :   gov_iter begin = piter->second.gov->access_rules().begin();
    1184           1 :   gov_iter end = piter->second.gov->access_rules().end();
    1185             : 
    1186           1 :   for (gov_iter giter = begin; giter != end; ++giter) {
    1187             : 
    1188           1 :     if (giter->domains.has(piter->second.domain_id)) {
    1189           1 :       Governance::TopicAccessRules::iterator tr_iter;
    1190             : 
    1191           1 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
    1192           1 :         if (pattern_match(topic_name, tr_iter->topic_expression.c_str())) {
    1193           1 :           attributes = tr_iter->topic_attrs;
    1194           1 :           return true;
    1195             :         }
    1196             :       }
    1197             :     }
    1198             :   }
    1199             : 
    1200           0 :   CommonUtilities::set_security_error(ex,-1, 0, "AccessControlBuiltInImpl::get_topic_sec_attributes: No matching domain/topic in governance");
    1201           0 :   return false;
    1202           1 : }
    1203             : 
    1204           3 : ::CORBA::Boolean AccessControlBuiltInImpl::get_datawriter_sec_attributes(
    1205             :   ::DDS::Security::PermissionsHandle permissions_handle,
    1206             :   const char * topic_name,
    1207             :   const ::DDS::PartitionQosPolicy & partition,
    1208             :   const ::DDS::Security::DataTagQosPolicy & data_tag,
    1209             :   ::DDS::Security::EndpointSecurityAttributes & attributes,
    1210             :   ::DDS::Security::SecurityException & ex)
    1211             : {
    1212             :   // The spec claims there is supposed to be a topic name parameter
    1213             :   // to this function which is not in the IDL at this time
    1214             : 
    1215           3 :   if (DDS::HANDLE_NIL == permissions_handle) {
    1216           1 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_datawriter_sec_attributes: Invalid permissions handle");
    1217           1 :     return false;
    1218             :   }
    1219             : 
    1220           2 :   if (0 == topic_name) {
    1221           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_datawriter_sec_attributes: Invalid topic name");
    1222           0 :     return false;
    1223             :   }
    1224             : 
    1225           2 :   if (!get_sec_attributes(permissions_handle, topic_name, partition, data_tag, attributes, ex)) {
    1226           0 :     return false;
    1227             :   }
    1228             : 
    1229           2 :   return true;
    1230             : }
    1231             : 
    1232           1 : ::CORBA::Boolean AccessControlBuiltInImpl::get_datareader_sec_attributes(
    1233             :   ::DDS::Security::PermissionsHandle permissions_handle,
    1234             :   const char * topic_name,
    1235             :   const ::DDS::PartitionQosPolicy & partition,
    1236             :   const ::DDS::Security::DataTagQosPolicy & data_tag,
    1237             :   ::DDS::Security::EndpointSecurityAttributes & attributes,
    1238             :   ::DDS::Security::SecurityException & ex)
    1239             : {
    1240           1 :   if (DDS::HANDLE_NIL == permissions_handle) {
    1241           1 :     CommonUtilities::set_security_error(ex, -1, 0, "Invalid permissions handle");
    1242           1 :     return false;
    1243             :   }
    1244             : 
    1245           0 :   if (0 == topic_name) {
    1246           0 :     CommonUtilities::set_security_error(ex, -1, 0, "Invalid topic name");
    1247           0 :     return false;
    1248             :   }
    1249             : 
    1250           0 :   if (!get_sec_attributes(permissions_handle, topic_name, partition, data_tag, attributes, ex)) {
    1251           0 :     return false;
    1252             :   }
    1253             : 
    1254           0 :   return true;
    1255             : }
    1256             : 
    1257           1 : ::CORBA::Boolean AccessControlBuiltInImpl::return_participant_sec_attributes(
    1258             :   const ::DDS::Security::ParticipantSecurityAttributes & attributes,
    1259             :   ::DDS::Security::SecurityException & ex)
    1260             : {
    1261             :   ACE_UNUSED_ARG(attributes);
    1262             :   ACE_UNUSED_ARG(ex);
    1263             : 
    1264           1 :   return true;
    1265             : }
    1266             : 
    1267           1 : ::CORBA::Boolean AccessControlBuiltInImpl::return_datawriter_sec_attributes(
    1268             :   const ::DDS::Security::EndpointSecurityAttributes & attributes,
    1269             :   ::DDS::Security::SecurityException & ex)
    1270             : {
    1271             :   ACE_UNUSED_ARG(attributes);
    1272             :   ACE_UNUSED_ARG(ex);
    1273             : 
    1274           1 :   return true;
    1275             : }
    1276             : 
    1277           1 : ::CORBA::Boolean AccessControlBuiltInImpl::return_datareader_sec_attributes(
    1278             :   const ::DDS::Security::EndpointSecurityAttributes & attributes,
    1279             :   ::DDS::Security::SecurityException & ex)
    1280             : {
    1281             :   ACE_UNUSED_ARG(attributes);
    1282             :   ACE_UNUSED_ARG(ex);
    1283             : 
    1284           1 :   return true;
    1285             : }
    1286             : 
    1287          28 : ::CORBA::Long AccessControlBuiltInImpl::generate_handle()
    1288             : {
    1289          28 :   ACE_Guard<ACE_Thread_Mutex> guard(gen_handle_mutex_);
    1290          56 :   return CommonUtilities::increment_handle(next_handle_);
    1291          28 : }
    1292             : 
    1293             : AccessControlBuiltInImpl::RevokePermissionsTask_rch&
    1294           5 : AccessControlBuiltInImpl::make_task(RevokePermissionsTask_rch& task)
    1295             : {
    1296           5 :   if (!task) {
    1297           5 :     task = DCPS::make_rch<RevokePermissionsTask>(TheServiceParticipant->time_source(), TheServiceParticipant->interceptor(), DCPS::ref(*this));
    1298             :   }
    1299           5 :   return task;
    1300             : }
    1301             : 
    1302           6 : bool AccessControlBuiltInImpl::validate_date_time(
    1303             :   const Permissions::Validity_t& validity,
    1304             :   DDS::Security::SecurityException& ex)
    1305             : {
    1306           6 :   if (validity.not_before == 0) {
    1307           0 :     CommonUtilities::set_security_error(ex, -1, 0,
    1308             :       "AccessControlBuiltInImpl::validate_date_time: Permissions not_before time is invalid.");
    1309           0 :     return false;
    1310             :   }
    1311             : 
    1312           6 :   if (validity.not_after == 0) {
    1313           0 :     CommonUtilities::set_security_error(ex, -1, 0,
    1314             :       "AccessControlBuiltInImpl::validate_date_time: Permissions not_after time is invalid.");
    1315           0 :     return false;
    1316             :   }
    1317             : 
    1318             :   // Get the current time as UTC
    1319           6 :   const time_t now = std::time(0);
    1320           6 :   std::tm* const now_utc_tm = std::gmtime(&now);
    1321           6 :   const time_t now_utc = std::mktime(now_utc_tm);
    1322             : 
    1323           6 :   if (now_utc < validity.not_before) {
    1324           1 :     CommonUtilities::set_security_error(ex, -1, 0,
    1325             :       "AccessControlBuiltInImpl::validate_date_time: Permissions grant hasn't started yet.");
    1326           1 :     return false;
    1327             :   }
    1328             : 
    1329           5 :   if (now_utc > validity.not_after) {
    1330           0 :     CommonUtilities::set_security_error(ex, -1, 0,
    1331             :       "AccessControlBuiltInImpl::validate_date_time: Permissions grant has expired.");
    1332           0 :     return false;
    1333             :   }
    1334             : 
    1335           5 :   return true;
    1336             : }
    1337             : 
    1338           2 : CORBA::Boolean AccessControlBuiltInImpl::get_sec_attributes(::DDS::Security::PermissionsHandle permissions_handle,
    1339             :                                                             const char * topic_name,
    1340             :                                                             const::DDS::PartitionQosPolicy & /*partition*/,
    1341             :                                                             const::DDS::Security::DataTagQosPolicy & /*data_tag*/,
    1342             :                                                             ::DDS::Security::EndpointSecurityAttributes & attributes,
    1343             :                                                             ::DDS::Security::SecurityException & ex)
    1344             : {
    1345           2 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, false);
    1346             : 
    1347           2 :   const ACPermsMap::iterator ac_iter = local_ac_perms_.find(permissions_handle);
    1348           2 :   if (ac_iter == local_ac_perms_.end()) {
    1349           0 :     CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_datawriter_sec_attributes: No matching permissions handle present");
    1350           0 :     return false;
    1351             :   }
    1352             : 
    1353           2 :   const gov_iter begin = ac_iter->second.gov->access_rules().begin();
    1354           2 :   const gov_iter end = ac_iter->second.gov->access_rules().end();
    1355           2 :   for (gov_iter giter = begin; giter != end; ++giter) {
    1356           2 :     if (giter->domains.has(ac_iter->second.domain_id)) {
    1357           2 :       if (std::strcmp(topic_name, "DCPSParticipantVolatileMessageSecure") == 0) {
    1358           0 :         attributes.base.is_write_protected = false;
    1359           0 :         attributes.base.is_read_protected = false;
    1360           0 :         attributes.base.is_liveliness_protected = false;
    1361           0 :         attributes.base.is_discovery_protected = false;
    1362           0 :         attributes.is_submessage_protected = true;
    1363           0 :         attributes.is_payload_protected = false;
    1364           0 :         attributes.is_key_protected = false;
    1365           2 :         return true;
    1366             :       }
    1367             : 
    1368           2 :       if (std::strcmp(topic_name, "DCPSParticipantStatelessMessage") == 0) {
    1369           0 :         attributes.base.is_write_protected = false;
    1370           0 :         attributes.base.is_read_protected = false;
    1371           0 :         attributes.base.is_liveliness_protected = false;
    1372           0 :         attributes.base.is_discovery_protected = false;
    1373           0 :         attributes.is_submessage_protected = false;
    1374           0 :         attributes.is_payload_protected = false;
    1375           0 :         attributes.is_key_protected = false;
    1376           0 :         return true;
    1377             :       }
    1378             : 
    1379           2 :       if (std::strcmp(topic_name, "DCPSParticipantMessageSecure") == 0) {
    1380           0 :         attributes.base.is_write_protected = false;
    1381           0 :         attributes.base.is_read_protected = false;
    1382           0 :         attributes.base.is_liveliness_protected = false;
    1383           0 :         attributes.base.is_discovery_protected = false;
    1384           0 :         attributes.is_submessage_protected = giter->domain_attrs.is_liveliness_protected;
    1385           0 :         attributes.is_payload_protected = false;
    1386           0 :         attributes.is_key_protected = false;
    1387             : 
    1388           0 :         if (giter->domain_attrs.plugin_participant_attributes & ::DDS::Security::PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED) {
    1389           0 :           attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
    1390             :         }
    1391             : 
    1392           0 :         if (giter->domain_attrs.plugin_participant_attributes & ::DDS::Security::PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_ORIGIN_AUTHENTICATED) {
    1393           0 :           attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
    1394             :         }
    1395             : 
    1396           0 :         return true;
    1397             :       }
    1398             : 
    1399           2 :       if (std::strcmp(topic_name, "DCPSParticipantSecure") == 0 ||
    1400           2 :           std::strcmp(topic_name, "DCPSPublicationsSecure") == 0 ||
    1401           2 :           std::strcmp(topic_name, "DCPSSubscriptionsSecure") == 0 ||
    1402           2 :           std::strcmp(topic_name, "TypeLookupServiceRequestSecure") == 0 ||
    1403           2 :           std::strcmp(topic_name, "TypeLookupServiceReplySecure") == 0) {
    1404           0 :         attributes.base.is_write_protected = false;
    1405           0 :         attributes.base.is_read_protected = false;
    1406           0 :         attributes.base.is_liveliness_protected = false;
    1407           0 :         attributes.base.is_discovery_protected = false;
    1408           0 :         attributes.is_submessage_protected = giter->domain_attrs.is_discovery_protected;
    1409           0 :         attributes.is_payload_protected = false;
    1410           0 :         attributes.is_key_protected = false;
    1411             : 
    1412           0 :         if (giter->domain_attrs.plugin_participant_attributes & ::DDS::Security::PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_BUILTIN_IS_DISCOVERY_ENCRYPTED) {
    1413           0 :           attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
    1414             :         }
    1415             : 
    1416           0 :         if (giter->domain_attrs.plugin_participant_attributes & ::DDS::Security::PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_ORIGIN_AUTHENTICATED) {
    1417           0 :           attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
    1418             :         }
    1419             : 
    1420           0 :         return true;
    1421             :       }
    1422             : 
    1423           2 :       Governance::TopicAccessRules::iterator tr_iter;
    1424             : 
    1425           2 :       for (tr_iter = giter->topic_rules.begin(); tr_iter != giter->topic_rules.end(); ++tr_iter) {
    1426           2 :         if (pattern_match(topic_name, tr_iter->topic_expression.c_str())) {
    1427             : 
    1428             :           // Process the TopicSecurityAttributes base
    1429           2 :           attributes.base.is_write_protected = tr_iter->topic_attrs.is_write_protected;
    1430           2 :           attributes.base.is_read_protected = tr_iter->topic_attrs.is_read_protected;
    1431           2 :           attributes.base.is_liveliness_protected = tr_iter->topic_attrs.is_liveliness_protected;
    1432           2 :           attributes.base.is_discovery_protected = tr_iter->topic_attrs.is_discovery_protected;
    1433             : 
    1434             :           // Process metadata protection attributes
    1435           2 :           if (tr_iter->metadata_protection_kind == "NONE") {
    1436           2 :             attributes.is_submessage_protected = false;
    1437             :           }
    1438             :           else {
    1439           0 :             attributes.is_submessage_protected = true;
    1440             : 
    1441           0 :             if (tr_iter->metadata_protection_kind == "ENCRYPT" ||
    1442           0 :               tr_iter->metadata_protection_kind == "ENCRYPT_WITH_ORIGIN_AUTHENTICATION") {
    1443           0 :               attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
    1444             :             }
    1445             : 
    1446           0 :             if (tr_iter->metadata_protection_kind == "SIGN_WITH_ORIGIN_AUTHENTICATION" ||
    1447           0 :               tr_iter->metadata_protection_kind == "ENCRYPT_WITH_ORIGIN_AUTHENTICATION") {
    1448           0 :               attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
    1449             :             }
    1450             :           }
    1451             : 
    1452             :           // Process data protection attributes
    1453             : 
    1454           2 :           if (tr_iter->data_protection_kind == "NONE") {
    1455           2 :             attributes.is_payload_protected = false;
    1456           2 :             attributes.is_key_protected = false;
    1457             :           }
    1458           0 :           else if (tr_iter->data_protection_kind == "SIGN") {
    1459           0 :             attributes.is_payload_protected = true;
    1460           0 :             attributes.is_key_protected = false;
    1461             :           }
    1462           0 :           else if (tr_iter->data_protection_kind == "ENCRYPT") {
    1463           0 :             attributes.is_payload_protected = true;
    1464           0 :             attributes.is_key_protected = true;
    1465           0 :             attributes.plugin_endpoint_attributes |= ::DDS::Security::PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_PAYLOAD_ENCRYPTED;
    1466             :           }
    1467             : 
    1468           2 :           return true;
    1469             :         }
    1470             :       }
    1471             :     }
    1472             :   }
    1473             : 
    1474           0 :   CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl::get_sec_attributes: Invalid topic name");
    1475           0 :   return false;
    1476           2 : }
    1477             : 
    1478           5 : bool AccessControlBuiltInImpl::search_permissions(
    1479             :   const char* topic_name,
    1480             :   const DDS::Security::DomainId_t domain_id,
    1481             :   const DDS::PartitionQosPolicy& partition,
    1482             :   const Permissions::PublishSubscribe_t pub_or_sub,
    1483             :   const Permissions::Grant& grant,
    1484             :   DDS::Security::SecurityException& ex)
    1485             : {
    1486           5 :   for (Permissions::Rules::const_iterator rit = grant.rules.begin(); rit != grant.rules.end(); ++rit) {
    1487           5 :     if (rit->domains.has(domain_id)) {
    1488           8 :       for (Permissions::Actions::const_iterator ait = rit->actions.begin(); ait != rit->actions.end(); ++ait) {
    1489           8 :         if (ait->ps_type == pub_or_sub &&
    1490          13 :             ait->topic_matches(topic_name) &&
    1491           5 :             ait->partitions_match(partition.name, rit->ad_type)) {
    1492           5 :           if (rit->ad_type == Permissions::ALLOW) {
    1493           5 :             return true;
    1494             :           } else {
    1495           0 :             return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl: DENY rule matched");
    1496             :           }
    1497             :         }
    1498             :       }
    1499             :     }
    1500             :   }
    1501             : 
    1502           0 :   if (grant.default_permission == Permissions::ALLOW) {
    1503           0 :     return true;
    1504             :   } else {
    1505           0 :     return CommonUtilities::set_security_error(ex, -1, 0, "AccessControlBuiltInImpl: No matching rule for topic, default permission is DENY.");
    1506             :   }
    1507             : }
    1508             : 
    1509           4 : void AccessControlBuiltInImpl::parse_class_id(
    1510             :   const std::string& class_id,
    1511             :   std::string & plugin_class_name,
    1512             :   int & major_version,
    1513             :   int & minor_version)
    1514             : {
    1515           4 :   const std::string delimiter = ":";
    1516             : 
    1517           4 :   major_version = 1;
    1518           4 :   minor_version = 0;
    1519             : 
    1520           4 :   size_t pos = class_id.find_last_of(delimiter);
    1521             : 
    1522           4 :   if ((pos > 0UL) && (pos != class_id.length() - 1)) {
    1523           4 :     plugin_class_name = class_id.substr(0, (pos - 1));
    1524             : 
    1525           4 :     const std::string period = ".";
    1526             : 
    1527           4 :     size_t period_pos = class_id.find_last_of(period);
    1528             : 
    1529           4 :     if (period_pos > 0UL) {
    1530           4 :       std::string mv_string = class_id.substr((pos + 1), (period_pos - 1));
    1531             : 
    1532           4 :       major_version = atoi(mv_string.c_str());
    1533             : 
    1534           4 :       if (period_pos != class_id.length() - 1) {
    1535           4 :         mv_string = class_id.substr((period_pos + 1), (class_id.length() - 1));
    1536           4 :         minor_version = atoi(mv_string.c_str());
    1537             :       }
    1538           4 :     }
    1539           4 :   }
    1540             :   else {
    1541           0 :     plugin_class_name.clear();
    1542             :   }
    1543             : 
    1544           4 : }
    1545             : 
    1546           5 : AccessControlBuiltInImpl::RevokePermissionsTask::RevokePermissionsTask(const DCPS::TimeSource& time_source,
    1547             :                                                                        DCPS::ReactorInterceptor_rch interceptor,
    1548           5 :                                                                        AccessControlBuiltInImpl& impl)
    1549             :   : SporadicTask(time_source, interceptor)
    1550           5 :   , impl_(impl)
    1551           5 : { }
    1552             : 
    1553          10 : AccessControlBuiltInImpl::RevokePermissionsTask::~RevokePermissionsTask()
    1554             : {
    1555           5 :   if (DCPS::security_debug.bookkeeping) {
    1556           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1557             :                ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::~RevokePermissionsTask %@ handle_to_expiration_ %B expiration_to_handle_ %B\n"),
    1558             :                this,
    1559             :                handle_to_expiration_.size(),
    1560             :                expiration_to_handle_.size()));
    1561             :   }
    1562          10 : }
    1563             : 
    1564             : namespace {
    1565             :   // Some platforms cannot schedule timers far enough into the future
    1566             :   // to accommodate expiration times so the scheduling interval is
    1567             :   // capped at an hour.
    1568             :   const TimeDuration MAX_DURATION = TimeDuration(3600, 0);
    1569             : }
    1570             : 
    1571             : void
    1572           5 : AccessControlBuiltInImpl::RevokePermissionsTask::insert(::DDS::Security::PermissionsHandle pm_handle,
    1573             :                                                         const time_t& expiration)
    1574             : {
    1575           5 :   ACE_GUARD(ACE_Thread_Mutex, guard, lock_);
    1576             : 
    1577           5 :   if (handle_to_expiration_.count(pm_handle)) {
    1578           0 :     return;
    1579             :   }
    1580             : 
    1581           5 :   const time_t current_date_time = time(0);
    1582           5 :   tm* current_time_tm = gmtime(&current_date_time);
    1583           5 :   const time_t cur_utc_time = mktime(current_time_tm);
    1584           5 :   const TimeDuration duration = std::min(TimeDuration(expiration - cur_utc_time), MAX_DURATION);
    1585             : 
    1586           5 :   const bool empty_before = expiration_to_handle_.empty();
    1587             : 
    1588           5 :   handle_to_expiration_[pm_handle] = expiration;
    1589             : 
    1590           5 :   if (DCPS::security_debug.bookkeeping) {
    1591           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1592             :                ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::insert handle_to_expiration_ (total %B)\n"),
    1593             :                handle_to_expiration_.size()));
    1594             :   }
    1595             : 
    1596             :   ExpirationToHandle::const_iterator pos =
    1597           5 :     expiration_to_handle_.insert(ExpirationToHandle::value_type(expiration, pm_handle));
    1598             : 
    1599           5 :   if (DCPS::security_debug.bookkeeping) {
    1600           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1601             :                ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::insert expiration_to_handle_ (total %B)\n"),
    1602             :                expiration_to_handle_.size()));
    1603             :   }
    1604             : 
    1605           5 :   if (!empty_before && pos == expiration_to_handle_.begin()) {
    1606           0 :     cancel();
    1607             :   }
    1608             : 
    1609           5 :   if (pos == expiration_to_handle_.begin()) {
    1610           5 :     schedule(duration);
    1611             :   }
    1612           5 : }
    1613             : 
    1614             : void
    1615           0 : AccessControlBuiltInImpl::RevokePermissionsTask::erase(::DDS::Security::PermissionsHandle pm_handle)
    1616             : {
    1617           0 :   ACE_GUARD(ACE_Thread_Mutex, guard, lock_);
    1618             : 
    1619           0 :   HandleToExpiration::iterator iter = handle_to_expiration_.find(pm_handle);
    1620           0 :   if (iter == handle_to_expiration_.end()) {
    1621           0 :     return;
    1622             :   }
    1623             : 
    1624           0 :   const time_t expiration = iter->second;
    1625             : 
    1626             :   std::pair<ExpirationToHandle::iterator, ExpirationToHandle::iterator> er =
    1627           0 :     expiration_to_handle_.equal_range(expiration);
    1628           0 :   while (er.first != er.second) {
    1629           0 :     if (er.first->second == pm_handle) {
    1630           0 :       expiration_to_handle_.erase(er.first++);
    1631           0 :       if (DCPS::security_debug.bookkeeping) {
    1632           0 :         ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1633             :                    ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::erase expiration_to_handle_ (total %B)\n"),
    1634             :                    expiration_to_handle_.size()));
    1635             :       }
    1636             :     } else {
    1637           0 :       ++er.first;
    1638             :     }
    1639             :   }
    1640             : 
    1641           0 :   handle_to_expiration_.erase(pm_handle);
    1642           0 :   if (DCPS::security_debug.bookkeeping) {
    1643           0 :     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1644             :                ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::execute handle_to_expiration_ (total %B)\n"),
    1645             :                handle_to_expiration_.size()));
    1646             :   }
    1647           0 : }
    1648             : 
    1649             : void
    1650           0 : AccessControlBuiltInImpl::RevokePermissionsTask::execute(const DCPS::MonotonicTimePoint& /*now*/)
    1651             : {
    1652           0 :   ACE_GUARD(ACE_Thread_Mutex, guard, lock_);
    1653             : 
    1654           0 :   const time_t current_date_time = time(0);
    1655           0 :   tm* current_time_tm = gmtime(&current_date_time);
    1656           0 :   const time_t cur_utc_time = mktime(current_time_tm);
    1657             : 
    1658           0 :   for (ExpirationToHandle::iterator pos = expiration_to_handle_.begin(), limit = expiration_to_handle_.end();
    1659           0 :          pos != limit && pos->first < cur_utc_time;) {
    1660           0 :     const ::DDS::Security::PermissionsHandle pm_handle = pos->second;
    1661           0 :     ACPermsMap::iterator iter = impl_.local_ac_perms_.find(pm_handle);
    1662           0 :     if (iter == impl_.local_ac_perms_.end()) {
    1663           0 :       ACE_DEBUG((LM_ERROR, ACE_TEXT("(%P|%t) AccessControlBuiltInImpl::Revoke_Permissions_Timer::execute: ")
    1664             :                  ACE_TEXT("pm_handle %d not found!\n"), pm_handle));
    1665             :     }
    1666           0 :     impl_.local_ac_perms_.erase(iter);
    1667           0 :     if (DCPS::security_debug.bookkeeping) {
    1668           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1669             :                  ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::execute local_ac_perms_ (total %B)\n"),
    1670             :                  impl_.local_ac_perms_.size()));
    1671             :     }
    1672             : 
    1673             :     // If a listener exists, call on_revoke_permissions
    1674           0 :     if (impl_.listener_ptr_ && !impl_.listener_ptr_->on_revoke_permissions(&impl_, pm_handle)) {
    1675           0 :       ACE_DEBUG((LM_ERROR, ACE_TEXT("(%P|%t) AccessControlBuiltInImpl::Revoke_Permissions_Timer::execute: ")
    1676             :                  ACE_TEXT("on_revoke_permissions failed for pm_handle %d!\n"), pm_handle));
    1677             :     }
    1678             : 
    1679           0 :     if (OpenDDS::DCPS::DCPS_debug_level > 0) {
    1680           0 :       ACE_DEBUG((LM_DEBUG,
    1681             :                  ACE_TEXT("(%P|%t) AccessControlBuiltInImpl::Revoke_Permissions_Timer::execute: Completed...\n")));
    1682             :     }
    1683             : 
    1684           0 :     handle_to_expiration_.erase(pm_handle);
    1685           0 :     if (DCPS::security_debug.bookkeeping) {
    1686           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1687             :                  ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::execute handle_to_expiration_ (total %B)\n"),
    1688             :                  handle_to_expiration_.size()));
    1689             :     }
    1690             : 
    1691           0 :     expiration_to_handle_.erase(pos++);
    1692           0 :     if (DCPS::security_debug.bookkeeping) {
    1693           0 :       ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
    1694             :                  ACE_TEXT("AccessControlBuiltInImpl::RevokePermissionsTask::execute expiration_to_handle_ (total %B)\n"),
    1695             :                  expiration_to_handle_.size()));
    1696             :     }
    1697             :   }
    1698             : 
    1699           0 :   if (!expiration_to_handle_.empty()) {
    1700           0 :     const TimeDuration duration = std::min(TimeDuration(expiration_to_handle_.begin()->first - cur_utc_time), MAX_DURATION);
    1701           0 :     schedule(duration);
    1702           0 :   }
    1703           0 : }
    1704             : 
    1705             : SSL::SubjectName
    1706           0 : AccessControlBuiltInImpl::get_subject_name(DDS::Security::PermissionsHandle permissions_handle) const
    1707             : {
    1708           0 :   ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, handle_mutex_, SSL::SubjectName());
    1709             : 
    1710           0 :   ACPermsMap::const_iterator pos = local_ac_perms_.find(permissions_handle);
    1711           0 :   if (pos != local_ac_perms_.end()) {
    1712           0 :     return pos->second.subject;
    1713             :   }
    1714             : 
    1715           0 :   return SSL::SubjectName();
    1716           0 : }
    1717             : 
    1718             : } // namespace Security
    1719             : } // namespace OpenDDS
    1720             : 
    1721             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16