diff options
author | Jacob Keeler <jacob.keeler@livioradio.com> | 2018-06-18 12:01:38 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-18 12:01:38 -0700 |
commit | 9c6a43aad481a1b45a50ccc40b456bb168989f47 (patch) | |
tree | cf21b340a414c183d92c733091e159390186022b /src/components/protocol_handler | |
parent | 28c8a64c67b137508bfc1b9ec35b6723fae992db (diff) | |
parent | 24edd97c1f2b4fc67eb882245cd865939b075c6f (diff) | |
download | sdl_core-9c6a43aad481a1b45a50ccc40b456bb168989f47.tar.gz |
Merge branch 'develop' into feat/mt_transport_changes
Diffstat (limited to 'src/components/protocol_handler')
8 files changed, 128 insertions, 37 deletions
diff --git a/src/components/protocol_handler/include/protocol_handler/handshake_handler.h b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h index 020754608b..5b62a54c22 100644 --- a/src/components/protocol_handler/include/protocol_handler/handshake_handler.h +++ b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h @@ -91,6 +91,12 @@ class HandshakeHandler : public security_manager::SecurityManagerListener { security_manager::SSLContext::HandshakeResult result) OVERRIDE; /** + * @brief Notification about handshake failure + * @return true on success notification handling or false otherwise + */ + bool OnHandshakeFailed() OVERRIDE; + + /** * @brief Notification that certificate update is required. */ void OnCertificateUpdateRequired() OVERRIDE; diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h index d5f498df6d..765260c675 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h @@ -267,6 +267,8 @@ class ProtocolHandlerImpl uint8_t session_id, uint8_t service_type); + void NotifyOnFailedHandshake() OVERRIDE; + // TODO(Ezamakhov): move Ack/Nack as interface for StartSessionHandler /** * \brief Sends acknowledgement of starting session to mobile application @@ -790,7 +792,9 @@ class ProtocolHandlerImpl bool is_ptu_triggered_; std::list<std::shared_ptr<HandshakeHandler> > ptu_pending_handlers_; + std::list<std::shared_ptr<HandshakeHandler> > handshake_handlers_; sync_primitives::Lock ptu_handlers_lock_; + sync_primitives::Lock handshake_handlers_lock_; #endif // ENABLE_SECURITY // Thread that pumps non-parsed messages coming from mobile side. diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_packet.h b/src/components/protocol_handler/include/protocol_handler/protocol_packet.h index e5b1e3360d..d3e3ec5809 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_packet.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_packet.h @@ -252,6 +252,12 @@ class ProtocolPacket { const size_t messageSize); /** + * @brief Calculates FIRST_FRAME data for further handling of consecutive + * frames + */ + void HandleRawFirstFrameData(const uint8_t* message); + + /** * \brief Getter of protocol version. */ uint8_t protocol_version() const; diff --git a/src/components/protocol_handler/src/handshake_handler.cc b/src/components/protocol_handler/src/handshake_handler.cc index 46b80db29e..2fc229cb1b 100644 --- a/src/components/protocol_handler/src/handshake_handler.cc +++ b/src/components/protocol_handler/src/handshake_handler.cc @@ -94,6 +94,18 @@ bool HandshakeHandler::GetPolicyCertificateData(std::string& data) const { void HandshakeHandler::OnCertificateUpdateRequired() {} +bool HandshakeHandler::OnHandshakeFailed() { + BsonObject params; + if (payload_) { + params = bson_object_from_bytes(payload_.get()); + } else { + bson_object_initialize_default(¶ms); + } + ProcessFailedHandshake(params); + bson_object_deinitialize(¶ms); + return true; +} + bool HandshakeHandler::OnHandshakeDone( uint32_t connection_key, security_manager::SSLContext::HandshakeResult result) { diff --git a/src/components/protocol_handler/src/multiframe_builder.cc b/src/components/protocol_handler/src/multiframe_builder.cc index 5a1fc6d205..cf8a23ddc1 100644 --- a/src/components/protocol_handler/src/multiframe_builder.cc +++ b/src/components/protocol_handler/src/multiframe_builder.cc @@ -91,6 +91,8 @@ bool MultiFrameBuilder::RemoveConnection(const ConnectionID connection_id) { ProtocolFramePtrList MultiFrameBuilder::PopMultiframes() { LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_DEBUG(logger_, "Current state is: " << multiframes_map_); + LOG4CXX_DEBUG(logger_, + "Current multiframe map size is: " << multiframes_map_.size()); ProtocolFramePtrList outpute_frame_list; for (MultiFrameMap::iterator connection_it = multiframes_map_.begin(); connection_it != multiframes_map_.end(); diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index 04a7237e45..d74348b32d 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -152,6 +152,7 @@ ProtocolHandlerImpl::~ProtocolHandlerImpl() { "Not all observers have unsubscribed" " from ProtocolHandlerImpl"); } + handshake_handlers_.clear(); } void ProtocolHandlerImpl::AddProtocolObserver(ProtocolObserver* observer) { @@ -1091,6 +1092,11 @@ void ProtocolHandlerImpl::OnUnexpectedDisconnect( OnConnectionClosed(connection_id); } +void ProtocolHandlerImpl::NotifyOnFailedHandshake() { + LOG4CXX_AUTO_TRACE(logger_); + security_manager_->NotifyListenersOnHandshakeFailed(); +} + void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { LOG4CXX_AUTO_TRACE(logger_); @@ -1103,12 +1109,14 @@ void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { return; } - const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired(); for (auto handler : ptu_pending_handlers_) { + const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired( + handler->connection_key()); security_manager::SSLContext* ssl_context = - is_cert_expired - ? NULL - : security_manager_->CreateSSLContext(handler->connection_key()); + is_cert_expired ? NULL + : security_manager_->CreateSSLContext( + handler->connection_key(), + security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); @@ -1623,7 +1631,8 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( session_observer_.KeyFromPair(connection_id, session_id); security_manager::SSLContext* ssl_context = - security_manager_->CreateSSLContext(connection_key); + security_manager_->CreateSSLContext( + connection_key, security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -1753,11 +1762,11 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( } #ifdef ENABLE_SECURITY + const uint8_t protocol_version = packet->protocol_version(); const bool protection = - // Protocol version 1 is not support protection - (packet->protocol_version() > PROTOCOL_VERSION_1) - ? packet->protection_flag() - : false; + // Protocol version 1 does not support protection + (protocol_version > PROTOCOL_VERSION_1) ? packet->protection_flag() + : false; #else const bool protection = false; #endif // ENABLE_SECURITY @@ -1950,14 +1959,11 @@ void ProtocolHandlerImpl::NotifySessionStarted( context, packet->protocol_version(), bson_object_bytes); + handshake_handlers_.push_back(handler); const bool is_certificate_empty = security_manager_->IsPolicyCertificateDataEmpty(); - const bool is_certificate_expired = - is_certificate_empty || - security_manager_->IsCertificateUpdateRequired(); - if (context.is_ptu_required_ && is_certificate_empty) { LOG4CXX_DEBUG(logger_, "PTU for StartSessionHandler " @@ -1973,6 +1979,7 @@ void ProtocolHandlerImpl::NotifySessionStarted( ptu_pending_handlers_.push_back(handler); is_ptu_triggered_ = true; security_manager_->NotifyOnCertificateUpdateRequired(); + security_manager_->PostponeHandshake(connection_key); } else { LOG4CXX_DEBUG(logger_, "PTU has been triggered. Added to pending."); ptu_pending_handlers_.push_back(handler); @@ -1981,9 +1988,11 @@ void ProtocolHandlerImpl::NotifySessionStarted( } security_manager::SSLContext* ssl_context = - is_certificate_expired + is_certificate_empty ? NULL - : security_manager_->CreateSSLContext(connection_key); + : security_manager_->CreateSSLContext( + connection_key, + security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -2017,12 +2026,27 @@ void ProtocolHandlerImpl::NotifySessionStarted( *fullVersion, *start_session_ack_params); } else { - security_manager_->AddListener(new HandshakeHandler(*handler)); + LOG4CXX_DEBUG(logger_, + "Adding Handshake handler to listeners: " << handler.get()); + security_manager::SecurityManagerListener* listener = + new HandshakeHandler(*handler); + security_manager_->AddListener(listener); + if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); + + if (!security_manager_->IsSystemTimeProviderReady()) { + security_manager_->RemoveListener(listener); + SendStartSessionNAck(context.connection_id_, + packet->session_id(), + protocol_version, + packet->service_type(), + rejected_params); + } } } + LOG4CXX_DEBUG(logger_, "Protection establishing for connection " << connection_key << " is in progress"); @@ -2075,6 +2099,7 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageHeartBeat( } void ProtocolHandlerImpl::PopValideAndExpirateMultiframes() { + LOG4CXX_AUTO_TRACE(logger_); const ProtocolFramePtrList& frame_list = multiframe_builder_.PopMultiframes(); for (ProtocolFramePtrList::const_iterator it = frame_list.begin(); it != frame_list.end(); @@ -2321,6 +2346,11 @@ RESULT_CODE ProtocolHandlerImpl::DecryptFrame(ProtocolFramePtr packet) { << out_data_size << " bytes"); DCHECK(out_data); DCHECK(out_data_size); + // Special handling for decrypted FIRST_FRAME + if (packet->frame_type() == FRAME_TYPE_FIRST && packet->protection_flag()) { + packet->HandleRawFirstFrameData(out_data); + return RESULT_OK; + } packet->set_data(out_data, out_data_size); return RESULT_OK; } diff --git a/src/components/protocol_handler/src/protocol_packet.cc b/src/components/protocol_handler/src/protocol_packet.cc index 065fd97aa0..3cd9e7f781 100644 --- a/src/components/protocol_handler/src/protocol_packet.cc +++ b/src/components/protocol_handler/src/protocol_packet.cc @@ -524,6 +524,17 @@ bool ProtocolPacket::operator==(const ProtocolPacket& other) const { return false; } +void ProtocolPacket::HandleRawFirstFrameData(const uint8_t* message) { + LOG4CXX_AUTO_TRACE(logger_); + payload_size_ = 0; + const uint8_t* data = message; + uint32_t total_data_bytes = data[0] << 24; + total_data_bytes |= data[1] << 16; + total_data_bytes |= data[2] << 8; + total_data_bytes |= data[3]; + set_total_data_bytes(total_data_bytes); +} + RESULT_CODE ProtocolPacket::deserializePacket(const uint8_t* message, const size_t messageSize) { LOG4CXX_AUTO_TRACE(logger_); @@ -536,18 +547,15 @@ RESULT_CODE ProtocolPacket::deserializePacket(const uint8_t* message, packet_data_.totalDataBytes = packet_header_.dataSize; uint32_t dataPayloadSize = 0; - if ((offset < messageSize) && packet_header_.frameType != FRAME_TYPE_FIRST) { + if ((offset < messageSize)) { dataPayloadSize = messageSize - offset; } - if (packet_header_.frameType == FRAME_TYPE_FIRST) { + if (packet_header_.frameType == FRAME_TYPE_FIRST && + !packet_header_.protection_flag) { payload_size_ = 0; const uint8_t* data = message + offset; - uint32_t total_data_bytes = data[0] << 24; - total_data_bytes |= data[1] << 16; - total_data_bytes |= data[2] << 8; - total_data_bytes |= data[3]; - set_total_data_bytes(total_data_bytes); + HandleRawFirstFrameData(data); if (0 == packet_data_.data) { return RESULT_FAIL; } @@ -606,6 +614,8 @@ uint8_t* ProtocolPacket::data() const { } void ProtocolPacket::set_total_data_bytes(size_t dataBytes) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Data bytes : " << dataBytes); if (dataBytes) { delete[] packet_data_.data; packet_data_.data = new (std::nothrow) uint8_t[dataBytes]; diff --git a/src/components/protocol_handler/test/protocol_handler_tm_test.cc b/src/components/protocol_handler/test/protocol_handler_tm_test.cc index 7b47084c60..b73fbf7f5f 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -46,6 +46,7 @@ #include "security_manager/mock_ssl_context.h" #endif // ENABLE_SECURITY #include "transport_manager/mock_transport_manager.h" +#include "utils/mock_system_time_handler.h" #include "utils/make_shared.h" #include "utils/test_async_waiter.h" #include <bson_object.h> @@ -99,8 +100,12 @@ using protocol_handler::kBulk; using protocol_handler::kInvalidServiceType; // For TM states using transport_manager::TransportManagerListener; +using test::components::security_manager_test::MockSystemTimeHandler; using transport_manager::E_SUCCESS; using transport_manager::DeviceInfo; +// For security +using ContextCreationStrategy = + security_manager::SecurityManager::ContextCreationStrategy; // For CH entities using connection_handler::DeviceHandle; // Google Testing Framework Entities @@ -1011,7 +1016,10 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtected_Fail) { SetProtocolVersion2(); // Expect start protection for unprotected session - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return fail protection WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); @@ -1066,7 +1074,7 @@ TEST_F(ProtocolHandlerImplTest, SetProtocolVersion2(); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1143,7 +1151,7 @@ TEST_F(ProtocolHandlerImplTest, .WillOnce(ReturnRefOfCopy(services)); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce(Return(&ssl_context_mock)); @@ -1222,7 +1230,7 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1320,7 +1328,7 @@ TEST_F( times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1416,7 +1424,10 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return new SSLContext WillOnce( @@ -1444,27 +1455,37 @@ TEST_F(ProtocolHandlerImplTest, // Expect add listener for handshake result EXPECT_CALL(security_manager_mock, AddListener(_)) - // Emulate handshake fail - .WillOnce(Invoke(OnHandshakeDoneFunctor( - connection_key, - security_manager::SSLContext::Handshake_Result_Success))); + // Emulate handshake + .WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + Invoke(OnHandshakeDoneFunctor( + connection_key, + security_manager::SSLContext::Handshake_Result_Success)))); + times++; // Listener check SSLContext EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, start_service)) . // Emulate protection for service is not enabled - WillOnce(ReturnNull()); + WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); + times++; + + EXPECT_CALL(security_manager_mock, IsSystemTimeProviderReady()) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); + times++; - // Expect service protection enable EXPECT_CALL(session_observer_mock, - SetProtectionFlag(connection_key, start_service)); + SetProtectionFlag(connection_key, start_service)) + .WillOnce(NotifyTestAsyncWaiter(&waiter)); + times++; - // Expect send Ack with PROTECTION_OFF (on fail handshake) + // Expect send Ack with PROTECTION_ON (on successfull handshake) EXPECT_CALL(transport_manager_mock, SendMessageToDevice( ControlMessage(FRAME_DATA_START_SERVICE_ACK, PROTECTION_ON))) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; SendControlMessage( |