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
|