Skip to content

Commit 8b139a5

Browse files
committed
ishapes for security
1 parent f219861 commit 8b139a5

14 files changed

+1163
-25
lines changed

examples/DCPS/ishapes/main.cpp

Lines changed: 71 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,30 @@
2929
using namespace OpenDDS::RTPS;
3030
using namespace OpenDDS::DCPS;
3131

32+
// security setup helpers:
33+
34+
const char DDSSEC_PROP_IDENTITY_CA[] = "dds.sec.auth.identity_ca";
35+
const char DDSSEC_PROP_IDENTITY_CERT[] = "dds.sec.auth.identity_certificate";
36+
const char DDSSEC_PROP_IDENTITY_PRIVKEY[] = "dds.sec.auth.private_key";
37+
const char DDSSEC_PROP_PERM_CA[] = "dds.sec.access.permissions_ca";
38+
const char DDSSEC_PROP_PERM_GOV_DOC[] = "dds.sec.access.governance";
39+
const char DDSSEC_PROP_PERM_DOC[] = "dds.sec.access.permissions";
40+
41+
const char auth_ca_file[] = "file:security/TESTONLY_identity_ca_cert.pem";
42+
const char perm_ca_file[] = "file:security/TESTONLY_permissions_ca_cert.pem";
43+
const char id_cert_file[] =
44+
"file:security/TESTONLY_oci_opendds_dds_identity_cert.pem";
45+
const char id_key_file[] =
46+
"file:security/TESTONLY_oci_opendds_dds_identity_private_key.pem";
47+
48+
void append(DDS::PropertySeq& props, const char* name, const char* value)
49+
{
50+
const DDS::Property_t prop = {name, value, false /*propagate*/};
51+
const unsigned int len = props.length();
52+
props.length(len + 1);
53+
props[len] = prop;
54+
}
55+
3256
int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) {
3357
int retval = -1;
3458

@@ -51,7 +75,7 @@ int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) {
5175
DDS::DomainId_t domain = 0;
5276
bool multicast = true;
5377
unsigned int resend = 1;
54-
std::string partition;
78+
std::string partition, governance, permissions;
5579
int defaultSize = 0;
5680

5781
int curr = 1;
@@ -66,69 +90,88 @@ int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) {
6690
if (ACE_OS::strcmp(ACE_TEXT("-u"), argv[curr]) == 0) {
6791
multicast = false;
6892
std::cout << "SEDP unicast only" << std::endl;
69-
}
70-
else if ((ACE_OS::strcmp(ACE_TEXT("-r"), argv[curr]) == 0) && (curr + 1 < argc)) {
93+
} else if ((ACE_OS::strcmp(ACE_TEXT("-r"), argv[curr]) == 0) &&
94+
(curr + 1 < argc)) {
7195
resend = ACE_OS::atoi(argv[++curr]);
7296
std::cout << "Resend: " << resend << " sec" << std::endl;
73-
}
74-
else if ((ACE_OS::strcmp(ACE_TEXT("-pb"), argv[curr]) == 0) && (curr + 1 < argc)) {
97+
} else if ((ACE_OS::strcmp(ACE_TEXT("-pb"), argv[curr]) == 0) &&
98+
(curr + 1 < argc)) {
7599
const u_short temp = ACE_OS::atoi(argv[++curr]);
76100
std::cout << "pb: " << temp << std::endl;
77101
disc->pb(temp);
78-
}
79-
else if ((ACE_OS::strcmp(ACE_TEXT("-dg"), argv[curr]) == 0) && (curr + 1 < argc)) {
102+
} else if ((ACE_OS::strcmp(ACE_TEXT("-dg"), argv[curr]) == 0) &&
103+
(curr + 1 < argc)) {
80104
const u_short temp = ACE_OS::atoi(argv[++curr]);
81105
std::cout << "dg: " << temp << std::endl;
82106
disc->dg(temp);
83-
}
84-
else if ((ACE_OS::strcmp(ACE_TEXT("-pg"), argv[curr]) == 0) && (curr + 1 < argc)) {
107+
} else if ((ACE_OS::strcmp(ACE_TEXT("-pg"), argv[curr]) == 0) &&
108+
(curr + 1 < argc)) {
85109
const u_short temp = ACE_OS::atoi(argv[++curr]);
86110
std::cout << "pg: " << temp << std::endl;
87111
disc->pg(temp);
88-
}
89-
else if ((ACE_OS::strcmp(ACE_TEXT("-d0"), argv[curr]) == 0) && (curr + 1 < argc)) {
112+
} else if ((ACE_OS::strcmp(ACE_TEXT("-d0"), argv[curr]) == 0) &&
113+
(curr + 1 < argc)) {
90114
const u_short temp = ACE_OS::atoi(argv[++curr]);
91115
std::cout << "d0: " << temp << std::endl;
92116
disc->d0(temp);
93-
}
94-
else if ((ACE_OS::strcmp(ACE_TEXT("-d1"), argv[curr]) == 0) && (curr + 1 < argc)) {
117+
} else if ((ACE_OS::strcmp(ACE_TEXT("-d1"), argv[curr]) == 0) &&
118+
(curr + 1 < argc)) {
95119
const u_short temp = ACE_OS::atoi(argv[++curr]);
96120
std::cout << "d1: " << temp << std::endl;
97121
disc->d1(temp);
98-
}
99-
else if ((ACE_OS::strcmp(ACE_TEXT("-dx"), argv[curr]) == 0) && (curr + 1 < argc)) {
122+
} else if ((ACE_OS::strcmp(ACE_TEXT("-dx"), argv[curr]) == 0) &&
123+
(curr + 1 < argc)) {
100124
const u_short temp = ACE_OS::atoi(argv[++curr]);
101125
std::cout << "dx: " << temp << std::endl;
102126
disc->dx(temp);
103-
}
104-
else if ((ACE_OS::strcmp(ACE_TEXT("-partition"), argv[curr]) == 0) &&
105-
(curr + 1 < argc)) {
127+
} else if ((ACE_OS::strcmp(ACE_TEXT("-partition"), argv[curr]) == 0) &&
128+
(curr + 1 < argc)) {
106129
partition = ACE_TEXT_ALWAYS_CHAR(argv[++curr]);
107130
std::cout << "Partition[0]: " << partition << std::endl;
108-
}
109-
else if ((ACE_OS::strcmp(ACE_TEXT("-defaultSize"), argv[curr]) == 0) &&
110-
(curr + 1 < argc)) {
131+
} else if ((ACE_OS::strcmp(ACE_TEXT("-defaultSize"), argv[curr]) == 0) &&
132+
(curr + 1 < argc)) {
111133
defaultSize = ACE_OS::atoi(argv[++curr]);
112-
}
113-
else {
114-
std::cout << "Ignoring unknown param: " << ACE_TEXT_ALWAYS_CHAR(argv[curr]) << std::endl;
134+
} else if ((ACE_OS::strcmp(ACE_TEXT("-governance"), argv[curr]) == 0) &&
135+
(curr + 1 < argc)) {
136+
governance = argv[++curr];
137+
} else if ((ACE_OS::strcmp(ACE_TEXT("-permissions"), argv[curr]) == 0) &&
138+
(curr + 1 < argc)) {
139+
permissions = argv[++curr];
140+
} else {
141+
std::cout << "Ignoring unknown param: " <<
142+
ACE_TEXT_ALWAYS_CHAR(argv[curr]) << std::endl;
115143
}
116144
}
117145

