OpenDDS  Snapshot(2023/04/28-20:55)
AuthenticationBuiltInImpl.cpp
Go to the documentation of this file.
1 /*
2 *
3 *
4 * Distributed under the OpenDDS License.
5 * See: http://www.opendds.org/license.html
6 */
7 
9 
10 #include "CommonUtilities.h"
11 #include "TokenReader.h"
12 #include "TokenWriter.h"
13 #include "SSL/Utils.h"
14 
15 #include "dds/DCPS/GuidUtils.h"
16 #include "dds/DCPS/LocalObject.h"
17 #include "dds/DCPS/Serializer.h"
18 
19 #include "dds/DCPS/RTPS/RtpsCoreC.h"
20 #include "dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.h"
21 
22 #include "ace/config-macros.h"
23 #include "ace/Guard_T.h"
24 
25 #include <sstream>
26 #include <vector>
27 #include <algorithm>
28 #include <cstdio>
29 
31 
32 namespace OpenDDS {
33 namespace Security {
34 
36 
37 static bool challenges_match(const DDS::OctetSeq& c1, const DDS::OctetSeq& c2);
38 
39 static void extract_participant_guid_from_cpdata(const DDS::OctetSeq& cpdata, DCPS::GUID_t& dst);
40 
41 static bool validate_topic_data_guid(const DDS::OctetSeq& cpdata,
42  const std::vector<unsigned char>& subject_name_hash,
44 
45 const std::string Auth_Plugin_Name("DDS:Auth:PKI-DH");
46 const std::string Auth_Plugin_Major_Version("1");
47 const std::string Auth_Plugin_Minor_Version("0");
48 
49 const std::string Auth_Request_Class_Ext("AuthReq");
50 const std::string Handshake_Request_Class_Ext("Req");
51 const std::string Handshake_Reply_Class_Ext("Reply");
52 const std::string Handshake_Final_Class_Ext("Final");
53 
54 const char* AuthenticationBuiltInImpl::PROPERTY_HANDSHAKE_DEBUG = "opendds.sec.auth.handshake_debug";
55 
56 struct SharedSecret : DCPS::LocalObject<DDS::Security::SharedSecretHandle> {
57 
61  : challenge1_(challenge1)
62  , challenge2_(challenge2)
63  , shared_secret_(sharedSecret)
64  {}
65 
69 
71 };
72 
74 : listener_ptr_()
75 , identity_mutex_()
76 , handshake_mutex_()
77 , handle_mutex_()
78 , next_handle_(1)
79 {
80 }
81 
83 {
84  if (DCPS::security_debug.bookkeeping) {
85  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
86  ACE_TEXT("AuthenticationBuiltInImpl::~AuthenticationBuiltInImpl local_participants_ %B handshake_data_ %B\n"),
87  local_participants_.size(),
88  handshake_data_.size()));
89  }
90 }
91 
93  ::DDS::Security::IdentityHandle & local_identity_handle,
94  ::OpenDDS::DCPS::GUID_t & adjusted_participant_guid,
95  ::DDS::Security::DomainId_t /*domain_id*/,
96  const ::DDS::DomainParticipantQos & participant_qos,
97  const ::OpenDDS::DCPS::GUID_t & candidate_participant_guid,
99 {
101 
102  LocalAuthCredentialData::shared_ptr credentials = DCPS::make_rch<LocalAuthCredentialData>();
103  if (!credentials->load_credentials(participant_qos.property.value, ex)) {
104  return result;
105  }
106 
107  if (credentials->validate()) {
108  if (candidate_participant_guid != DCPS::GUID_UNKNOWN) {
109 
110  int err = SSL::make_adjusted_guid(candidate_participant_guid,
111  adjusted_participant_guid,
112  credentials->get_participant_cert());
113  if (!err) {
114  local_identity_handle = get_next_handle();
115 
116  LocalParticipantData::shared_ptr local_participant = DCPS::make_rch<LocalParticipantData>();
117  local_participant->participant_guid = adjusted_participant_guid;
118  local_participant->credentials = credentials;
119  for (unsigned i = 0; i < participant_qos.property.value.length(); ++i) {
120  if (std::strcmp(PROPERTY_HANDSHAKE_DEBUG,
121  participant_qos.property.value[i].name.in()) == 0) {
122  local_participant->handshake_debug = true;
123  }
124  }
125 
126  {
127  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
128  local_participants_[local_identity_handle] = local_participant;
129 
130  if (DCPS::security_debug.bookkeeping) {
131  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
132  ACE_TEXT("AuthenticationBuiltInImpl::validate_local_identity local_participants_ (total %B)\n"),
133  local_participants_.size()));
134  }
135  }
136 
138 
139  } else {
140  set_security_error(ex, -1, 0, "SSL::make_adjusted_guid failed");
141  }
142 
143  } else {
144  set_security_error(ex, -1, 0, "GUID_UNKNOWN passed in for candidate_participant_guid");
145  }
146 
147  } else {
148  set_security_error(ex, -1, 0, "local-credential-data failed validation");
149  }
150 
151  return result;
152 }
153 
155  ::DDS::Security::IdentityToken & identity_token,
158 {
159  ::CORBA::Boolean status = false;
160 
161  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
162 
164  if (local_data) {
165  const LocalAuthCredentialData& local_credential_data = *(local_data->credentials);
166 
167  const SSL::Certificate& pcert = local_credential_data.get_participant_cert();
168  const SSL::Certificate& cacert = local_credential_data.get_ca_cert();
169 
170  std::string tmp;
171 
172  OpenDDS::Security::TokenWriter identity_wrapper(identity_token, Identity_Status_Token_Class_Id);
173 
174  pcert.subject_name_to_str(tmp);
175  identity_wrapper.add_property(dds_cert_sn, tmp.c_str());
176  identity_wrapper.add_property(dds_cert_algo, pcert.keypair_algo());
177 
178  cacert.subject_name_to_str(tmp);
179  identity_wrapper.add_property(dds_ca_sn, tmp.c_str());
180  identity_wrapper.add_property(dds_ca_algo, cacert.keypair_algo());
181 
182  status = true;
183 
184  } else {
185  set_security_error(ex, -1, 0, "Unknown Identity handle");
186  }
187  return status;
188 }
189 
194 {
195  ::CORBA::Boolean status = false;
196 
197  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
198 
199  // Populate a simple version of an IdentityStatusToken as long as the handle is known
201  if (local_data) {
202 
203  // TODO: Pending AuthenticationListener support (see security spec. 8.3.2.2).
204  // This routine will most likely populate the IdentityStatusToken with
205  // useful data once this has been completed. For now it's a glorified no-op!
206 
207  status = true;
208  } else {
209  set_security_error(ex, -1, 0, "Unknown Identity handle");
210  }
211 
212  return status;
213 }
214 
217  const ::DDS::Security::PermissionsCredentialToken & permissions_credential,
218  const ::DDS::Security::PermissionsToken & permissions_token,
220 {
221  ACE_UNUSED_ARG(permissions_token);
222 
223  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
224 
226  if (! local_data) {
227  set_security_error(ex, -1, 0, "Identity handle not recognized");
228  return false;
229  }
230 
231  return local_data->credentials->load_access_permissions(permissions_credential, ex);
232 }
233 
235  ::DDS::Security::IdentityHandle & remote_identity_handle,
236  ::DDS::Security::AuthRequestMessageToken & local_auth_request_token,
237  const ::DDS::Security::AuthRequestMessageToken & remote_auth_request_token,
238  ::DDS::Security::IdentityHandle local_identity_handle,
239  const ::DDS::Security::IdentityToken & remote_identity_token,
240  const ::OpenDDS::DCPS::GUID_t & remote_participant_guid,
242 {
243  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
244 
245  LocalParticipantData::shared_ptr local_data = get_local_participant(local_identity_handle);
246 
247  if (!local_data) {
248  set_security_error(ex, -1, 0, "Local participant ID not found");
250  }
251 
252  if (!check_class_versions(remote_identity_token.class_id)) {
253  set_security_error(ex, -1, 0, "Remote class ID is not compatible");
255  }
256 
257  // Make sure that a remote_participant_guid has not already been assigned a
258  // remote-identity-handle before creating a new one.
259  RemoteParticipantMap::iterator begin = local_data->validated_remotes.begin(),
260  end = local_data->validated_remotes.end(),
261  found = std::find_if(begin, end,
262  was_guid_validated(remote_participant_guid));
263 
264  if (found == end) {
265  // Generate local token.
266  DDS::OctetSeq nonce;
267  int err = SSL::make_nonce_256(nonce);
268  if (err) {
269  set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for future_challenge property");
271  }
272 
273  TokenWriter auth_req_wrapper(local_auth_request_token, build_class_id(Auth_Request_Class_Ext));
274  auth_req_wrapper.add_bin_property("future_challenge", nonce);
275 
276  // Retain all of the data needed for a handshake with the remote participant
277  RemoteParticipantData::shared_ptr remote_participant = DCPS::make_rch<RemoteParticipantData>();
278  remote_participant->participant_guid = remote_participant_guid;
279  remote_participant->local_participant = local_identity_handle;
280  remote_participant->local_auth_request = local_auth_request_token;
281 
282  remote_identity_handle = get_next_handle();
283  found = local_data->validated_remotes.insert(std::make_pair(remote_identity_handle, remote_participant)).first;
284 
285  if (DCPS::security_debug.bookkeeping) {
286  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
287  ACE_TEXT("AuthenticationBuiltInImpl::validate_remote_identity validated_remotes (total %B)\n"),
288  local_data->validated_remotes.size()));
289  }
290  }
291 
292  // Update the remote token.
293  found->second->remote_auth_request = remote_auth_request_token;
294 
295  // Set return values.
296  remote_identity_handle = found->first;
297 
298  // Don't need to send the local token if we have a remote token.
299  TokenReader remote_request(remote_auth_request_token);
300  if (remote_request.is_nil()) {
301  local_auth_request_token = found->second->local_auth_request;
302  } else {
303  local_auth_request_token = DDS::Security::Token();
304  }
305 
306  if (is_handshake_initiator(local_data->participant_guid, remote_participant_guid)) {
308  } else {
310  }
311 }
312 
314  ::DDS::Security::HandshakeHandle & handshake_handle,
315  ::DDS::Security::HandshakeMessageToken & handshake_message,
316  ::DDS::Security::IdentityHandle initiator_identity_handle,
317  ::DDS::Security::IdentityHandle replier_identity_handle,
318  const ::DDS::OctetSeq & serialized_local_participant_data,
320 {
321  if (serialized_local_participant_data.length() == 0) {
322  set_security_error(ex, -1, 0, "No participant data provided");
324  }
325 
326  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
327 
328  HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
329 
330  if (! handshake_data.first) {
331  set_security_error(ex, -1, 0, "Unknown local participant");
333  }
334 
335  if (! handshake_data.second) {
336  set_security_error(ex, -1, 0, "Unknown remote participant");
338  }
339 
340  const LocalParticipantData& local_data = *handshake_data.first;
341  RemoteParticipantData& remote_data = *handshake_data.second;
342 
343  const LocalAuthCredentialData& local_credential_data = *local_data.credentials;
344 
346 
348 
349  // Compute hash_c1 and store for later
350 
351  DDS::OctetSeq hash_c1;
352 
353  {
354  CredentialHash hash(local_credential_data.get_participant_cert(),
355  *diffie_hellman,
356  serialized_local_participant_data,
357  local_credential_data.get_access_permissions());
358 
359  int err = hash(hash_c1);
360  if (err) {
361  set_security_error(ex, -1, 0, "Failed to generate credential-hash 'hash_c1'");
363  }
364  }
365 
366  message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
367  message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
368  message_out.add_bin_property("c.pdata", serialized_local_participant_data);
369  message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
370  message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
371  if (local_data.handshake_debug) {
372  message_out.add_bin_property("hash_c1", hash_c1);
373  }
374 
375  DDS::OctetSeq dhpub;
376  diffie_hellman->pub_key(dhpub);
377  message_out.add_bin_property("dh1", dhpub);
378 
379  OpenDDS::Security::TokenReader auth_wrapper(remote_data.local_auth_request);
380  if (auth_wrapper.is_nil()) {
381  DDS::OctetSeq nonce;
382  int err = SSL::make_nonce_256(nonce);
383  if (! err) {
384  message_out.add_bin_property("challenge1", nonce);
385 
386  } else {
387  set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for challenge1 property");
389  }
390 
391  } else {
392  const DDS::OctetSeq& challenge_data = auth_wrapper.get_bin_property_value("future_challenge");
393  message_out.add_bin_property("challenge1", challenge_data);
394  }
395 
396  remote_data.initiator_identity = initiator_identity_handle;
397  remote_data.replier_identity = replier_identity_handle;
399  remote_data.request = handshake_message;
400  remote_data.reply = DDS::Security::Token();
401  remote_data.diffie_hellman = DCPS::move(diffie_hellman);
402  remote_data.hash_c1 = hash_c1;
403 
404  if (handshake_handle == DDS::HANDLE_NIL) {
405  handshake_handle = get_next_handle();
406  }
407 
408  {
409  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(handshake_mutex_);
410  handshake_data_[handshake_handle] = handshake_data;
411 
412  if (DCPS::security_debug.bookkeeping) {
413  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
414  ACE_TEXT("AuthenticationBuiltInImpl::begin_handshake_request handshake_data_ (total %B)\n"),
415  handshake_data_.size()));
416  }
417  }
418 
420 }
421 
423 {
424  dst = DCPS::GUID_UNKNOWN;
425 
426  ACE_Message_Block buffer(reinterpret_cast<const char*>(cpdata.get_buffer()), cpdata.length());
427  buffer.wr_ptr(cpdata.length());
428  OpenDDS::DCPS::Serializer serializer(&buffer,
431  RTPS::ParameterList params;
432 
433  if (serializer >> params) {
434  for (unsigned int i = 0; i < params.length(); ++i) {
435  const RTPS::Parameter& p = params[i];
436 
437  if (p._d() == RTPS::PID_PARTICIPANT_GUID) {
438  dst = p.guid();
439  break;
440  }
441  }
442 
443  } else {
445  ACE_TEXT("(%P|%t) WARNING: extract_participant_guid_from_cpdata, ")
446  ACE_TEXT("failed to deserialize guid from cpdata.\n")));
447  }
448 
449 }
450 
452  const std::vector<unsigned char>& subject_name_hash,
454 {
455  if (cpdata.length() > 5u) { /* Enough to withstand the hash-comparison below */
456 
457  DCPS::GUID_t remote_participant_guid;
458  extract_participant_guid_from_cpdata(cpdata, remote_participant_guid);
459 
460  const DCPS::GuidPrefix_t& prefix = remote_participant_guid.guidPrefix;
461 
462  /* Make sure first bit is set */
463 
464  if ((prefix[0] & 0x80) != 0x80) {
465  set_security_error(ex, -1, 0, "Malformed participant_guid in 'c.pdata'; First bit must be set.");
466  return false;
467  }
468 
469  /* Check the following 47 bits match the subject-hash */
470 
471  /* First byte needs to remove the manually-set first-bit before comparison */
472  if ((prefix[0] & 0x7F) != SSL::offset_1bit(&subject_name_hash[0], 0)) {
473  set_security_error(ex, -1, 0, "First byte of participant_guid in 'c.pdata' does not match bits of subject-name hash in 'c.id'");
474  return false;
475  }
476  for (size_t i = 1; i <= 5u; ++i) { /* Compare remaining 5 bytes */
477  if (prefix[i] != SSL::offset_1bit(&subject_name_hash[0], i)) { /* Slide the hash to the right 1 so it aligns with the guid prefix */
478  set_security_error(ex, -1, 0, "Bits 2 - 48 of 'c.pdata' participant_guid does not match first 47 bits of subject-name hash in 'c.id'");
479  return false;
480  }
481  }
482 
483  } else {
484  set_security_error(ex, -1, 0, "Data missing in 'c.pdata'");
485  return false;
486  }
487 
488  return true;
489 }
490 
491 static void make_reply_signature_sequence(const DDS::OctetSeq& hash_c2,
492  const DDS::OctetSeq& challenge2,
493  const DDS::OctetSeq& dh2,
494  const DDS::OctetSeq& challenge1,
495  const DDS::OctetSeq& dh1,
496  const DDS::OctetSeq& hash_c1,
498 {
500 
501  {
503  p.name = "hash_c2";
504  p.value = hash_c2;
505  p.propagate = true;
506  *inserter = p;
507  }
508 
509  {
511  p.name = "challenge2";
512  p.value = challenge2;
513  p.propagate = true;
514  *inserter = p;
515  }
516 
517  {
519  p.name = "dh2";
520  p.value = dh2;
521  p.propagate = true;
522  *inserter = p;
523  }
524 
525  {
527  p.name = "challenge1";
528  p.value = challenge1;
529  p.propagate = true;
530  *inserter = p;
531  }
532 
533  {
535  p.name = "dh1";
536  p.value = dh1;
537  p.propagate = true;
538  *inserter = p;
539  }
540 
541  {
543  p.name = "hash_c1";
544  p.value = hash_c1;
545  p.propagate = true;
546  *inserter = p;
547  }
548 }
549 
550 static void make_final_signature_sequence(const DDS::OctetSeq& hash_c1,
551  const DDS::OctetSeq& challenge1,
552  const DDS::OctetSeq& dh1,
553  const DDS::OctetSeq& challenge2,
554  const DDS::OctetSeq& dh2,
555  const DDS::OctetSeq& hash_c2,
557 {
559 
560  {
562  p.name = "hash_c1";
563  p.value = hash_c1;
564  p.propagate = true;
565  *inserter = p;
566  }
567 
568  {
570  p.name = "challenge1";
571  p.value = challenge1;
572  p.propagate = true;
573  *inserter = p;
574  }
575 
576  {
578  p.name = "dh1";
579  p.value = dh1;
580  p.propagate = true;
581  *inserter = p;
582  }
583 
584  {
586  p.name = "challenge2";
587  p.value = challenge2;
588  p.propagate = true;
589  *inserter = p;
590  }
591 
592  {
594  p.name = "dh2";
595  p.value = dh2;
596  p.propagate = true;
597  *inserter = p;
598  }
599 
600  {
602  p.name = "hash_c2";
603  p.value = hash_c2;
604  p.propagate = true;
605  *inserter = p;
606  }
607 }
608 
610  ::DDS::Security::HandshakeHandle & handshake_handle,
611  ::DDS::Security::HandshakeMessageToken & handshake_message_out,
612  ::DDS::Security::IdentityHandle initiator_identity_handle,
613  ::DDS::Security::IdentityHandle replier_identity_handle,
614  const ::DDS::OctetSeq & serialized_local_participant_data,
616 {
619 
620  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
621 
622  // Copy the "in" part of the inout param
623  const DDS::Security::HandshakeMessageToken request_token = handshake_message_out;
624  handshake_message_out = DDS::Security::HandshakeMessageToken();
625 
626  DDS::OctetSeq challenge1, challenge2, dh2, cperm, hash_c1, hash_c2;
627 
629  SSL::DiffieHellman::unique_ptr diffie_hellman;
630 
633 
634  if (serialized_local_participant_data.length() == 0) {
635  set_security_error(ex, -1, 0, "No participant data provided");
636  return Failure;
637  }
638 
639  HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
640 
641  if (! handshake_data.first) {
642  set_security_error(ex, -1, 0, "Unknown local participant");
643  return Failure;
644  }
645 
646  if (! handshake_data.second) {
647  set_security_error(ex, -1, 0, "Unknown remote participant");
648  return Failure;
649  }
650 
651  const LocalParticipantData& local_data = *handshake_data.first;
652  RemoteParticipantData& remote_data = *handshake_data.second;
653 
654  DDS::Security::HandshakeMessageToken message_data_in(request_token);
655  TokenReader message_in(message_data_in);
656  if (message_in.is_nil()) {
657  set_security_error(ex, -1, 0, "Handshake_message_out is an inout param and must not be nil");
658  return Failure;
659 
660  }
661  challenge1 = message_in.get_bin_property_value("challenge1");
662 
663  TokenReader initiator_remote_auth_request(remote_data.remote_auth_request);
664  if (! initiator_remote_auth_request.is_nil()) {
665  const DDS::OctetSeq& future_challenge = initiator_remote_auth_request.get_bin_property_value("future_challenge");
666 
667  if (! challenges_match(challenge1, future_challenge)) {
668  return Failure;
669  }
670  }
671 
672  const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
673 
674  const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
675  if (cid.length() > 0) {
676 
677  remote_cert->deserialize(cid);
678  if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
679  {
680  set_security_error(ex, -1, 0, "Certificate validation failed");
681  return Failure;
682  }
683 
684  } else {
685  set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
686  return Failure;
687  }
688 
689  /* Validate participant_guid in c.pdata */
690 
691  const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
692 
693  std::vector<unsigned char> hash;
694  if (0 != remote_cert->subject_name_digest(hash)) {
695  set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
696  return Failure;
697  }
698 
699  if (! validate_topic_data_guid(cpdata, hash, ex)) {
700  return Failure;
701  }
702 
703  cperm = message_in.get_bin_property_value("c.perm");
704 
705  const DDS::OctetSeq& dh_algo = message_in.get_bin_property_value("c.kagree_algo");
706  diffie_hellman.reset(SSL::DiffieHellman::factory(dh_algo));
707 
708  /* Compute hash_c1 and store for later */
709 
710  {
711  CredentialHash hash(*remote_cert,
712  *diffie_hellman,
713  cpdata,
714  cperm);
715  int err = hash(hash_c1);
716  if (err) {
717  set_security_error(ex, -1, 0, "Failed to compute hash_c1.");
718  return Failure;
719  }
720  }
721 
722  /* Compute hash_c2 and store for later */
723 
724  {
725  CredentialHash hash(local_credential_data.get_participant_cert(),
726  *diffie_hellman,
727  serialized_local_participant_data,
728  local_credential_data.get_access_permissions());
729  int err = hash(hash_c2);
730  if (err) {
731  set_security_error(ex, -1, 0, "Failed to compute hash_c2.");
732  return Failure;
733  }
734  }
735 
736  // TODO: Currently support for OCSP is optional in the security spec and
737  // so it has been deferred to a post-beta release.
738  // Add OCSP checks when "ocsp_status" property is given in message_in.
739  // Most of this logic would probably be placed in the Certificate directly
740  // or an OCSP abstraction that the Certificate uses.
741 
742  const DDS::OctetSeq& dh1 = message_in.get_bin_property_value("dh1");
743 
744  TokenWriter message_out(handshake_message_out, build_class_id(Handshake_Reply_Class_Ext));
745 
746  message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
747  message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
748  message_out.add_bin_property("c.pdata", serialized_local_participant_data);
749  message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
750  message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
751 
752  if (local_data.handshake_debug) {
753  message_out.add_bin_property("hash_c2", hash_c2);
754  }
755 
756  diffie_hellman->pub_key(dh2);
757  message_out.add_bin_property("dh2", dh2);
758 
759  if (local_data.handshake_debug) {
760  message_out.add_bin_property("hash_c1", hash_c1);
761  message_out.add_bin_property("dh1", dh1);
762  }
763 
764  message_out.add_bin_property("challenge1", challenge1);
765 
766  TokenReader initiator_local_auth_request(remote_data.local_auth_request);
767  if (! initiator_local_auth_request.is_nil()) {
768  const DDS::OctetSeq& future_challenge = initiator_local_auth_request.get_bin_property_value("future_challenge");
769  message_out.add_bin_property("challenge2", future_challenge);
770  challenge2 = future_challenge;
771 
772  } else {
773  int err = SSL::make_nonce_256(challenge2);
774  if (! err) {
775  message_out.add_bin_property("challenge2", challenge2);
776 
777  } else {
778  set_security_error(ex, -1, 0, "SSL::make_nonce_256 failed.");
779  return Failure;
780  }
781  }
782 
783  DDS::BinaryPropertySeq sign_these;
785  challenge2,
786  dh2,
787  challenge1,
788  dh1,
789  hash_c1,
790  sign_these);
791 
792  DDS::OctetSeq signature;
793  SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), signature);
794  message_out.add_bin_property("signature", signature);
795 
796  remote_data.replier_identity = replier_identity_handle;
797  remote_data.initiator_identity = initiator_identity_handle;
799  remote_data.diffie_hellman = DCPS::move(diffie_hellman);
800  remote_data.certificate = DCPS::move(remote_cert);
801  remote_data.c_perm = cperm;
802  remote_data.reply = handshake_message_out;
803  remote_data.request = request_token;
804  remote_data.hash_c1 = hash_c1;
805  remote_data.hash_c2 = hash_c2;
806 
807  if (handshake_handle == DDS::HANDLE_NIL) {
808  handshake_handle = get_next_handle();
809  }
810 
811  {
813  handshake_data_[handshake_handle] = handshake_data;
814 
815  if (DCPS::security_debug.bookkeeping) {
816  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
817  ACE_TEXT("AuthenticationBuiltInImpl::begin_handshake_reply handshake_data_ (total %B)\n"),
818  handshake_data_.size()));
819  }
820  }
821 
822  return Pending;
823 }
824 
826  ::DDS::Security::HandshakeMessageToken & handshake_message_out,
827  const ::DDS::Security::HandshakeMessageToken & handshake_message_in,
828  ::DDS::Security::HandshakeHandle handshake_handle,
830 {
831  const std::string incoming_class_ext = get_extension(handshake_message_in.class_id);
832 
833  if (Handshake_Reply_Class_Ext == incoming_class_ext) {
834  return process_handshake_reply(handshake_message_out, handshake_message_in, handshake_handle, ex);
835 
836  } else if (Handshake_Final_Class_Ext == incoming_class_ext) {
837  return process_final_handshake(handshake_message_in, handshake_handle, ex);
838  }
839 
841 }
842 
844  ::DDS::Security::HandshakeHandle handshake_handle,
846 {
847  using namespace DDS::Security;
848 
849  SharedSecretHandle* result = 0;
850 
851  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
852 
853  HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
854  if (handshake_data.first && handshake_data.second) {
855 
856  ValidationResult_t state = handshake_data.second->state;
857  if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
858  SharedSecretHandle_var handle = handshake_data.second->shared_secret;
859  result = handle._retn();
860 
861  } else {
862  set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
863  }
864 
865  } else {
866  set_security_error(ex, -1, 0, "Unknown handshake handle");
867  }
868 
869  return result;
870 }
871 
873  ::DDS::Security::AuthenticatedPeerCredentialToken & peer_credential_token,
874  ::DDS::Security::HandshakeHandle handshake_handle,
876 {
877  using namespace DDS::Security;
878  ::CORBA::Boolean result = false;
879 
880  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
881 
882  HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
883  if (handshake_data.first && handshake_data.second) {
884  ValidationResult_t state = handshake_data.second->state;
885  if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
886  OpenDDS::Security::TokenWriter peer_token(peer_credential_token, Auth_Peer_Cred_Token_Class_Id);
887 
888  DDS::BinaryPropertySeq& props = peer_credential_token.binary_properties;
889  props.length(2);
890 
892  p1.name = "c.id";
893  p1.value = handshake_data.second->certificate->original_bytes();
894  p1.propagate = true;
895 
897  p2.name = "c.perm";
898  p2.value = handshake_data.second->c_perm;
899  p2.propagate = true;
900 
901  props[0] = p1;
902  props[1] = p2;
903 
904  result = true;
905 
906  } else {
907  set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
908  }
909 
910  } else {
911  set_security_error(ex, -1, 0, "Unknown handshake handle");
912  }
913 
914  return result;
915 }
916 
918  ::DDS::Security::AuthenticationListener_ptr listener,
920 {
921  ::CORBA::Boolean results = false;
922 
923  if (!listener) {
924  set_security_error(ex, -1, 0, "Null listener provided");
925  } else {
926  results = true;
927  listener_ptr_ = listener;
928  }
929  return results;
930 }
931 
935 {
936  // Nothing to do here yet
937  ACE_UNUSED_ARG(token);
938  ACE_UNUSED_ARG(ex);
939  return true;
940 }
941 
942 
946 {
947  // Nothing to do here yet
948  ACE_UNUSED_ARG(token);
949  ACE_UNUSED_ARG(ex);
950  return true;
951 }
952 
953 
957 {
958  // Nothing to do here yet
959  ACE_UNUSED_ARG(peer_credential_token);
960  ACE_UNUSED_ARG(ex);
961  return true;
962 }
963 
965  ::DDS::Security::HandshakeHandle handshake_handle,
967 {
969 
970  HandshakeDataMap::iterator found = handshake_data_.find(handshake_handle);
971  if (found != handshake_data_.end()) {
972  handshake_data_.erase(found);
973 
974  if (DCPS::security_debug.bookkeeping) {
975  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
976  ACE_TEXT("AuthenticationBuiltInImpl::return_handshake_handle handshake_data_ (total %B)\n"),
977  handshake_data_.size()));
978  }
979 
980  return true;
981  }
982 
983  set_security_error(ex, -1, 0, "Handshake handle not recognized");
984  return false;
985 }
986 
988  ::DDS::Security::IdentityHandle identity_handle,
990 {
992 
993  LocalParticipantMap::iterator local = local_participants_.find(identity_handle);
994 
995  if (local != local_participants_.end()) {
996 
997  {
998  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
999 
1000  for (HandshakeDataMap::iterator it = handshake_data_.begin(); it != handshake_data_.end(); /* increment in loop*/) {
1001  if (it->second.first == local->second) {
1002  handshake_data_.erase(it++);
1003  } else {
1004  ++it;
1005  }
1006  }
1007  }
1008 
1009  local_participants_.erase(local);
1010 
1011  if (DCPS::security_debug.bookkeeping) {
1012  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
1013  ACE_TEXT("AuthenticationBuiltInImpl::return_identity_handle local_participants_ (total %B)\n"),
1014  local_participants_.size()));
1015  }
1016 
1017  return true;
1018  }
1019 
1020  local = std::find_if(local_participants_.begin(), local_participants_.end(),
1021  local_has_remote_handle(identity_handle));
1022 
1023  if (local != local_participants_.end()) {
1024 
1025  const RemoteParticipantMap::iterator remote = local->second->validated_remotes.find(identity_handle);
1026 
1027  {
1028  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
1029 
1030  for (HandshakeDataMap::iterator it = handshake_data_.begin(); it != handshake_data_.end(); /* increment in loop*/) {
1031  if (it->second.second == remote->second) {
1032  handshake_data_.erase(it++);
1033  } else {
1034  ++it;
1035  }
1036  }
1037  }
1038 
1039  local->second->validated_remotes.erase(remote);
1040 
1041  if (DCPS::security_debug.bookkeeping) {
1042  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
1043  ACE_TEXT("AuthenticationBuiltInImpl::return_identity_handle validated_remotes (total %B)\n"),
1044  local->second->validated_remotes.size()));
1045  }
1046 
1047  return true;
1048  }
1049 
1050  set_security_error(ex, -1, 0, "Identity handle not recognized");
1051  return false;
1052 }
1053 
1055  ::DDS::Security::SharedSecretHandle* sharedsecret_handle,
1057 {
1058  // Nothing to do here in the stub version
1059  ACE_UNUSED_ARG(sharedsecret_handle);
1060  ACE_UNUSED_ARG(ex);
1061  return true;
1062 }
1063 
1064 
1066  DDS::Security::HandshakeMessageToken & handshake_message_out,
1067  const DDS::Security::HandshakeMessageToken & handshake_message_in,
1068  DDS::Security::HandshakeHandle handshake_handle,
1070 {
1071  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
1072  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
1073 
1074  DDS::OctetSeq challenge1, hash_c2;
1076 
1079 
1080  HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
1081  if (!handshake_data.first || !handshake_data.second) {
1082  set_security_error(ex, -1, 0, "Unknown handshake handle");
1083  return Failure;
1084  }
1085 
1086  LocalParticipantData& local_data = *(handshake_data.first);
1087  RemoteParticipantData& remote_data = *(handshake_data.second);
1088 
1090  set_security_error(ex, -1, 0, "Handshake state is not valid");
1091  return Failure;
1092  }
1093 
1094  TokenReader message_in(handshake_message_in);
1095  if (message_in.is_nil()) {
1096  set_security_error(ex, -1, 0, "Handshake_message_in must not be nil");
1097  return Failure;
1098  }
1099 
1100  const DDS::OctetSeq& challenge2 = message_in.get_bin_property_value("challenge2");
1101 
1102  TokenReader auth_wrapper(remote_data.remote_auth_request);
1103  if (! auth_wrapper.is_nil()) {
1104  const DDS::OctetSeq& future_challenge = auth_wrapper.get_bin_property_value("future_challenge");
1105 
1106  if (! challenges_match(challenge2, future_challenge)) {
1107  set_security_error(ex, -1, 0, "challenge2 does not match future_challenge");
1108  return Failure;
1109  }
1110  }
1111 
1112  const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
1113 
1114  const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
1115  if (cid.length() > 0) {
1116 
1117  remote_cert->deserialize(cid);
1118 
1119  if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
1120  {
1121  set_security_error(ex, -1, 0, "Certificate validation failed");
1122  return Failure;
1123  }
1124 
1125  } else {
1126  set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
1127  return Failure;
1128  }
1129 
1130  /* Check that challenge1 on message_in matches the one sent in HandshakeRequestMessageToken */
1131 
1132  TokenReader handshake_request_token(remote_data.request);
1133  if (handshake_request_token.is_nil()) {
1134  set_security_error(ex, -1, 0, "Handshake-request-token is nil");
1135  return Failure;
1136 
1137  } else {
1138  challenge1 = handshake_request_token.get_bin_property_value("challenge1");
1139  const DDS::OctetSeq& challenge1_reply = message_in.get_bin_property_value("challenge1");
1140 
1141  if (! challenges_match(challenge1, challenge1_reply)) {
1142  set_security_error(ex, -1, 0, "handshake-request challenge1 value does not match local challenge1");
1143  return Failure;
1144  }
1145  }
1146 
1147  /* Validate participant_guid in c.pdata */
1148 
1149  const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
1150 
1151  std::vector<unsigned char> hash;
1152  if (0 != remote_cert->subject_name_digest(hash)) {
1153  set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
1154  return Failure;
1155  }
1156 
1157  if (! validate_topic_data_guid(cpdata, hash, ex)) {
1158  return Failure;
1159  }
1160 
1161  /* Compute/Store the Diffie-Hellman shared-secret */
1162 
1163  const DDS::OctetSeq& dh2 = message_in.get_bin_property_value("dh2");
1164  if (0 != remote_data.diffie_hellman->gen_shared_secret(dh2)) {
1165  set_security_error(ex, -1, 0, "Failed to generate shared secret from dh1 and dh2");
1166  return Failure;
1167  }
1168 
1169  const DDS::OctetSeq& cperm = message_in.get_bin_property_value("c.perm");
1170 
1171  /* Compute hash_c2 and store for later (hash_c1 was already computed in request) */
1172 
1173  {
1174  CredentialHash hash(*remote_cert,
1175  *remote_data.diffie_hellman,
1176  cpdata,
1177  cperm);
1178  int err = hash(hash_c2);
1179  if (err) {
1180  set_security_error(ex, -1, 0, "Computing hash_c2 failed");
1181  return Failure;
1182  }
1183  }
1184 
1185  /* Validate Signature field */
1186  const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
1187 
1188  DDS::BinaryPropertySeq verify_these;
1190  challenge2,
1191  dh2,
1192  challenge1,
1193  dh1,
1194  remote_data.hash_c1,
1195  verify_these);
1196 
1197  const DDS::OctetSeq& remote_signature = message_in.get_bin_property_value("signature");
1198 
1199  int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
1200  if (err) {
1201  set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
1202  return Failure;
1203  }
1204 
1205  OpenDDS::Security::TokenWriter final_msg(handshake_message_out, build_class_id(Handshake_Final_Class_Ext));
1206 
1207  if (local_data.handshake_debug) {
1208  final_msg.add_bin_property("hash_c1", remote_data.hash_c1);
1209  final_msg.add_bin_property("hash_c2", hash_c2);
1210  final_msg.add_bin_property("dh1", dh1);
1211  final_msg.add_bin_property("dh2", dh2);
1212  }
1213 
1214  final_msg.add_bin_property("challenge1", challenge1);
1215  final_msg.add_bin_property("challenge2", challenge2);
1216 
1217  DDS::BinaryPropertySeq sign_these;
1219  challenge1,
1220  dh1,
1221  challenge2,
1222  dh2,
1223  hash_c2,
1224  sign_these);
1225 
1226  DDS::OctetSeq tmp;
1227  SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), tmp);
1228  final_msg.add_bin_property("signature", tmp);
1229 
1230  remote_data.certificate = DCPS::move(remote_cert);
1231  remote_data.state = FinalMessage;
1232  remote_data.c_perm = message_in.get_bin_property_value("c.perm");
1233  remote_data.hash_c2 = hash_c2;
1234  remote_data.shared_secret = new SharedSecret(challenge1,
1235  challenge2,
1236  remote_data.diffie_hellman->get_shared_secret());
1237  return FinalMessage;
1238 }
1239 
1241 {
1242  if ((c1.length()) < 1 || (c2.length() < 1)) {
1243  return false;
1244  }
1245  if (c1.length() != c2.length()) {
1246  return false;
1247  }
1248 
1249  if (0 != std::memcmp(c1.get_buffer(), c2.get_buffer(), c2.length())) {
1250  return false;
1251  }
1252 
1253  return true;
1254 }
1255 
1257  const DDS::Security::HandshakeMessageToken & handshake_message_in, /* Final message token */
1258  DDS::Security::HandshakeHandle handshake_handle,
1260 {
1263 
1264  ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
1265  ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
1266 
1267  HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
1268  if (!handshake_data.first || !handshake_data.second) {
1269  set_security_error(ex, -1, 0, "Unknown handshake handle");
1270  return Failure;
1271  }
1272 
1273  RemoteParticipantData& remote_data = *(handshake_data.second);
1274 
1276  set_security_error(ex, -1, 0, "Handshake state is not valid");
1277  return Failure;
1278  }
1279 
1280  /* Check challenge1 and challenge2 match what was sent with the reply-message-token */
1281 
1282  TokenReader handshake_final_token(handshake_message_in);
1283  if (handshake_final_token.is_nil()) {
1284  set_security_error(ex, -1, 0, "Handshake-final-token is nil");
1285  return Failure;
1286  }
1287 
1288  TokenReader handshake_reply_token(remote_data.reply);
1289  if (handshake_reply_token.is_nil()) {
1290  set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
1291  return Failure;
1292  }
1293 
1294  /* Per the spec, dh1 is optional in all _but_ the request token so it's grabbed from the request */
1295  TokenReader handshake_request_token(remote_data.request);
1296  if (handshake_reply_token.is_nil()) {
1297  set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
1298  return Failure;
1299  }
1300 
1301  const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
1302  const DDS::OctetSeq& dh2 = handshake_reply_token.get_bin_property_value("dh2");
1303 
1304  const DDS::OctetSeq& challenge1_reply = handshake_reply_token.get_bin_property_value("challenge1");
1305  const DDS::OctetSeq& challenge2_reply = handshake_reply_token.get_bin_property_value("challenge2");
1306 
1307  const DDS::OctetSeq& challenge1_final = handshake_final_token.get_bin_property_value("challenge1");
1308  const DDS::OctetSeq& challenge2_final = handshake_final_token.get_bin_property_value("challenge2");
1309 
1310  if (! challenges_match(challenge1_reply, challenge1_final) || ! challenges_match(challenge2_reply, challenge2_final)) {
1311  return Failure;
1312  }
1313 
1314  /* Validate Signature field */
1315 
1316  const SSL::Certificate::unique_ptr& remote_cert = remote_data.certificate;
1317 
1318  DDS::BinaryPropertySeq verify_these;
1320  challenge1_reply,
1321  dh1,
1322  challenge2_reply,
1323  dh2,
1324  remote_data.hash_c2,
1325  verify_these);
1326 
1327  const DDS::OctetSeq& remote_signature = handshake_final_token.get_bin_property_value("signature");
1328 
1329  int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
1330  if (err) {
1331  set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
1332  return Failure;
1333  }
1334 
1335  /* Compute/Store the Diffie-Hellman shared-secret */
1336 
1337  if (0 != remote_data.diffie_hellman->gen_shared_secret(dh1)) {
1338  set_security_error(ex, -1, 0, "Failed to generate shared secret from dh2 and dh1");
1339  return Failure;
1340  }
1341 
1342  remote_data.state = DDS::Security::VALIDATION_OK;
1343  remote_data.shared_secret = new SharedSecret(challenge1_reply,
1344  challenge2_reply,
1345  remote_data.diffie_hellman->get_shared_secret());
1346 
1347  return ValidationOkay;
1348 }
1349 
1352 {
1353  LocalParticipantMap::iterator found = local_participants_.find(handle);
1354  if (found != local_participants_.end()) {
1355  return found->second;
1356  }
1357 
1359 }
1360 
1362 {
1363  if (DCPS::security_debug.bookkeeping) {
1364  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) {bookkeeping} ")
1365  ACE_TEXT("LocalParticipantData::~LocalParticipantData validated_remotes %B\n"),
1366  validated_remotes.size()));
1367  }
1368 }
1369 
1372 {
1373  HandshakeDataMap::iterator found = handshake_data_.find(handle);
1374  if (found != handshake_data_.end()) {
1375  return found->second;
1376  }
1377 
1378  return HandshakeDataPair();
1379 }
1380 
1384 {
1386 
1387  LocalParticipantMap::iterator found_local = local_participants_.find(h1);
1388  if (found_local != local_participants_.end()) {
1389  other = h2;
1390 
1391  } else {
1392  found_local = local_participants_.find(h2);
1393  if (found_local != local_participants_.end()) {
1394  other = h1;
1395 
1396  } else {
1397  return HandshakeDataPair();
1398  }
1399  }
1400 
1401  RemoteParticipantMap::iterator found_remote = found_local->second->validated_remotes.find(other);
1402  if (found_remote != found_local->second->validated_remotes.end()) {
1403  return std::make_pair(found_local->second, found_remote->second);
1404  }
1405 
1406  return HandshakeDataPair();
1407 }
1408 
1410  const OpenDDS::DCPS::GUID_t& local, const OpenDDS::DCPS::GUID_t& remote)
1411 {
1412  const unsigned char* local_ = reinterpret_cast<const unsigned char*>(&local);
1413  const unsigned char* remote_ = reinterpret_cast<const unsigned char*>(&remote);
1414 
1415  using DCPS::SecurityDebug;
1416  if (DCPS::security_debug.force_auth_role != SecurityDebug::FORCE_AUTH_ROLE_NORMAL) {
1417  return DCPS::security_debug.force_auth_role == SecurityDebug::FORCE_AUTH_ROLE_LEADER;
1418  }
1419 
1420  /* if remote > local, pending request; else pending handshake message */
1421  return std::lexicographical_compare(local_, local_ + sizeof(local),
1422  remote_, remote_ + sizeof(remote));
1423 
1424 }
1425 
1426 bool AuthenticationBuiltInImpl::check_class_versions(const char* remote_class_id)
1427 {
1428  if (!remote_class_id) {
1429  return false;
1430  }
1431  bool class_matches = false;
1432 
1433  // Slow, but this is just for the stub
1434  std::string class_id_str(remote_class_id);
1435 
1436  // Class name is the text prior to the final ':'
1437  size_t colon_pos = class_id_str.find_last_of(':');
1438  if (std::string::npos != colon_pos && colon_pos > 0) {
1439  // Compare the class name vs the expected class name
1440  std::string remote_class_name = class_id_str.substr(0, colon_pos);
1441  if (0 == Auth_Plugin_Name.compare(remote_class_name)) {
1442  // Major version is the text between the final : and a .
1443  size_t major_start = colon_pos + 1;
1444  size_t period_pos = class_id_str.find_first_of('.', major_start);
1445  if (std::string::npos != period_pos && period_pos > major_start) {
1446  std::string major_version = class_id_str.substr(major_start, period_pos - major_start);
1447  if (0 == Auth_Plugin_Major_Version.compare(major_version)) {
1448  class_matches = true;
1449  }
1450  }
1451  }
1452  }
1453 
1454  return class_matches;
1455 }
1456 
1457 std::string AuthenticationBuiltInImpl::build_class_id(const std::string& message_ext)
1458 {
1459  std::string class_id_stream = Auth_Plugin_Name +
1462  + "+" + message_ext;
1463 
1464  return class_id_stream;
1465 }
1466 
1467 std::string AuthenticationBuiltInImpl::get_extension(const char* class_id)
1468 {
1469  std::string ext_string("");
1470 
1471  std::string class_id_str(class_id);
1472  size_t extension_delim_pos = class_id_str.find_last_of('+');
1473  if (extension_delim_pos != std::string::npos) {
1474  size_t start_ext_pos = extension_delim_pos + 1;
1475  if (start_ext_pos < class_id_str.length()) {
1476  ext_string = class_id_str.substr(start_ext_pos);
1477  }
1478  }
1479 
1480  return ext_string;
1481 }
1482 
1484 {
1487 }
1488 
1489 } // namespace Security
1490 } // namespace OpenDDS
1491 
#define ACE_DEBUG(X)
static DiffieHellman * factory(const DDS::OctetSeq &kagree_algo)
const DDS::OctetSeq & original_bytes() const
Definition: Certificate.h:90
DDS::Security::ValidationResult_t process_final_handshake(const DDS::Security::HandshakeMessageToken &handshake_message_in, DDS::Security::HandshakeHandle handshake_handle, DDS::Security::SecurityException &ex)
ACE_CDR::Long Long
#define ACE_ERROR(X)
virtual ::DDS::Security::SharedSecretHandle * get_shared_secret(::DDS::Security::HandshakeHandle handshake_handle, ::DDS::Security::SecurityException &ex)
BinaryPropertySeq binary_properties
virtual ::DDS::Security::ValidationResult_t begin_handshake_request(::DDS::Security::HandshakeHandle &handshake_handle, ::DDS::Security::HandshakeMessageToken &handshake_message, ::DDS::Security::IdentityHandle initiator_identity_handle, ::DDS::Security::IdentityHandle replier_identity_handle, const ::DDS::OctetSeq &serialized_local_participant_data, ::DDS::Security::SecurityException &ex)
const char Auth_Peer_Cred_Token_Class_Id[]
Implements some simple wrapper functions to provide a const API around the Token data structure as sp...
Definition: TokenReader.h:40
const InstanceHandle_t HANDLE_NIL
static void make_reply_signature_sequence(const DDS::OctetSeq &hash_c2, const DDS::OctetSeq &challenge2, const DDS::OctetSeq &dh2, const DDS::OctetSeq &challenge1, const DDS::OctetSeq &dh1, const DDS::OctetSeq &hash_c1, DDS::BinaryPropertySeq &dst)
int make_nonce_256(std::vector< unsigned char > &nonce)
int hash(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst)
bool is_handshake_initiator(const DCPS::GUID_t &local, const DCPS::GUID_t &remote)
int sign_serialized(const DDS::BinaryPropertySeq &src, const PrivateKey &key, DDS::OctetSeq &dst)
static void make_final_signature_sequence(const DDS::OctetSeq &hash_c1, const DDS::OctetSeq &challenge1, const DDS::OctetSeq &dh1, const DDS::OctetSeq &challenge2, const DDS::OctetSeq &dh2, const DDS::OctetSeq &hash_c2, DDS::BinaryPropertySeq &dst)
void add_bin_property(const char *prop_name, const DDS::OctetSeq &prop_value, bool propagate=true)
Definition: TokenWriter.cpp:59
SharedSecret(DDS::OctetSeq challenge1, DDS::OctetSeq challenge2, DDS::OctetSeq sharedSecret)
const GUID_t GUID_UNKNOWN
Nil value for GUID.
Definition: GuidUtils.h:59
const ParameterId_t PID_PARTICIPANT_GUID
Definition: RtpsCore.idl:289
YARD is all original work While it may rely on standard YARD does not include code from other sources We have chosen to release our work as public domain code This means that YARD has been released outside the copyright system Feel free to use the code in any way you wish especially in an academic plagiarism has very little to do with copyright In an academic or in any situation where you are expected to give credit to other people s you will need to cite YARD as a source The author is Christopher and the appropriate date is December the release date for we can t make any promises regarding whether YARD will do what you or whether we will make any changes you ask for You are free to hire your own expert for that If you choose to distribute YARD you ll probably want to read up on the laws covering warranties in your state
Definition: COPYING.txt:14
virtual ::DDS::Security::ValidationResult_t validate_remote_identity(::DDS::Security::IdentityHandle &remote_identity_handle, ::DDS::Security::AuthRequestMessageToken &local_auth_request_token, const ::DDS::Security::AuthRequestMessageToken &remote_auth_request_token, ::DDS::Security::IdentityHandle local_identity_handle, const ::DDS::Security::IdentityToken &remote_identity_token, const DCPS::GUID_t &remote_participant_guid, ::DDS::Security::SecurityException &ex)
LocalParticipantData::shared_ptr get_local_participant(DDS::Security::IdentityHandle handle)
DDS::DomainId_t DomainId_t
virtual ::DDS::Security::ValidationResult_t validate_local_identity(::DDS::Security::IdentityHandle &local_identity_handle, DCPS::GUID_t &adjusted_participant_guid, ::DDS::Security::DomainId_t domain_id, const ::DDS::DomainParticipantQos &participant_qos, const DCPS::GUID_t &candidate_participant_guid, ::DDS::Security::SecurityException &ex)
DDS::Security::ValidationResult_t process_handshake_reply(DDS::Security::HandshakeMessageToken &handshake_message_out, const DDS::Security::HandshakeMessageToken &handshake_message_in, DDS::Security::HandshakeHandle handshake_handle, DDS::Security::SecurityException &ex)
virtual ::CORBA::Boolean set_listener(::DDS::Security::AuthenticationListener_ptr listener, ::DDS::Security::SecurityException &ex)
key GuidPrefix_t guidPrefix
Definition: DdsDcpsGuid.idl:58
T::rv_reference move(T &p)
Definition: unique_ptr.h:141
virtual ::CORBA::Boolean return_identity_handle(::DDS::Security::IdentityHandle identity_handle, ::DDS::Security::SecurityException &ex)
const std::string Handshake_Reply_Class_Ext("Reply")
virtual ::CORBA::Boolean set_permissions_credential_and_token(::DDS::Security::IdentityHandle handle, const ::DDS::Security::PermissionsCredentialToken &permissions_credential, const ::DDS::Security::PermissionsToken &permissions_token, ::DDS::Security::SecurityException &ex)
virtual ::CORBA::Boolean return_identity_token(const ::DDS::Security::IdentityToken &token, ::DDS::Security::SecurityException &ex)
OpenDDS::internal::special_serialization typedef sequence< Parameter > ParameterList
Definition: RtpsCore.idl:236
u_int major_version(void)
unsigned char offset_1bit(const unsigned char array[], size_t i)
Gets byte from array as though it were shifted right one bit.
const SSL::Certificate & get_participant_cert() const
const char * dsign_algo() const
Definition: Certificate.h:92
const std::string Auth_Plugin_Name("DDS:Auth:PKI-DH")
LM_DEBUG
const std::string Auth_Plugin_Minor_Version("0")
Class to serialize and deserialize data for DDS.
Definition: Serializer.h:369
HandshakeDataPair make_handshake_pair(DDS::Security::IdentityHandle h1, DDS::Security::IdentityHandle h2)
Finds the local and remote data objects associated with h1 and h2 and creates a new handshake pair wi...
ACE_CDR::Boolean Boolean
const DDS::OctetSeq & get_access_permissions() const
int verify_serialized(const DDS::BinaryPropertySeq &src, const Certificate &key, const DDS::OctetSeq &signed_data)
std::pair< LocalParticipantData::shared_ptr, RemoteParticipantData::shared_ptr > HandshakeDataPair
MessageToken AuthRequestMessageToken
virtual ::CORBA::Boolean return_sharedsecret_handle(::DDS::Security::SharedSecretHandle *sharedsecret_handle, ::DDS::Security::SecurityException &ex)
void add_property(const char *prop_name, const char *prop_value, bool propagate=true)
Definition: TokenWriter.cpp:38
static void extract_participant_guid_from_cpdata(const DDS::OctetSeq &cpdata, DCPS::GUID_t &dst)
DDS::BinaryPropertySeq BinaryPropertySeq
char * wr_ptr(void) const
LM_WARNING
sequence< octet > OctetSeq
Definition: DdsDcpsCore.idl:64
const std::string Handshake_Request_Class_Ext("Req")
virtual ::CORBA::Boolean get_identity_status_token(::DDS::Security::IdentityStatusToken &identity_status_token, ::DDS::Security::IdentityHandle handle, ::DDS::Security::SecurityException &ex)
const SSL::PrivateKey & get_participant_private_key() const
virtual ::CORBA::Boolean return_handshake_handle(::DDS::Security::HandshakeHandle handshake_handle, ::DDS::Security::SecurityException &ex)
const std::string Auth_Plugin_Major_Version("1")
virtual ::CORBA::Boolean get_authenticated_peer_credential_token(::DDS::Security::AuthenticatedPeerCredentialToken &peer_credential_token, ::DDS::Security::HandshakeHandle handshake_handle, ::DDS::Security::SecurityException &ex)
const DDS::OctetSeq & get_bin_property_value(const std::string &property_name) const
Definition: TokenReader.cpp:59
ACE_TEXT("TCP_Factory")
HandshakeDataPair get_handshake_data(DDS::Security::HandshakeHandle handle)
virtual ::DDS::Security::ValidationResult_t begin_handshake_reply(::DDS::Security::HandshakeHandle &handshake_handle, ::DDS::Security::HandshakeMessageToken &handshake_message_out, ::DDS::Security::IdentityHandle initiator_identity_handle, ::DDS::Security::IdentityHandle replier_identity_handle, const ::DDS::OctetSeq &serialized_local_participant_data, ::DDS::Security::SecurityException &ex)
MessageToken HandshakeMessageToken
octet GuidPrefix_t[12]
Definition: DdsDcpsGuid.idl:19
const char Identity_Status_Token_Class_Id[]
const std::string Auth_Request_Class_Ext("AuthReq")
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
int make_adjusted_guid(const OpenDDS::DCPS::GUID_t &src, OpenDDS::DCPS::GUID_t &dst, const Certificate &target)
int subject_name_to_str(std::string &dst, unsigned long flags=XN_FLAG_ONELINE) const
std::string build_class_id(const std::string &message_ext)
Token PermissionsCredentialToken
virtual ::CORBA::Boolean get_identity_token(::DDS::Security::IdentityToken &identity_token, ::DDS::Security::IdentityHandle handle, ::DDS::Security::SecurityException &ex)
DDS::Security::AuthenticationListener_ptr listener_ptr_
bool set_security_error(DDS::Security::SecurityException &ex, int code, int minor_code, const char *message)
const SSL::Certificate & get_ca_cert() const
static bool challenges_match(const DDS::OctetSeq &c1, const DDS::OctetSeq &c2)
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
enum OpenDDS::DCPS::SecurityDebug::ForceAuthRole force_auth_role
virtual ::DDS::Security::ValidationResult_t process_handshake(::DDS::Security::HandshakeMessageToken &handshake_message_out, const ::DDS::Security::HandshakeMessageToken &handshake_message_in, ::DDS::Security::HandshakeHandle handshake_handle, ::DDS::Security::SecurityException &ex)
Token AuthenticatedPeerCredentialToken
Implements some simple wrapper functions to provide a non-const API around the Token data structure a...
Definition: TokenWriter.h:43
static bool validate_topic_data_guid(const DDS::OctetSeq &cpdata, const std::vector< unsigned char > &subject_name_hash, DDS::Security::SecurityException &ex)
OpenDDS_Dcps_Export SecurityDebug security_debug
Definition: debug.cpp:32
virtual ::CORBA::Boolean return_identity_status_token(const ::DDS::Security::IdentityStatusToken &token, ::DDS::Security::SecurityException &ex)
const std::string Handshake_Final_Class_Ext("Final")
virtual ::CORBA::Boolean return_authenticated_peer_credential_token(const ::DDS::Security::AuthenticatedPeerCredentialToken &peer_credential_token, ::DDS::Security::SecurityException &ex)
static const char * PROPERTY_HANDSHAKE_DEBUG
include in PropertyQosPolicy to add optional properties to Handshake tokens