LCOV - code coverage report
Current view: top level - DCPS/security/AccessControl - Governance.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 118 70.3 %
Date: 2023-04-30 01:32:43 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.OpenDDS.org/license.html
       4             :  */
       5             : 
       6             : #include "Governance.h"
       7             : 
       8             : #include "XmlUtils.h"
       9             : 
      10             : #include <dds/DCPS/debug.h>
      11             : 
      12             : #include <ace/OS_NS_strings.h>
      13             : #include <ace/XML_Utils/XercesString.h>
      14             : 
      15             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      16             : 
      17             : namespace OpenDDS {
      18             : namespace Security {
      19             : 
      20             : using XML::XStr;
      21             : using namespace XmlUtils;
      22             : using namespace DDS::Security;
      23             : using OpenDDS::DCPS::security_debug;
      24             : 
      25          36 : Governance::TopicAccessRule::TopicAccessRule()
      26             : {
      27          36 :   topic_attrs.is_read_protected = false;
      28          36 :   topic_attrs.is_write_protected = false;
      29          36 :   topic_attrs.is_discovery_protected = false;
      30          36 :   topic_attrs.is_liveliness_protected = false;
      31          36 : }
      32             : 
      33          22 : Governance::Governance()
      34             : {
      35          22 : }
      36             : 
      37             : namespace {
      38         188 :   bool get_bool_tag_value(const SSL::SignedDocument& doc, const xercesc::DOMNode* node,
      39             :     const ACE_TCHAR* name, bool& value)
      40             :   {
      41         188 :     if (!parse_bool(node, value)) {
      42           0 :       if (security_debug.access_error) {
      43           0 :         ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
      44             :           "\"%s\" value, \"%C\", in \"%C\" is not a valid boolean value\n",
      45             :           name, to_string(node).c_str(), doc.filename().c_str()));
      46             :       }
      47           0 :       return false;
      48             :     }
      49             : 
      50         188 :     return true;
      51             :   }
      52             : 
      53          44 :   bool get_bool_tag(const SSL::SignedDocument& doc, const xercesc::DOMElement* parent,
      54             :     const ACE_TCHAR* name, bool& value)
      55             :   {
      56          44 :     const xercesc::DOMNodeList* const nodes = parent->getElementsByTagName(XStr(name));
      57          44 :     if (nodes->getLength() != 1) {
      58           0 :       if (security_debug.access_error) {
      59           0 :         ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
      60             :           "expected 1 boolean value \"%s\" in parent element in \"%C\", found %B\n",
      61             :           name, doc.filename().c_str(), nodes->getLength()));
      62             :       }
      63           0 :       return false;
      64             :     }
      65             : 
      66          44 :     return get_bool_tag_value(doc, nodes->item(0), name, value);
      67             :   }
      68             : 
      69          66 :   bool get_protection_kind(const SSL::SignedDocument& doc, const xercesc::DOMElement* parent,
      70             :     const ACE_TCHAR* name, bool& is_protected, CORBA::ULong& attributes,
      71             :     CORBA::ULong enc_attr, CORBA::ULong oa_attr)
      72             :   {
      73          66 :     const xercesc::DOMNodeList* const nodes = parent->getElementsByTagName(XStr(name));
      74          66 :     if (nodes->getLength() != 1) {
      75           0 :       if (security_debug.access_error) {
      76           0 :         ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
      77             :           "expected 1 proctection kind value named \"%s\" in parent element in \"%C\", found %B\n",
      78             :           name, doc.filename().c_str(), nodes->getLength()));
      79             :       }
      80           0 :       return false;
      81             :     }
      82             : 
      83          66 :     const xercesc::DOMNode* const node = nodes->item(0);
      84          66 :     const std::string value = to_string(node);
      85          66 :     if (ACE_OS::strcasecmp(value.c_str(), "NONE") == 0) {
      86          59 :       is_protected = false;
      87           7 :     } else if (ACE_OS::strcasecmp(value.c_str(), "SIGN") == 0) {
      88           0 :       is_protected = true;
      89           7 :     } else if (ACE_OS::strcasecmp(value.c_str(), "ENCRYPT") == 0) {
      90           7 :       is_protected = true;
      91           7 :       attributes |= enc_attr;
      92           0 :     } else if (ACE_OS::strcasecmp(value.c_str(), "SIGN_WITH_ORIGIN_AUTHENTICATION") == 0) {
      93           0 :       is_protected = true;
      94           0 :       attributes |= oa_attr;
      95           0 :     } else if (ACE_OS::strcasecmp(value.c_str(), "ENCRYPT_WITH_ORIGIN_AUTHENTICATION") == 0) {
      96           0 :       is_protected = true;
      97           0 :       attributes |= enc_attr;
      98           0 :       attributes |= oa_attr;
      99             :     } else {
     100           0 :       if (security_debug.access_error) {
     101           0 :         ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
     102             :           "invalid %s, \"%C\", in \"%s\"\n",
     103             :           name, value.c_str(), doc.filename().c_str()));
     104             :       }
     105           0 :       return false;
     106             :     }
     107             : 
     108          66 :     return true;
     109          66 :   }
     110             : }
     111             : 
     112          22 : int Governance::load(const SSL::SignedDocument& doc)
     113             : {
     114          22 :   const std::string& xml = doc.content();
     115          22 :   ParserPtr parser;
     116          22 :   if (!get_parser(parser, doc.filename(), xml)) {
     117           0 :     if (security_debug.access_error) {
     118           0 :       ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
     119             :         "get_parser failed\n"));
     120             :     }
     121           0 :     return -1;
     122             :   }
     123             : 
     124             :   // Find the domain rules
     125          22 :   const xercesc::DOMNodeList* const domainRules = parser->getDocument()->getDocumentElement()->
     126          22 :     getElementsByTagName(XStr(ACE_TEXT("domain_rule")));
     127          44 :   for (XMLSize_t r = 0, dr_len = domainRules->getLength(); r < dr_len; ++r) {
     128          22 :     Governance::DomainRule domain_rule;
     129          22 :     domain_rule.domain_attrs.plugin_participant_attributes = 0;
     130             :     const xercesc::DOMElement* const domain_rule_el =
     131          22 :       dynamic_cast<const xercesc::DOMElement*>(domainRules->item(r));
     132          22 :     if (!domain_rule_el) {
     133           0 :       if (security_debug.access_error) {
     134           0 :         ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
     135             :           "domain_rule_el is null\n"));
     136             :       }
     137           0 :       return -1;
     138             :     }
     139             : 
     140             :     // Process domain ids this domain rule applies to
     141          22 :     const xercesc::DOMNodeList* const ruleNodes = domain_rule_el->getChildNodes();
     142         352 :     for (XMLSize_t rn = 0, rn_len = ruleNodes->getLength(); rn < rn_len; rn++) {
     143         330 :       const xercesc::DOMNode* const ruleNode = ruleNodes->item(rn);
     144         330 :       const XStr dn_tag = ruleNode->getNodeName();
     145         330 :       if (ACE_TEXT("domains") == dn_tag) {
     146          22 :         if (!parse_domain_id_set(ruleNode, domain_rule.domains)) {
     147           0 :           if (security_debug.access_error) {
     148           0 :             ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} Governance::load: "
     149             :               "failed to process domain ids in \"%C\"\n",
     150             :               doc.filename().c_str()));
     151             :           }
     152           0 :           return -1;
     153             :         }
     154             :       }
     155         330 :     }
     156             : 
     157             :     // Process allow_unauthenticated_participants
     158          22 :     if (!get_bool_tag(doc, domain_rule_el, ACE_TEXT("allow_unauthenticated_participants"),
     159             :         domain_rule.domain_attrs.allow_unauthenticated_participants)) {
     160           0 :       return -1;
     161             :     }
     162             : 
     163             :     // Process enable_join_access_control
     164          22 :     if (!get_bool_tag(doc, domain_rule_el, ACE_TEXT("enable_join_access_control"),
     165             :         domain_rule.domain_attrs.is_access_protected)) {
     166           0 :       return -1;
     167             :     }
     168             : 
     169             :     // Process discovery_protection_kind
     170          22 :     if (!get_protection_kind(doc, domain_rule_el, ACE_TEXT("discovery_protection_kind"),
     171             :         domain_rule.domain_attrs.is_discovery_protected,
     172             :         domain_rule.domain_attrs.plugin_participant_attributes,
     173             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_BUILTIN_IS_DISCOVERY_ENCRYPTED,
     174             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_ORIGIN_AUTHENTICATED)) {
     175           0 :       return -1;
     176             :     }
     177             : 
     178             :     // Process liveliness_protection_kind
     179          22 :     if (!get_protection_kind(doc, domain_rule_el, ACE_TEXT("liveliness_protection_kind"),
     180             :         domain_rule.domain_attrs.is_liveliness_protected,
     181             :         domain_rule.domain_attrs.plugin_participant_attributes,
     182             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED,
     183             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_ORIGIN_AUTHENTICATED)) {
     184           0 :       return -1;
     185             :     }
     186             : 
     187             :     // Process rtps_protection_kind
     188          22 :     if (!get_protection_kind(doc, domain_rule_el, ACE_TEXT("rtps_protection_kind"),
     189             :         domain_rule.domain_attrs.is_rtps_protected,
     190             :         domain_rule.domain_attrs.plugin_participant_attributes,
     191             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED,
     192             :         PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_ORIGIN_AUTHENTICATED)) {
     193           0 :       return -1;
     194             :     }
     195             : 
     196          22 :     domain_rule.domain_attrs.plugin_participant_attributes |=
     197             :       PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
     198             : 
     199             :     // Process topic rules
     200             :     const xercesc::DOMNodeList* topic_rules =
     201          22 :       domain_rule_el->getElementsByTagName(XStr(ACE_TEXT("topic_rule")));
     202          58 :     for (XMLSize_t tr = 0, tr_len = topic_rules->getLength(); tr < tr_len; tr++) {
     203          36 :       const xercesc::DOMNode* topic_rule = topic_rules->item(tr);
     204          36 :       const xercesc::DOMNodeList* topic_rule_nodes = topic_rule->getChildNodes();
     205          36 :       Governance::TopicAccessRule t_rules;
     206         576 :       for (XMLSize_t trn = 0, trn_len = topic_rule_nodes->getLength(); trn < trn_len; trn++) {
     207         540 :         const xercesc::DOMNode* topic_rule_node = topic_rule_nodes->item(trn);
     208         540 :         const std::string name = to_string(topic_rule_node->getNodeName());
     209             : 
     210         540 :         bool* bool_value = 0;
     211         540 :         if (name == "topic_expression") {
     212          36 :           t_rules.topic_expression = to_string(topic_rule_node);
     213         504 :         } else if (name == "enable_discovery_protection") {
     214          36 :           bool_value = &t_rules.topic_attrs.is_discovery_protected;
     215         468 :         } else if (name == "enable_liveliness_protection") {
     216          36 :           bool_value = &t_rules.topic_attrs.is_liveliness_protected;
     217         432 :         } else if (name == "enable_read_access_control") {
     218          36 :           bool_value = &t_rules.topic_attrs.is_read_protected;
     219         396 :         } else if (name == "enable_write_access_control") {
     220          36 :           bool_value = &t_rules.topic_attrs.is_write_protected;
     221         360 :         } else if (name == "metadata_protection_kind") {
     222          36 :           t_rules.metadata_protection_kind = to_string(topic_rule_node);
     223         324 :         } else if (name == "data_protection_kind") {
     224          36 :           t_rules.data_protection_kind = to_string(topic_rule_node);
     225             :         }
     226             : 
     227         540 :         if (bool_value && !get_bool_tag_value(doc, topic_rule_node,
     228             :             ACE_TEXT_CHAR_TO_TCHAR(name.c_str()), *bool_value)) {
     229           0 :           return -1;
     230             :         }
     231         540 :       }
     232          36 :       domain_rule.topic_rules.push_back(t_rules);
     233          36 :     }
     234             : 
     235          22 :     access_rules_.push_back(domain_rule);
     236          22 :   } // domain_rule
     237             : 
     238          22 :   return 0;
     239          22 : }
     240             : 
     241             : 
     242             : }
     243             : }
     244             : 
     245             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16