118146
disc->resend_period(ACE_Time_Value(resend));
119147
disc->sedp_multicast(multicast);
120148
TheServiceParticipant->add_discovery(static_rchandle_cast<Discovery>(disc));
121149
TheServiceParticipant->set_repo_domain(domain, disc->key());
150+
DDS::DomainParticipantQos dp_qos;
151+
dpf->get_default_participant_qos(dp_qos);
152+
153+
if (!governance.empty() && !permissions.empty()) {
154+
TheServiceParticipant->set_security(true);
155+
DDS::PropertySeq& props = dp_qos.property.value;
156+
append(props, DDSSEC_PROP_IDENTITY_CA, auth_ca_file);
157+
append(props, DDSSEC_PROP_IDENTITY_CERT, id_cert_file);
158+
append(props, DDSSEC_PROP_IDENTITY_PRIVKEY, id_key_file);
159+
append(props, DDSSEC_PROP_PERM_CA, perm_ca_file);
160+
append(props, DDSSEC_PROP_PERM_GOV_DOC, ("file:" + governance).c_str());
161+
append(props, DDSSEC_PROP_PERM_DOC, ("file:" + permissions).c_str());
162+
}
122163

123164
// Create DomainParticipant
124165
DDS::DomainParticipant_var participant =
125166
dpf->create_participant(domain,
126-
PARTICIPANT_QOS_DEFAULT,
167+
dp_qos,
127168
0,
128169
DEFAULT_STATUS_MASK);
129170

130171
if (!participant) {
131172
std::cerr << "Could not connect to domain " << std::endl;
173+
TheServiceParticipant->shutdown();
174+
return EXIT_FAILURE;
132175
}
133176

