00001
00002
00003
00004
00005
00006
00007
00008 #include "AuthenticationBuiltInImpl.h"
00009
00010 #include "CommonUtilities.h"
00011 #include "TokenReader.h"
00012 #include "TokenWriter.h"
00013 #include "SSL/Utils.h"
00014
00015 #include "dds/DCPS/GuidUtils.h"
00016 #include "dds/DCPS/LocalObject.h"
00017 #include "dds/DCPS/Serializer.h"
00018
00019 #include "dds/DCPS/RTPS/RtpsCoreC.h"
00020 #include "dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.h"
00021
00022 #include "ace/config-macros.h"
00023 #include "ace/Guard_T.h"
00024
00025 #include <sstream>
00026 #include <vector>
00027 #include <algorithm>
00028 #include <cstdio>
00029
00030 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00031
00032 namespace OpenDDS {
00033 namespace Security {
00034
00035 using CommonUtilities::set_security_error;
00036
00037 static bool challenges_match(const DDS::OctetSeq& c1, const DDS::OctetSeq& c2);
00038
00039 static void extract_participant_guid_from_cpdata(const DDS::OctetSeq& cpdata, DCPS::GUID_t& dst);
00040
00041 static bool validate_topic_data_guid(const DDS::OctetSeq& cpdata,
00042 const std::vector<unsigned char>& subject_name_hash,
00043 DDS::Security::SecurityException& ex);
00044
00045 const std::string Auth_Plugin_Name("DDS:Auth:PKI-DH");
00046 const std::string Auth_Plugin_Major_Version("1");
00047 const std::string Auth_Plugin_Minor_Version("0");
00048
00049 const std::string Identity_Status_Token_Class_Id("DDS:Auth:PKI-DH:1.0");
00050 const std::string Auth_Peer_Cred_Token_Class_Id("DDS:Auth:PKI-DH:1.0");
00051 const std::string Auth_Request_Class_Ext("AuthReq");
00052 const std::string Handshake_Request_Class_Ext("Req");
00053 const std::string Handshake_Reply_Class_Ext("Reply");
00054 const std::string Handshake_Final_Class_Ext("Final");
00055
00056 struct SharedSecret : DCPS::LocalObject<DDS::Security::SharedSecretHandle> {
00057
00058 SharedSecret(DDS::OctetSeq challenge1,
00059 DDS::OctetSeq challenge2,
00060 DDS::OctetSeq sharedSecret)
00061 : challenge1_(challenge1)
00062 , challenge2_(challenge2)
00063 , shared_secret_(sharedSecret)
00064 {}
00065
00066 DDS::OctetSeq* challenge1() { return new DDS::OctetSeq(challenge1_); }
00067 DDS::OctetSeq* challenge2() { return new DDS::OctetSeq(challenge2_); }
00068 DDS::OctetSeq* sharedSecret() { return new DDS::OctetSeq(shared_secret_); }
00069
00070 DDS::OctetSeq challenge1_, challenge2_, shared_secret_;
00071 };
00072
00073 AuthenticationBuiltInImpl::AuthenticationBuiltInImpl()
00074 : listener_ptr_()
00075 , identity_mutex_()
00076 , handshake_mutex_()
00077 , handle_mutex_()
00078 , next_handle_(1)
00079 {
00080 }
00081
00082 AuthenticationBuiltInImpl::~AuthenticationBuiltInImpl()
00083 {
00084
00085 }
00086
00087 ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::validate_local_identity(
00088 ::DDS::Security::IdentityHandle & local_identity_handle,
00089 ::OpenDDS::DCPS::GUID_t & adjusted_participant_guid,
00090 ::DDS::Security::DomainId_t ,
00091 const ::DDS::DomainParticipantQos & participant_qos,
00092 const ::OpenDDS::DCPS::GUID_t & candidate_participant_guid,
00093 ::DDS::Security::SecurityException & ex)
00094 {
00095 DDS::Security::ValidationResult_t result = DDS::Security::VALIDATION_FAILED;
00096
00097 LocalAuthCredentialData::shared_ptr credentials = DCPS::make_rch<LocalAuthCredentialData>();
00098 if (! credentials->load_credentials(participant_qos.property.value, ex)) {
00099 return result;
00100 }
00101
00102 if (credentials->validate()) {
00103 if (candidate_participant_guid != DCPS::GUID_UNKNOWN) {
00104
00105 int err = SSL::make_adjusted_guid(candidate_participant_guid,
00106 adjusted_participant_guid,
00107 credentials->get_participant_cert());
00108 if (! err) {
00109 local_identity_handle = get_next_handle();
00110
00111 LocalParticipantData::shared_ptr local_participant = DCPS::make_rch<LocalParticipantData>();
00112 local_participant->participant_guid = adjusted_participant_guid;
00113 local_participant->credentials = credentials;
00114
00115 {
00116 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00117 local_participants_[local_identity_handle] = local_participant;
00118 }
00119
00120 result = DDS::Security::VALIDATION_OK;
00121
00122 } else {
00123 set_security_error(ex, -1, 0, "SSL::make_adjusted_guid failed");
00124 }
00125
00126 } else {
00127 set_security_error(ex, -1, 0, "GUID_UNKNOWN passed in for candidate_participant_guid");
00128 }
00129
00130 } else {
00131 set_security_error(ex, -1, 0, "local-credential-data failed validation");
00132 }
00133
00134 return result;
00135 }
00136
00137 ::CORBA::Boolean AuthenticationBuiltInImpl::get_identity_token(
00138 ::DDS::Security::IdentityToken & identity_token,
00139 ::DDS::Security::IdentityHandle handle,
00140 ::DDS::Security::SecurityException & ex)
00141 {
00142 ::CORBA::Boolean status = false;
00143
00144 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00145
00146 LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
00147 if (local_data) {
00148 const LocalAuthCredentialData& local_credential_data = *(local_data->credentials);
00149
00150 const SSL::Certificate& pcert = local_credential_data.get_participant_cert();
00151 const SSL::Certificate& cacert = local_credential_data.get_ca_cert();
00152
00153 std::string tmp;
00154
00155 OpenDDS::Security::TokenWriter identity_wrapper(identity_token, "DDS:Auth:PKI-DH:1.0");
00156
00157 pcert.subject_name_to_str(tmp);
00158 identity_wrapper.add_property("dds.cert.sn", tmp.c_str());
00159 identity_wrapper.add_property("dds.cert.algo", pcert.keypair_algo());
00160
00161 cacert.subject_name_to_str(tmp);
00162 identity_wrapper.add_property("dds.ca.sn", tmp.c_str());
00163 identity_wrapper.add_property("dds.ca.algo", cacert.keypair_algo());
00164
00165 status = true;
00166
00167 } else {
00168 set_security_error(ex, -1, 0, "Unknown Identity handle");
00169 }
00170 return status;
00171 }
00172
00173 ::CORBA::Boolean AuthenticationBuiltInImpl::get_identity_status_token(
00174 ::DDS::Security::IdentityStatusToken&,
00175 ::DDS::Security::IdentityHandle handle,
00176 ::DDS::Security::SecurityException & ex)
00177 {
00178 ::CORBA::Boolean status = false;
00179
00180 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00181
00182
00183 LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
00184 if (local_data) {
00185
00186
00187
00188
00189
00190 status = true;
00191 } else {
00192 set_security_error(ex, -1, 0, "Unknown Identity handle");
00193 }
00194
00195 return status;
00196 }
00197
00198 ::CORBA::Boolean AuthenticationBuiltInImpl::set_permissions_credential_and_token(
00199 ::DDS::Security::IdentityHandle handle,
00200 const ::DDS::Security::PermissionsCredentialToken & permissions_credential,
00201 const ::DDS::Security::PermissionsToken & permissions_token,
00202 ::DDS::Security::SecurityException & ex)
00203 {
00204 ACE_UNUSED_ARG(permissions_token);
00205
00206 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00207
00208 LocalParticipantData::shared_ptr local_data = get_local_participant(handle);
00209 if (! local_data) {
00210 set_security_error(ex, -1, 0, "Identity handle not recognized");
00211 return false;
00212 }
00213
00214 return local_data->credentials->load_access_permissions(permissions_credential, ex);
00215 }
00216
00217 ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::validate_remote_identity(
00218 ::DDS::Security::IdentityHandle & remote_identity_handle,
00219 ::DDS::Security::AuthRequestMessageToken & local_auth_request_token,
00220 const ::DDS::Security::AuthRequestMessageToken & remote_auth_request_token,
00221 ::DDS::Security::IdentityHandle local_identity_handle,
00222 const ::DDS::Security::IdentityToken & remote_identity_token,
00223 const ::OpenDDS::DCPS::GUID_t & remote_participant_guid,
00224 ::DDS::Security::SecurityException & ex)
00225 {
00226 DDS::Security::ValidationResult_t result = DDS::Security::VALIDATION_OK;
00227
00228 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00229
00230 LocalParticipantData::shared_ptr local_data = get_local_participant(local_identity_handle);
00231 if (local_data) {
00232 if (check_class_versions(remote_identity_token.class_id)) {
00233
00234
00235
00236
00237 RemoteParticipantMap::iterator begin = local_data->validated_remotes.begin(),
00238 end = local_data->validated_remotes.end(),
00239 found = std::find_if(begin, end,
00240 was_guid_validated(remote_participant_guid));
00241 if (found != end) {
00242 remote_identity_handle = found->first;
00243 local_auth_request_token = found->second->local_auth_request;
00244
00245 if (is_handshake_initiator(local_data->participant_guid, remote_participant_guid)) {
00246 result = DDS::Security::VALIDATION_PENDING_HANDSHAKE_REQUEST;
00247
00248 } else {
00249 result = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00250 }
00251
00252 } else {
00253
00254 TokenReader remote_request(remote_auth_request_token);
00255 if (remote_request.is_nil()) {
00256
00257 DDS::OctetSeq nonce;
00258 int err = SSL::make_nonce_256(nonce);
00259 if (! err) {
00260 TokenWriter auth_req_wrapper(local_auth_request_token, build_class_id(Auth_Request_Class_Ext));
00261
00262 auth_req_wrapper.add_bin_property("future_challenge", nonce);
00263
00264 } else {
00265 set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for future_challenge property");
00266
00267 result = DDS::Security::VALIDATION_FAILED;
00268 }
00269
00270 } else {
00271 local_auth_request_token = DDS::Security::Token();
00272 }
00273
00274 if (result == DDS::Security::VALIDATION_OK) {
00275
00276
00277 RemoteParticipantData::shared_ptr remote_participant = DCPS::make_rch<RemoteParticipantData>();
00278 remote_participant->participant_guid = remote_participant_guid;
00279 remote_participant->local_participant = local_identity_handle;
00280 remote_participant->local_auth_request = local_auth_request_token;
00281 remote_participant->remote_auth_request = remote_auth_request_token;
00282
00283 remote_identity_handle = get_next_handle();
00284 local_data->validated_remotes[remote_identity_handle] = remote_participant;
00285
00286 if (is_handshake_initiator(local_data->participant_guid, remote_participant_guid)) {
00287 result = DDS::Security::VALIDATION_PENDING_HANDSHAKE_REQUEST;
00288
00289 } else {
00290 result = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00291 }
00292 }
00293 }
00294
00295 } else {
00296 set_security_error(ex, -1, 0, "Remote class ID is not compatible");
00297 result = DDS::Security::VALIDATION_FAILED;
00298 }
00299
00300 } else {
00301 set_security_error(ex, -1, 0, "Local participant ID not found");
00302 result = DDS::Security::VALIDATION_FAILED;
00303 }
00304
00305 return result;
00306 }
00307
00308 ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::begin_handshake_request(
00309 ::DDS::Security::HandshakeHandle & handshake_handle,
00310 ::DDS::Security::HandshakeMessageToken & handshake_message,
00311 ::DDS::Security::IdentityHandle initiator_identity_handle,
00312 ::DDS::Security::IdentityHandle replier_identity_handle,
00313 const ::DDS::OctetSeq & serialized_local_participant_data,
00314 ::DDS::Security::SecurityException & ex)
00315 {
00316 if (serialized_local_participant_data.length() == 0) {
00317 set_security_error(ex, -1, 0, "No participant data provided");
00318 return DDS::Security::VALIDATION_FAILED;
00319 }
00320
00321 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00322
00323 HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
00324
00325 if (! handshake_data.first) {
00326 set_security_error(ex, -1, 0, "Unknown local participant");
00327 return DDS::Security::VALIDATION_FAILED;
00328 }
00329
00330 if (! handshake_data.second) {
00331 set_security_error(ex, -1, 0, "Unknown remote participant");
00332 return DDS::Security::VALIDATION_FAILED;
00333 }
00334
00335 LocalParticipantData& local_data = *(handshake_data.first);
00336 RemoteParticipantData& remote_data = *(handshake_data.second);
00337
00338 const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
00339
00340 SSL::DiffieHellman::unique_ptr diffie_hellman(new SSL::DiffieHellman(new SSL::ECDH_PRIME_256_V1_CEUM));
00341
00342 OpenDDS::Security::TokenWriter message_out(handshake_message, build_class_id(Handshake_Request_Class_Ext));
00343
00344
00345
00346 DDS::OctetSeq hash_c1;
00347
00348 {
00349 CredentialHash hash(local_credential_data.get_participant_cert(),
00350 *diffie_hellman,
00351 serialized_local_participant_data,
00352 local_credential_data.get_access_permissions());
00353
00354 int err = hash(hash_c1);
00355 if (err) {
00356 set_security_error(ex, -1, 0, "Failed to generate credential-hash 'hash_c1'");
00357 return DDS::Security::VALIDATION_FAILED;
00358 }
00359 }
00360
00361 message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
00362 message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
00363 message_out.add_bin_property("c.pdata", serialized_local_participant_data);
00364 message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
00365 message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
00366 message_out.add_bin_property("hash_c1", hash_c1);
00367
00368 DDS::OctetSeq dhpub;
00369 diffie_hellman->pub_key(dhpub);
00370 message_out.add_bin_property("dh1", dhpub);
00371
00372 OpenDDS::Security::TokenReader auth_wrapper(remote_data.local_auth_request);
00373 if (auth_wrapper.is_nil()) {
00374 DDS::OctetSeq nonce;
00375 int err = SSL::make_nonce_256(nonce);
00376 if (! err) {
00377 message_out.add_bin_property("challenge1", nonce);
00378
00379 } else {
00380 set_security_error(ex, -1, 0, "Failed to generate 256-bit nonce value for challenge1 property");
00381 return DDS::Security::VALIDATION_FAILED;
00382 }
00383
00384 } else {
00385 const DDS::OctetSeq& challenge_data = auth_wrapper.get_bin_property_value("future_challenge");
00386 message_out.add_bin_property("challenge1", challenge_data);
00387
00388 }
00389
00390 remote_data.initiator_identity = initiator_identity_handle;
00391 remote_data.replier_identity = replier_identity_handle;
00392 remote_data.state = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00393 remote_data.request = handshake_message;
00394 remote_data.reply = DDS::Security::Token();
00395 remote_data.diffie_hellman = DCPS::move(diffie_hellman);
00396 remote_data.hash_c1 = hash_c1;
00397
00398 handshake_handle = get_next_handle();
00399 {
00400 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(handshake_mutex_);
00401 handshake_data_[handshake_handle] = handshake_data;
00402 }
00403
00404 return DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00405 }
00406
00407 void extract_participant_guid_from_cpdata(const DDS::OctetSeq& cpdata, DCPS::GUID_t& dst)
00408 {
00409 dst = DCPS::GUID_UNKNOWN;
00410
00411 ACE_Message_Block buffer(reinterpret_cast<const char*>(cpdata.get_buffer()), cpdata.length());
00412 buffer.wr_ptr(cpdata.length());
00413 OpenDDS::DCPS::Serializer serializer(&buffer, DCPS::Serializer::SWAP_BE, DCPS::Serializer::ALIGN_CDR);
00414 RTPS::ParameterList params;
00415
00416 if (serializer >> params) {
00417 for (size_t i = 0; i < params.length(); ++i) {
00418 const RTPS::Parameter& p = params[i];
00419
00420 if (p._d() == RTPS::PID_PARTICIPANT_GUID) {
00421 dst = p.guid();
00422 break;
00423 }
00424 }
00425
00426 } else {
00427 ACE_ERROR((LM_WARNING,
00428 ACE_TEXT("(%P|%t) WARNING: extract_participant_guid_from_cpdata, ")
00429 ACE_TEXT("failed to deserialize guid from cpdata.\n")));
00430 }
00431
00432 }
00433
00434 bool validate_topic_data_guid(const DDS::OctetSeq& cpdata,
00435 const std::vector<unsigned char>& subject_name_hash,
00436 DDS::Security::SecurityException& ex)
00437 {
00438 if (cpdata.length() > 5u) {
00439
00440 DCPS::GUID_t remote_participant_guid;
00441 extract_participant_guid_from_cpdata(cpdata, remote_participant_guid);
00442
00443 const DCPS::GuidPrefix_t& prefix = remote_participant_guid.guidPrefix;
00444
00445
00446
00447 if ((prefix[0] & 0x80) != 0x80) {
00448 set_security_error(ex, -1, 0, "Malformed participant_guid in 'c.pdata'; First bit must be set.");
00449 return false;
00450 }
00451
00452
00453
00454
00455 if ((prefix[0] & 0x7F) != SSL::offset_1bit(&subject_name_hash[0], 0)) {
00456 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'");
00457 return false;
00458 }
00459 for (size_t i = 1; i <= 5u; ++i) {
00460 if (prefix[i] != SSL::offset_1bit(&subject_name_hash[0], i)) {
00461 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'");
00462 return false;
00463 }
00464 }
00465
00466 } else {
00467 set_security_error(ex, -1, 0, "Data missing in 'c.pdata'");
00468 return false;
00469 }
00470
00471 return true;
00472 }
00473
00474 static void make_reply_signature_sequence(const DDS::OctetSeq& hash_c2,
00475 const DDS::OctetSeq& challenge2,
00476 const DDS::OctetSeq& dh2,
00477 const DDS::OctetSeq& challenge1,
00478 const DDS::OctetSeq& dh1,
00479 const DDS::OctetSeq& hash_c1,
00480 DDS::BinaryPropertySeq& dst)
00481 {
00482 DCPS::SequenceBackInsertIterator<DDS::BinaryPropertySeq> inserter(dst);
00483
00484 {
00485 DDS::BinaryProperty_t p;
00486 p.name = "hash_c2";
00487 p.value = hash_c2;
00488 p.propagate = true;
00489 *inserter = p;
00490 }
00491
00492 {
00493 DDS::BinaryProperty_t p;
00494 p.name = "challenge2";
00495 p.value = challenge2;
00496 p.propagate = true;
00497 *inserter = p;
00498 }
00499
00500 {
00501 DDS::BinaryProperty_t p;
00502 p.name = "dh2";
00503 p.value = dh2;
00504 p.propagate = true;
00505 *inserter = p;
00506 }
00507
00508 {
00509 DDS::BinaryProperty_t p;
00510 p.name = "challenge1";
00511 p.value = challenge1;
00512 p.propagate = true;
00513 *inserter = p;
00514 }
00515
00516 {
00517 DDS::BinaryProperty_t p;
00518 p.name = "dh1";
00519 p.value = dh1;
00520 p.propagate = true;
00521 *inserter = p;
00522 }
00523
00524 {
00525 DDS::BinaryProperty_t p;
00526 p.name = "hash_c1";
00527 p.value = hash_c1;
00528 p.propagate = true;
00529 *inserter = p;
00530 }
00531 }
00532
00533 static void make_final_signature_sequence(const DDS::OctetSeq& hash_c1,
00534 const DDS::OctetSeq& challenge1,
00535 const DDS::OctetSeq& dh1,
00536 const DDS::OctetSeq& challenge2,
00537 const DDS::OctetSeq& dh2,
00538 const DDS::OctetSeq& hash_c2,
00539 DDS::BinaryPropertySeq& dst)
00540 {
00541 DCPS::SequenceBackInsertIterator<DDS::BinaryPropertySeq> inserter(dst);
00542
00543 {
00544 DDS::BinaryProperty_t p;
00545 p.name = "hash_c1";
00546 p.value = hash_c1;
00547 p.propagate = true;
00548 *inserter = p;
00549 }
00550
00551 {
00552 DDS::BinaryProperty_t p;
00553 p.name = "challenge1";
00554 p.value = challenge1;
00555 p.propagate = true;
00556 *inserter = p;
00557 }
00558
00559 {
00560 DDS::BinaryProperty_t p;
00561 p.name = "dh1";
00562 p.value = dh1;
00563 p.propagate = true;
00564 *inserter = p;
00565 }
00566
00567 {
00568 DDS::BinaryProperty_t p;
00569 p.name = "challenge2";
00570 p.value = challenge2;
00571 p.propagate = true;
00572 *inserter = p;
00573 }
00574
00575 {
00576 DDS::BinaryProperty_t p;
00577 p.name = "dh2";
00578 p.value = dh2;
00579 p.propagate = true;
00580 *inserter = p;
00581 }
00582
00583 {
00584 DDS::BinaryProperty_t p;
00585 p.name = "hash_c2";
00586 p.value = hash_c2;
00587 p.propagate = true;
00588 *inserter = p;
00589 }
00590 }
00591
00592 ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::begin_handshake_reply(
00593 ::DDS::Security::HandshakeHandle & handshake_handle,
00594 ::DDS::Security::HandshakeMessageToken & handshake_message_out,
00595 ::DDS::Security::IdentityHandle initiator_identity_handle,
00596 ::DDS::Security::IdentityHandle replier_identity_handle,
00597 const ::DDS::OctetSeq & serialized_local_participant_data,
00598 ::DDS::Security::SecurityException & ex)
00599 {
00600 using OpenDDS::Security::TokenWriter;
00601 using OpenDDS::Security::TokenReader;
00602
00603 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00604
00605
00606 const DDS::Security::HandshakeMessageToken request_token = handshake_message_out;
00607 handshake_message_out = DDS::Security::HandshakeMessageToken();
00608
00609 DDS::OctetSeq challenge1, challenge2, dh2, cperm, hash_c1, hash_c2;
00610
00611 SSL::Certificate::unique_ptr remote_cert(new SSL::Certificate);
00612 SSL::DiffieHellman::unique_ptr diffie_hellman;
00613
00614 const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED,
00615 Pending = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00616
00617 if (serialized_local_participant_data.length() == 0) {
00618 set_security_error(ex, -1, 0, "No participant data provided");
00619 return Failure;
00620 }
00621
00622 HandshakeDataPair handshake_data = make_handshake_pair(initiator_identity_handle, replier_identity_handle);
00623
00624 if (! handshake_data.first) {
00625 set_security_error(ex, -1, 0, "Unknown local participant");
00626 return DDS::Security::VALIDATION_FAILED;
00627 }
00628
00629 if (! handshake_data.second) {
00630 set_security_error(ex, -1, 0, "Unknown remote participant");
00631 return DDS::Security::VALIDATION_FAILED;
00632 }
00633
00634 LocalParticipantData& local_data = *(handshake_data.first);
00635 RemoteParticipantData& remote_data = *(handshake_data.second);
00636
00637 DDS::Security::HandshakeMessageToken message_data_in(request_token);
00638 TokenReader message_in(message_data_in);
00639 if (message_in.is_nil()) {
00640 set_security_error(ex, -1, 0, "Handshake_message_out is an inout param and must not be nil");
00641 return Failure;
00642
00643 }
00644 challenge1 = message_in.get_bin_property_value("challenge1");
00645
00646 TokenReader initiator_remote_auth_request(remote_data.remote_auth_request);
00647 if (! initiator_remote_auth_request.is_nil()) {
00648 const DDS::OctetSeq& future_challenge = initiator_remote_auth_request.get_bin_property_value("future_challenge");
00649
00650 if (! challenges_match(challenge1, future_challenge)) {
00651 return Failure;
00652 }
00653 }
00654
00655 const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
00656
00657 const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
00658 if (cid.length() > 0) {
00659
00660 remote_cert->deserialize(cid);
00661 if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
00662 {
00663 set_security_error(ex, -1, 0, "Certificate validation failed");
00664 return Failure;
00665 }
00666
00667 } else {
00668 set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
00669 return Failure;
00670 }
00671
00672
00673
00674 const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
00675
00676 std::vector<unsigned char> hash;
00677 if (0 != remote_cert->subject_name_digest(hash)) {
00678 set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
00679 return Failure;
00680 }
00681
00682 if (! validate_topic_data_guid(cpdata, hash, ex)) {
00683 return Failure;
00684 }
00685
00686 cperm = message_in.get_bin_property_value("c.perm");
00687
00688 const DDS::OctetSeq& dh_algo = message_in.get_bin_property_value("c.kagree_algo");
00689 diffie_hellman.reset(SSL::DiffieHellman::factory(dh_algo));
00690
00691
00692
00693 {
00694 CredentialHash hash(*remote_cert,
00695 *diffie_hellman,
00696 cpdata,
00697 cperm);
00698 int err = hash(hash_c1);
00699 if (err) {
00700 set_security_error(ex, -1, 0, "Failed to compute hash_c1.");
00701 return Failure;
00702 }
00703 }
00704
00705
00706
00707 {
00708 CredentialHash hash(local_credential_data.get_participant_cert(),
00709 *diffie_hellman,
00710 serialized_local_participant_data,
00711 local_credential_data.get_access_permissions());
00712 int err = hash(hash_c2);
00713 if (err) {
00714 set_security_error(ex, -1, 0, "Failed to compute hash_c2.");
00715 return Failure;
00716 }
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 const DDS::OctetSeq& dh1 = message_in.get_bin_property_value("dh1");
00726
00727 TokenWriter message_out(handshake_message_out, build_class_id(Handshake_Reply_Class_Ext));
00728
00729 message_out.add_bin_property("c.id", local_credential_data.get_participant_cert().original_bytes());
00730 message_out.add_bin_property("c.perm", local_credential_data.get_access_permissions());
00731 message_out.add_bin_property("c.pdata", serialized_local_participant_data);
00732 message_out.add_bin_property("c.dsign_algo", local_credential_data.get_participant_cert().dsign_algo());
00733 message_out.add_bin_property("c.kagree_algo", diffie_hellman->kagree_algo());
00734 message_out.add_bin_property("hash_c2", hash_c2);
00735
00736 diffie_hellman->pub_key(dh2);
00737 message_out.add_bin_property("dh2", dh2);
00738 message_out.add_bin_property("hash_c1", hash_c1);
00739 message_out.add_bin_property("dh1", dh1);
00740 message_out.add_bin_property("challenge1", challenge1);
00741
00742 TokenReader initiator_local_auth_request(remote_data.local_auth_request);
00743 if (! initiator_local_auth_request.is_nil()) {
00744 const DDS::OctetSeq& future_challenge = initiator_local_auth_request.get_bin_property_value("future_challenge");
00745 message_out.add_bin_property("challenge2", future_challenge);
00746 challenge2 = future_challenge;
00747
00748 } else {
00749 int err = SSL::make_nonce_256(challenge2);
00750 if (! err) {
00751 message_out.add_bin_property("challenge2", challenge2);
00752
00753 } else {
00754 set_security_error(ex, -1, 0, "SSL::make_nonce_256 failed.");
00755 return Failure;
00756 }
00757 }
00758
00759 DDS::BinaryPropertySeq sign_these;
00760 make_reply_signature_sequence(hash_c2,
00761 challenge2,
00762 dh2,
00763 challenge1,
00764 dh1,
00765 hash_c1,
00766 sign_these);
00767
00768 DDS::OctetSeq signature;
00769 SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), signature);
00770 message_out.add_bin_property("signature", signature);
00771
00772 remote_data.replier_identity = replier_identity_handle;
00773 remote_data.initiator_identity = initiator_identity_handle;
00774 remote_data.state = DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE;
00775 remote_data.diffie_hellman = DCPS::move(diffie_hellman);
00776 remote_data.certificate = DCPS::move(remote_cert);
00777 remote_data.c_perm = cperm;
00778 remote_data.reply = handshake_message_out;
00779 remote_data.request = request_token;
00780 remote_data.hash_c1 = hash_c1;
00781 remote_data.hash_c2 = hash_c2;
00782
00783 handshake_handle = get_next_handle();
00784 {
00785 ACE_Guard<ACE_Thread_Mutex> guard(handshake_mutex_);
00786 handshake_data_[handshake_handle] = handshake_data;
00787 }
00788
00789 return Pending;
00790 }
00791
00792 ::DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_handshake(
00793 ::DDS::Security::HandshakeMessageToken & handshake_message_out,
00794 const ::DDS::Security::HandshakeMessageToken & handshake_message_in,
00795 ::DDS::Security::HandshakeHandle handshake_handle,
00796 ::DDS::Security::SecurityException & ex)
00797 {
00798
00799 DDS::Security::ValidationResult_t result = DDS::Security::VALIDATION_OK;
00800
00801
00802 std::string incoming_class_ext = get_extension(handshake_message_in.class_id);
00803
00804 if (0 == Handshake_Reply_Class_Ext.compare(incoming_class_ext))
00805 {
00806 result = process_handshake_reply(handshake_message_out, handshake_message_in, handshake_handle, ex);
00807 }
00808 else if (0 == Handshake_Final_Class_Ext.compare(incoming_class_ext))
00809 {
00810 result = process_final_handshake(handshake_message_in, handshake_handle, ex);
00811 }
00812
00813 return result;
00814 }
00815
00816 ::DDS::Security::SharedSecretHandle* AuthenticationBuiltInImpl::get_shared_secret(
00817 ::DDS::Security::HandshakeHandle handshake_handle,
00818 ::DDS::Security::SecurityException & ex)
00819 {
00820 using namespace DDS::Security;
00821
00822 SharedSecretHandle* result = 0;
00823
00824 ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
00825
00826 HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
00827 if (handshake_data.first && handshake_data.second) {
00828
00829 ValidationResult_t state = handshake_data.second->state;
00830 if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
00831 SharedSecretHandle_var handle = handshake_data.second->shared_secret;
00832 result = handle._retn();
00833
00834 } else {
00835 set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
00836 }
00837
00838 } else {
00839 set_security_error(ex, -1, 0, "Unknown handshake handle");
00840 }
00841
00842 return result;
00843 }
00844
00845 ::CORBA::Boolean AuthenticationBuiltInImpl::get_authenticated_peer_credential_token(
00846 ::DDS::Security::AuthenticatedPeerCredentialToken & peer_credential_token,
00847 ::DDS::Security::HandshakeHandle handshake_handle,
00848 ::DDS::Security::SecurityException & ex)
00849 {
00850 using namespace DDS::Security;
00851 ::CORBA::Boolean result = false;
00852
00853 ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
00854
00855 HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
00856 if (handshake_data.first && handshake_data.second) {
00857 ValidationResult_t state = handshake_data.second->state;
00858 if (state == VALIDATION_OK || state == VALIDATION_OK_FINAL_MESSAGE) {
00859 OpenDDS::Security::TokenWriter peer_token(peer_credential_token, Auth_Peer_Cred_Token_Class_Id);
00860
00861 DDS::BinaryPropertySeq& props = peer_credential_token.binary_properties;
00862 props.length(2);
00863
00864 DDS::BinaryProperty_t p1;
00865 p1.name = "c.id";
00866 p1.value = handshake_data.second->certificate->original_bytes();
00867 p1.propagate = true;
00868
00869 DDS::BinaryProperty_t p2;
00870 p2.name = "c.perm";
00871 p2.value = handshake_data.second->c_perm;
00872 p2.propagate = true;
00873
00874 props[0] = p1;
00875 props[1] = p2;
00876
00877 result = true;
00878
00879 } else {
00880 set_security_error(ex, -1, 0, "Validation state must be either VALIDATION_OK or VALIDATION_OK_FINAL_MESSAGE");
00881 }
00882
00883 } else {
00884 set_security_error(ex, -1, 0, "Unknown handshake handle");
00885 }
00886
00887 return result;
00888 }
00889
00890 ::CORBA::Boolean AuthenticationBuiltInImpl::set_listener(
00891 ::DDS::Security::AuthenticationListener_ptr listener,
00892 ::DDS::Security::SecurityException & ex)
00893 {
00894 ::CORBA::Boolean results = false;
00895
00896 if (NULL == listener) {
00897 set_security_error(ex, -1, 0, "Null listener provided");
00898 } else {
00899 results = true;
00900 listener_ptr_ = listener;
00901 }
00902 return results;
00903 }
00904
00905 ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_token(
00906 const ::DDS::Security::IdentityToken & token,
00907 ::DDS::Security::SecurityException & ex)
00908 {
00909
00910 ACE_UNUSED_ARG(token);
00911 ACE_UNUSED_ARG(ex);
00912 return true;
00913 }
00914
00915
00916 ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_status_token(
00917 const ::DDS::Security::IdentityStatusToken & token,
00918 ::DDS::Security::SecurityException & ex)
00919 {
00920
00921 ACE_UNUSED_ARG(token);
00922 ACE_UNUSED_ARG(ex);
00923 return true;
00924 }
00925
00926
00927 ::CORBA::Boolean AuthenticationBuiltInImpl::return_authenticated_peer_credential_token(
00928 const ::DDS::Security::AuthenticatedPeerCredentialToken & peer_credential_token,
00929 ::DDS::Security::SecurityException & ex)
00930 {
00931
00932 ACE_UNUSED_ARG(peer_credential_token);
00933 ACE_UNUSED_ARG(ex);
00934 return true;
00935 }
00936
00937 ::CORBA::Boolean AuthenticationBuiltInImpl::return_handshake_handle(
00938 ::DDS::Security::HandshakeHandle handshake_handle,
00939 ::DDS::Security::SecurityException & ex)
00940 {
00941 ACE_Guard<ACE_Thread_Mutex> guard(handshake_mutex_);
00942
00943 HandshakeDataMap::iterator found = handshake_data_.find(handshake_handle);
00944 if (found != handshake_data_.end()) {
00945 handshake_data_.erase(found);
00946 return true;
00947 }
00948
00949 set_security_error(ex, -1, 0, "Handshake handle not recognized");
00950 return false;
00951 }
00952
00953 ::CORBA::Boolean AuthenticationBuiltInImpl::return_identity_handle(
00954 ::DDS::Security::IdentityHandle identity_handle,
00955 ::DDS::Security::SecurityException & ex)
00956 {
00957 ACE_Guard<ACE_Thread_Mutex> guard(identity_mutex_);
00958
00959 LocalParticipantMap::iterator local = local_participants_.find(identity_handle);
00960 if (local != local_participants_.end()) {
00961 local_participants_.erase(local);
00962 return true;
00963 }
00964
00965 local = std::find_if(local_participants_.begin(), local_participants_.end(),
00966 local_has_remote_handle(identity_handle));
00967
00968 if (local != local_participants_.end()) {
00969 local->second->validated_remotes.erase(identity_handle);
00970 return true;
00971 }
00972
00973 set_security_error(ex, -1, 0, "Identity handle not recognized");
00974 return false;
00975 }
00976
00977 ::CORBA::Boolean AuthenticationBuiltInImpl::return_sharedsecret_handle(
00978 ::DDS::Security::SharedSecretHandle* sharedsecret_handle,
00979 ::DDS::Security::SecurityException & ex)
00980 {
00981
00982 ACE_UNUSED_ARG(sharedsecret_handle);
00983 ACE_UNUSED_ARG(ex);
00984 return true;
00985 }
00986
00987
00988 DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_handshake_reply(
00989 DDS::Security::HandshakeMessageToken & handshake_message_out,
00990 const DDS::Security::HandshakeMessageToken & handshake_message_in,
00991 DDS::Security::HandshakeHandle handshake_handle,
00992 DDS::Security::SecurityException & ex)
00993 {
00994
00995 ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
00996 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
00997
00998 DDS::OctetSeq challenge1, hash_c2;
00999 SSL::Certificate::unique_ptr remote_cert(new SSL::Certificate);
01000
01001 const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED;
01002 const DDS::Security::ValidationResult_t FinalMessage = DDS::Security::VALIDATION_OK_FINAL_MESSAGE;
01003
01004 HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
01005 if (!handshake_data.first || !handshake_data.second) {
01006 set_security_error(ex, -1, 0, "Unknown handshake handle");
01007 return Failure;
01008 }
01009
01010 LocalParticipantData& local_data = *(handshake_data.first);
01011 RemoteParticipantData& remote_data = *(handshake_data.second);
01012
01013 if (remote_data.state != DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE) {
01014 set_security_error(ex, -1, 0, "Handshake state is not valid");
01015 return Failure;
01016 }
01017
01018 TokenReader message_in(handshake_message_in);
01019 if (message_in.is_nil()) {
01020 set_security_error(ex, -1, 0, "Handshake_message_in must not be nil");
01021 return Failure;
01022 }
01023
01024 const DDS::OctetSeq& challenge2 = message_in.get_bin_property_value("challenge2");
01025
01026 TokenReader auth_wrapper(remote_data.remote_auth_request);
01027 if (! auth_wrapper.is_nil()) {
01028 const DDS::OctetSeq& future_challenge = auth_wrapper.get_bin_property_value("future_challenge");
01029
01030 if (! challenges_match(challenge2, future_challenge)) {
01031 set_security_error(ex, -1, 0, "challenge2 does not match future_challenge");
01032 return Failure;
01033 }
01034 }
01035
01036 const LocalAuthCredentialData& local_credential_data = *(local_data.credentials);
01037
01038 const DDS::OctetSeq& cid = message_in.get_bin_property_value("c.id");
01039 if (cid.length() > 0) {
01040
01041 remote_cert->deserialize(cid);
01042
01043 if (X509_V_OK != remote_cert->validate(local_credential_data.get_ca_cert()))
01044 {
01045 set_security_error(ex, -1, 0, "Certificate validation failed");
01046 return Failure;
01047 }
01048
01049 } else {
01050 set_security_error(ex, -1, 0, "Certificate validation failed due to empty 'c.id' property supplied");
01051 return Failure;
01052 }
01053
01054
01055
01056 TokenReader handshake_request_token(remote_data.request);
01057 if (handshake_request_token.is_nil()) {
01058 set_security_error(ex, -1, 0, "Handshake-request-token is nil");
01059 return Failure;
01060
01061 } else {
01062 challenge1 = handshake_request_token.get_bin_property_value("challenge1");
01063 const DDS::OctetSeq& challenge1_reply = message_in.get_bin_property_value("challenge1");
01064
01065 if (! challenges_match(challenge1, challenge1_reply)) {
01066 set_security_error(ex, -1, 0, "handshake-request challenge1 value does not match local challenge1");
01067 return Failure;
01068 }
01069 }
01070
01071
01072
01073 const DDS::OctetSeq& cpdata = message_in.get_bin_property_value("c.pdata");
01074
01075 std::vector<unsigned char> hash;
01076 if (0 != remote_cert->subject_name_digest(hash)) {
01077 set_security_error(ex, -1, 0, "Failed to generate subject-name digest from remote certificate.");
01078 return Failure;
01079 }
01080
01081 if (! validate_topic_data_guid(cpdata, hash, ex)) {
01082 return Failure;
01083 }
01084
01085
01086
01087 const DDS::OctetSeq& dh2 = message_in.get_bin_property_value("dh2");
01088 if (0 != remote_data.diffie_hellman->gen_shared_secret(dh2)) {
01089 set_security_error(ex, -1, 0, "Failed to generate shared secret from dh1 and dh2");
01090 return Failure;
01091 }
01092
01093 const DDS::OctetSeq& cperm = message_in.get_bin_property_value("c.perm");
01094
01095
01096
01097 {
01098 CredentialHash hash(*remote_cert,
01099 *remote_data.diffie_hellman,
01100 cpdata,
01101 cperm);
01102 int err = hash(hash_c2);
01103 if (err) {
01104 set_security_error(ex, -1, 0, "Computing hash_c2 failed");
01105 return Failure;
01106 }
01107 }
01108
01109
01110 const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
01111
01112 DDS::BinaryPropertySeq verify_these;
01113 make_reply_signature_sequence(hash_c2,
01114 challenge2,
01115 dh2,
01116 challenge1,
01117 dh1,
01118 remote_data.hash_c1,
01119 verify_these);
01120
01121 const DDS::OctetSeq& remote_signature = message_in.get_bin_property_value("signature");
01122
01123 int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
01124 if (err) {
01125 set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
01126 return Failure;
01127 }
01128
01129 OpenDDS::Security::TokenWriter final_msg(handshake_message_out, build_class_id(Handshake_Final_Class_Ext));
01130
01131 final_msg.add_bin_property("hash_c1", remote_data.hash_c1);
01132 final_msg.add_bin_property("hash_c2", hash_c2);
01133 final_msg.add_bin_property("dh1", dh1);
01134 final_msg.add_bin_property("dh2", dh2);
01135 final_msg.add_bin_property("challenge1", challenge1);
01136 final_msg.add_bin_property("challenge2", challenge2);
01137
01138 DDS::BinaryPropertySeq sign_these;
01139 make_final_signature_sequence(remote_data.hash_c1,
01140 challenge1,
01141 dh1,
01142 challenge2,
01143 dh2,
01144 hash_c2,
01145 sign_these);
01146
01147 DDS::OctetSeq tmp;
01148 SSL::sign_serialized(sign_these, local_credential_data.get_participant_private_key(), tmp);
01149 final_msg.add_bin_property("signature", tmp);
01150
01151 remote_data.certificate = DCPS::move(remote_cert);
01152 remote_data.state = FinalMessage;
01153 remote_data.c_perm = message_in.get_bin_property_value("c.perm");
01154 remote_data.hash_c2 = hash_c2;
01155 remote_data.shared_secret = new SharedSecret(challenge1,
01156 challenge2,
01157 remote_data.diffie_hellman->get_shared_secret());
01158 return FinalMessage;
01159 }
01160
01161 bool challenges_match(const DDS::OctetSeq& c1, const DDS::OctetSeq& c2)
01162 {
01163 if ((c1.length()) < 1 || (c2.length() < 1)) {
01164 return false;
01165 }
01166 if (c1.length() != c2.length()) {
01167 return false;
01168 }
01169
01170 if (0 != std::memcmp(c1.get_buffer(), c2.get_buffer(), c2.length())) {
01171 return false;
01172 }
01173
01174 return true;
01175 }
01176
01177 DDS::Security::ValidationResult_t AuthenticationBuiltInImpl::process_final_handshake(
01178 const DDS::Security::HandshakeMessageToken & handshake_message_in,
01179 DDS::Security::HandshakeHandle handshake_handle,
01180 DDS::Security::SecurityException & ex)
01181 {
01182 const DDS::Security::ValidationResult_t Failure = DDS::Security::VALIDATION_FAILED;
01183 const DDS::Security::ValidationResult_t ValidationOkay = DDS::Security::VALIDATION_OK;
01184
01185 ACE_Guard<ACE_Thread_Mutex> handshake_data_guard(handshake_mutex_);
01186 ACE_Guard<ACE_Thread_Mutex> identity_data_guard(identity_mutex_);
01187
01188 HandshakeDataPair handshake_data = get_handshake_data(handshake_handle);
01189 if (!handshake_data.first || !handshake_data.second) {
01190 set_security_error(ex, -1, 0, "Unknown handshake handle");
01191 return Failure;
01192 }
01193
01194 RemoteParticipantData& remote_data = *(handshake_data.second);
01195
01196 if (remote_data.state != DDS::Security::VALIDATION_PENDING_HANDSHAKE_MESSAGE) {
01197 set_security_error(ex, -1, 0, "Handshake state is not valid");
01198 return Failure;
01199 }
01200
01201
01202
01203 TokenReader handshake_final_token(handshake_message_in);
01204 if (handshake_final_token.is_nil()) {
01205 set_security_error(ex, -1, 0, "Handshake-final-token is nil");
01206 return Failure;
01207 }
01208
01209 TokenReader handshake_reply_token(remote_data.reply);
01210 if (handshake_reply_token.is_nil()) {
01211 set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
01212 return Failure;
01213 }
01214
01215
01216 TokenReader handshake_request_token(remote_data.request);
01217 if (handshake_reply_token.is_nil()) {
01218 set_security_error(ex, -1, 0, "Handshake-reply-token is nil");
01219 return Failure;
01220 }
01221
01222 const DDS::OctetSeq& dh1 = handshake_request_token.get_bin_property_value("dh1");
01223 const DDS::OctetSeq& dh2 = handshake_reply_token.get_bin_property_value("dh2");
01224
01225 const DDS::OctetSeq& challenge1_reply = handshake_reply_token.get_bin_property_value("challenge1");
01226 const DDS::OctetSeq& challenge2_reply = handshake_reply_token.get_bin_property_value("challenge2");
01227
01228 const DDS::OctetSeq& challenge1_final = handshake_final_token.get_bin_property_value("challenge1");
01229 const DDS::OctetSeq& challenge2_final = handshake_final_token.get_bin_property_value("challenge2");
01230
01231 if (! challenges_match(challenge1_reply, challenge1_final) || ! challenges_match(challenge2_reply, challenge2_final)) {
01232 return Failure;
01233 }
01234
01235
01236
01237 const SSL::Certificate::unique_ptr& remote_cert = remote_data.certificate;
01238
01239 DDS::BinaryPropertySeq verify_these;
01240 make_final_signature_sequence(remote_data.hash_c1,
01241 challenge1_reply,
01242 dh1,
01243 challenge2_reply,
01244 dh2,
01245 remote_data.hash_c2,
01246 verify_these);
01247
01248 const DDS::OctetSeq& remote_signature = handshake_final_token.get_bin_property_value("signature");
01249
01250 int err = SSL::verify_serialized(verify_these, *remote_cert, remote_signature);
01251 if (err) {
01252 set_security_error(ex, -1, 0, "Remote 'signature' field failed signature verification");
01253 return Failure;
01254 }
01255
01256
01257
01258 if (0 != remote_data.diffie_hellman->gen_shared_secret(dh1)) {
01259 set_security_error(ex, -1, 0, "Failed to generate shared secret from dh2 and dh1");
01260 return Failure;
01261 }
01262
01263 remote_data.state = DDS::Security::VALIDATION_OK;
01264 remote_data.shared_secret = new SharedSecret(challenge1_reply,
01265 challenge2_reply,
01266 remote_data.diffie_hellman->get_shared_secret());
01267
01268 return ValidationOkay;
01269 }
01270
01271 AuthenticationBuiltInImpl::LocalParticipantData::shared_ptr
01272 AuthenticationBuiltInImpl::get_local_participant(DDS::Security::IdentityHandle handle)
01273 {
01274 LocalParticipantMap::iterator found = local_participants_.find(handle);
01275 if (found != local_participants_.end()) {
01276 return found->second;
01277 }
01278
01279 return LocalParticipantData::shared_ptr();
01280 }
01281
01282 AuthenticationBuiltInImpl::HandshakeDataPair
01283 AuthenticationBuiltInImpl::get_handshake_data(DDS::Security::HandshakeHandle handle)
01284 {
01285 HandshakeDataMap::iterator found = handshake_data_.find(handle);
01286 if (found != handshake_data_.end()) {
01287 return found->second;
01288 }
01289
01290 return HandshakeDataPair();
01291 }
01292
01293 AuthenticationBuiltInImpl::HandshakeDataPair
01294 AuthenticationBuiltInImpl::make_handshake_pair(DDS::Security::IdentityHandle h1,
01295 DDS::Security::IdentityHandle h2)
01296 {
01297 DDS::Security::IdentityHandle other = DDS::HANDLE_NIL;
01298
01299 LocalParticipantMap::iterator found_local = local_participants_.find(h1);
01300 if (found_local != local_participants_.end()) {
01301 other = h2;
01302
01303 } else {
01304 found_local = local_participants_.find(h2);
01305 if (found_local != local_participants_.end()) {
01306 other = h1;
01307
01308 } else {
01309 return HandshakeDataPair();
01310 }
01311 }
01312
01313 RemoteParticipantMap::iterator found_remote = found_local->second->validated_remotes.find(other);
01314 if (found_remote != found_local->second->validated_remotes.end()) {
01315 return std::make_pair(found_local->second, found_remote->second);
01316 }
01317
01318 return HandshakeDataPair();
01319 }
01320
01321 bool AuthenticationBuiltInImpl::is_handshake_initiator(const OpenDDS::DCPS::GUID_t& local, const OpenDDS::DCPS::GUID_t& remote)
01322 {
01323 const unsigned char* local_ = reinterpret_cast<const unsigned char*>(&local);
01324 const unsigned char* remote_ = reinterpret_cast<const unsigned char*>(&remote);
01325
01326
01327 return std::lexicographical_compare(local_, local_ + sizeof(local),
01328 remote_, remote_ + sizeof(remote));
01329
01330 }
01331
01332 bool AuthenticationBuiltInImpl::check_class_versions(const char* remote_class_id)
01333 {
01334 if (NULL == remote_class_id) {
01335 return false;
01336 }
01337 bool class_matches = false;
01338
01339
01340 std::string class_id_str(remote_class_id);
01341
01342
01343 size_t colon_pos = class_id_str.find_last_of(':');
01344 if (std::string::npos != colon_pos && colon_pos > 0) {
01345
01346 std::string remote_class_name = class_id_str.substr(0, colon_pos);
01347 if (0 == Auth_Plugin_Name.compare(remote_class_name)) {
01348
01349 size_t major_start = colon_pos + 1;
01350 size_t period_pos = class_id_str.find_first_of('.', major_start);
01351 if (std::string::npos != period_pos && period_pos > major_start) {
01352 std::string major_version = class_id_str.substr(major_start, period_pos - major_start);
01353 if (0 == Auth_Plugin_Major_Version.compare(major_version)) {
01354 class_matches = true;
01355 }
01356 }
01357 }
01358 }
01359
01360 return class_matches;
01361 }
01362
01363 std::string AuthenticationBuiltInImpl::build_class_id(const std::string& message_ext)
01364 {
01365 std::stringstream class_id_stream;
01366 class_id_stream << Auth_Plugin_Name
01367 << ":" << Auth_Plugin_Major_Version
01368 << "." << Auth_Plugin_Minor_Version
01369 << "+" << message_ext;
01370
01371 return class_id_stream.str();
01372 }
01373
01374 std::string AuthenticationBuiltInImpl::get_extension(const char* class_id)
01375 {
01376 std::string ext_string("");
01377
01378 std::string class_id_str(class_id);
01379 size_t extension_delim_pos = class_id_str.find_last_of('+');
01380 if (extension_delim_pos != std::string::npos) {
01381 size_t start_ext_pos = extension_delim_pos + 1;
01382 if (start_ext_pos < class_id_str.length()) {
01383 ext_string = class_id_str.substr(start_ext_pos);
01384 }
01385 }
01386
01387 return ext_string;
01388 }
01389
01390 CORBA::Long AuthenticationBuiltInImpl::get_next_handle()
01391 {
01392 ACE_Guard<ACE_Thread_Mutex> guard(handle_mutex_);
01393 return CommonUtilities::increment_handle(next_handle_);
01394 }
01395
01396 }
01397 }
01398
01399 OPENDDS_END_VERSIONED_NAMESPACE_DECL