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(¤t_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(¤t_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
|