134177
srand(clock());
@@ -137,6 +180,9 @@ int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) {
137180
Q_INIT_RESOURCE(ishape);
138181
// create and show your widgets here
139182
ShapesDialog shapes(participant, partition, defaultSize);
183+
if (TheServiceParticipant->get_security()) {
184+
shapes.setWindowTitle("OpenDDS Security BETA");
185+
}
140186
shapes.show();
141187
retval = app.exec();
142188

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
MIME-Version: 1.0
2+
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----0BB13B944CA22CF9D9DF1B3258DCB4E6"
3+
4+
This is an S/MIME signed message
5+
6+
------0BB13B944CA22CF9D9DF1B3258DCB4E6
7+
Content-Type: text/plain
8+
9+
<?xml version="1.0" encoding="UTF-8"?>
10+
11+
<!--
12+
Illustrates DDS Security is an extension of DDS. It is still possible to
13+
run applications without any protection.
14+
-->
15+
16+
<!--<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
17+
xsi:noNamespaceSchemaLocation="http://www.omg.org/spec/DDS-SECURITY/20160303/omg_shared_ca_governance.xsd">-->
18+
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:noNamespaceSchemaLocation="../schema/omg_shared_ca_governance.xsd">
20+
<domain_access_rules>
21+
<!-- Domain 0 is an "open domain" -->
22+
<domain_rule>
23+
<domains>
24+
<id>0</id>
25+
</domains>
26+
<allow_unauthenticated_participants>true</allow_unauthenticated_participants>
27+
<enable_join_access_control>false</enable_join_access_control>
28+
<discovery_protection_kind>NONE</discovery_protection_kind>
29+
<liveliness_protection_kind>NONE</liveliness_protection_kind>
30+
<rtps_protection_kind>NONE</rtps_protection_kind>
31+
32+
<topic_access_rules>
33+
<topic_rule>
34+
<topic_expression>*</topic_expression>
35+
<enable_discovery_protection>false</enable_discovery_protection>
36+
<enable_liveliness_protection>false</enable_liveliness_protection>
37+
<enable_read_access_control>false</enable_read_access_control>
38+
<enable_write_access_control>false</enable_write_access_control>
39+
<metadata_protection_kind>NONE</metadata_protection_kind>
40+
<data_protection_kind>NONE</data_protection_kind>
41+
</topic_rule>
42+
</topic_access_rules>
43+
</domain_rule>
44+
</domain_access_rules>
45+
</dds>
46+
47+
------0BB13B944CA22CF9D9DF1B3258DCB4E6
48+
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
49+
Content-Transfer-Encoding: base64
50+
Content-Disposition: attachment; filename="smime.p7s"
51+
52+
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
87+
88+
------0BB13B944CA22CF9D9DF1B3258DCB4E6--
89+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
MIME-Version: 1.0
2+
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----110ADAC04B1EC6CD679AF5C6B90FE150"
3+
4+
This is an S/MIME signed message
5+
6+
------110ADAC04B1EC6CD679AF5C6B90FE150
7+
Content-Type: text/plain
8+
9+
<?xml version="1.0" encoding="UTF-8"?>
10+
11+
<!--
12+
Illustrates DDS Security can be used to protect access to a DDS Domain.
13+
Only applications that can authenticate and have the proper permissions can
14+
join the Domain. Others cannot publish nor subscribe.
15+
-->
16+
17+
<!--<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18+
xsi:noNamespaceSchemaLocation="http://www.omg.org/spec/DDS-SECURITY/20160303/omg_shared_ca_governance.xsd">-->
19+
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:noNamespaceSchemaLocation="../schema/omg_shared_ca_governance.xsd">
21+
<domain_access_rules>
22+
<!--
23+
Domain 0 is a "protected domain." That is, only applications that
24+
can authenticate and have proper permissions can join it.
25+
-->
26+
<domain_rule>
27+
<domains>
28+
<id>0</id>
29+
</domains>
30+
<allow_unauthenticated_participants>false</allow_unauthenticated_participants>
31+
<enable_join_access_control>true</enable_join_access_control>
32+
<discovery_protection_kind>NONE</discovery_protection_kind>
33+
<liveliness_protection_kind>NONE</liveliness_protection_kind>
34+
<rtps_protection_kind>NONE</rtps_protection_kind>
35+
36+
<topic_access_rules>
37+
<topic_rule>
38+
<topic_expression>*</topic_expression>
39+
<enable_discovery_protection>false</enable_discovery_protection>
40+
<enable_liveliness_protection>false</enable_liveliness_protection>
41+
<enable_read_access_control>false</enable_read_access_control>
42+
<enable_write_access_control>false</enable_write_access_control>
43+
<metadata_protection_kind>NONE</metadata_protection_kind>
44+
<data_protection_kind>NONE</data_protection_kind>
45+
</topic_rule>
46+
</topic_access_rules>
47+
</domain_rule>
48+
</domain_access_rules>
49+
</dds>
50+
51+
------110ADAC04B1EC6CD679AF5C6B90FE150
52+
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
53+
Content-Transfer-Encoding: base64
54+
Content-Disposition: attachment; filename="smime.p7s"
55+
56+
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
91+
92+
------110ADAC04B1EC6CD679AF5C6B90FE150--
93+

0 commit comments

Comments
 (0)