diff options
30 files changed, 1463 insertions, 771 deletions
diff --git a/src/appMain/life_cycle.cc b/src/appMain/life_cycle.cc index 3bf0e62f87..be1a90d0a4 100644 --- a/src/appMain/life_cycle.cc +++ b/src/appMain/life_cycle.cc @@ -151,6 +151,7 @@ bool LifeCycle::StartComponents() { security_manager_->AddListener(app_manager_); app_manager_->AddPolicyObserver(crypto_manager_); + app_manager_->AddPolicyObserver(protocol_handler_); if (!crypto_manager_->Init()) { LOG4CXX_ERROR(logger_, "CryptoManager initialization fail."); return false; diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index e91bdf5d59..22ae032a00 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -921,15 +921,43 @@ class ApplicationManagerImpl const connection_handler::CloseSessionReason& close_reason) OVERRIDE; #ifdef ENABLE_SECURITY - // Overriden SecurityManagerListener method + /** + * @brief Notification about protection result + * @param connection_key Unique key of session which triggers handshake + * @param result result of connection protection + * @return true on success notification handling or false otherwise + */ bool OnHandshakeDone( uint32_t connection_key, security_manager::SSLContext::HandshakeResult result) OVERRIDE; + /** + * @brief Notification that certificate update is required. + */ void OnCertificateUpdateRequired() OVERRIDE; + /** + * @brief Get certificate data from policy + * @param reference to string where to save certificate data + * @return true if listener saved some data to string otherwise false + */ + bool GetPolicyCertificateData(std::string& data) const OVERRIDE; + + /** + * @brief Get unique handshake context by application id + * @param key id of application + * @return generated handshake context or empty context if application with + * provided id does not exist + */ security_manager::SSLContext::HandshakeContext GetHandshakeContext( uint32_t key) const OVERRIDE; + + /** + * @brief Check if application with specified app_id has NAVIGATION HMI type + * @param app_id id of application to check + * @return true if application is navi otherwise returns false + */ + bool CheckAppIsNavi(const uint32_t app_id) const OVERRIDE; #endif // ENABLE_SECURITY /** diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index eb3313e492..96e8a1314b 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -1655,6 +1655,12 @@ void ApplicationManagerImpl::OnCertificateUpdateRequired() { GetPolicyHandler().OnPTExchangeNeeded(); } +bool ApplicationManagerImpl::GetPolicyCertificateData(std::string& data) const { + LOG4CXX_AUTO_TRACE(logger_); + data = GetPolicyHandler().RetrieveCertificate(); + return true; +} + security_manager::SSLContext::HandshakeContext ApplicationManagerImpl::GetHandshakeContext(uint32_t key) const { LOG4CXX_AUTO_TRACE(logger_); @@ -1666,6 +1672,15 @@ ApplicationManagerImpl::GetHandshakeContext(uint32_t key) const { } return SSLContext::HandshakeContext(); } + +bool ApplicationManagerImpl::CheckAppIsNavi(const uint32_t app_id) const { + LOG4CXX_AUTO_TRACE(logger_); + ApplicationSharedPtr app = application(app_id); + if (app) { + return app->is_navi(); + } + return false; +} #endif // ENABLE_SECURITY void ApplicationManagerImpl::set_hmi_message_handler( diff --git a/src/components/connection_handler/include/connection_handler/connection.h b/src/components/connection_handler/include/connection_handler/connection.h index bd5858c4cd..b0f9586046 100644 --- a/src/components/connection_handler/include/connection_handler/connection.h +++ b/src/components/connection_handler/include/connection_handler/connection.h @@ -76,8 +76,10 @@ struct Service { Service() : service_type(protocol_handler::kInvalidServiceType) , is_protected_(false) {} + explicit Service(protocol_handler::ServiceType service_type) : service_type(service_type), is_protected_(false) {} + bool operator==(const protocol_handler::ServiceType service_type) const { return this->service_type == service_type; } @@ -209,6 +211,17 @@ class Connection { */ void SetProtectionFlag(const uint8_t session_id, const protocol_handler::ServiceType& service_type); + + /** + * @brief Check if session contains service with specified service type + * @param session_id id of session to check + * @param service_type type of service to check + * @return true if session contains service with specified service type + */ + bool SessionServiceExists( + const uint8_t session_id, + const protocol_handler::ServiceType& service_type) const; + #endif // ENABLE_SECURITY /** * @brief Returns map of sessions which have been opened in diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h index c2bac31c1b..120d48917b 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h @@ -212,7 +212,7 @@ class ConnectionHandlerImpl /** * \brief Callback function used by ProtocolHandler * when Mobile Application initiates start of new session. - * Result must be notified through NotifySessionStartedResult(). + * Result must be notified through NotifySessionStartedContext(). * \param connection_handle Connection identifier within which session * has to be started. * \param sessionId Identifier of the session to be start @@ -350,6 +350,16 @@ class ConnectionHandlerImpl const uint32_t& key, const protocol_handler::ServiceType& service_type) OVERRIDE; + /** + * @brief Check if session contains service with specified service type + * @param connection_key unique id of session to check + * @param service_type type of service to check + * @return true if session contains service with specified service type + */ + bool SessionServiceExists( + const uint32_t connection_key, + const protocol_handler::ServiceType& service_type) const OVERRIDE; + security_manager::SSLContext::HandshakeContext GetHandshakeContext( uint32_t key) const OVERRIDE; #endif // ENABLE_SECURITY @@ -530,54 +540,6 @@ class ConnectionHandlerImpl private: /** - * \brief Struct to keep variables between OnSessionStartedCallback() and - * NotifyServiceStartedResult() - **/ - struct ServiceStartedContext { - transport_manager::ConnectionUID connection_handle_; - uint8_t session_id_; - uint32_t new_session_id_; - protocol_handler::ServiceType service_type_; - uint32_t hash_id_; - bool is_protected_; - - /** - * \brief Constructor - */ - ServiceStartedContext() - : connection_handle_(0) - , session_id_(0) - , new_session_id_(0) - , service_type_(protocol_handler::kInvalidServiceType) - , hash_id_(0) - , is_protected_(0) {} - - /** - * \brief Constructor - * \param connection_handle Connection identifier within which session is - * started. - * \param session_id Session ID specified to OnSessionStartedCallback() - * \param new_session_id Session ID generated - * \param service_type Type of service - * \param hash_id Hash ID generated from connection_handle and - * new_session_id - * \param is_protected Whether service will be protected - **/ - ServiceStartedContext(transport_manager::ConnectionUID connection_handle, - uint8_t session_id, - uint32_t new_session_id, - protocol_handler::ServiceType service_type, - uint32_t hash_id, - bool is_protected) - : connection_handle_(connection_handle) - , session_id_(session_id) - , new_session_id_(new_session_id) - , service_type_(service_type) - , hash_id_(hash_id) - , is_protected_(is_protected) {} - }; - - /** * \brief Disconnect application. * * \param device_handle DeviceHandle of disconnected device. @@ -587,19 +549,6 @@ class ConnectionHandlerImpl void OnConnectionEnded(const transport_manager::ConnectionUID connection_id); - /** - * \brief Convenient method to call NotifySessionStartedResult() with - * negative result. - * \param connection_handle Identifier of connection within which session - * exists - * \param session_id session ID passed to OnSessionStartedCallback() - * \param is_protected whether the service would be protected - **/ - void NotifySessionStartedFailure( - const transport_manager::ConnectionUID connection_handle, - const uint8_t session_id, - bool is_protected); - const ConnectionHandlerSettings& settings_; /** * \brief Pointer to observer @@ -635,7 +584,8 @@ class ConnectionHandlerImpl utils::StlMapDeleter<ConnectionList> connection_list_deleter_; sync_primitives::Lock start_service_context_map_lock_; - std::map<uint32_t, ServiceStartedContext> start_service_context_map_; + std::map<uint32_t, protocol_handler::SessionContext> + start_service_context_map_; #ifdef BUILD_TESTS // Methods for test usage diff --git a/src/components/connection_handler/src/connection.cc b/src/components/connection_handler/src/connection.cc index 202736e612..d494611643 100644 --- a/src/components/connection_handler/src/connection.cc +++ b/src/components/connection_handler/src/connection.cc @@ -39,6 +39,7 @@ #include "protocol_handler/protocol_packet.h" #include "utils/logger.h" #include "utils/macro.h" +#include "utils/helpers.h" #ifdef ENABLE_SECURITY #include "security_manager/ssl_context.h" @@ -148,6 +149,10 @@ bool Connection::AddNewService(uint8_t session_id, LOG4CXX_WARN(logger_, "Wrong service " << static_cast<int>(service_type)); return false; } + + LOG4CXX_DEBUG(logger_, + "Add service " << service_type << " for session " + << static_cast<uint32_t>(session_id)); sync_primitives::AutoLock lock(session_map_lock_); SessionMap::iterator session_it = session_map_.find(session_id); @@ -156,6 +161,20 @@ bool Connection::AddNewService(uint8_t session_id, return false; } Session& session = session_it->second; + + if (session.protocol_version <= protocol_handler::PROTOCOL_VERSION_2 && + helpers::Compare<protocol_handler::ServiceType, + helpers::EQ, + helpers::ONE>( + service_type, + protocol_handler::ServiceType::kAudio, + protocol_handler::ServiceType::kMobileNav)) { + LOG4CXX_WARN(logger_, + "Audio and video services are disallowed for protocol version " + "2 or lower"); + return false; + } + Service* service = session.FindService(service_type); // if service already exists if (service) { @@ -294,6 +313,23 @@ void Connection::SetProtectionFlag( service_rpc->is_protected_ = true; } } + +bool Connection::SessionServiceExists( + const uint8_t session_id, + const protocol_handler::ServiceType& service_type) const { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(session_map_lock_); + + SessionMap::const_iterator session_it = session_map_.find(session_id); + if (session_it == session_map_.end()) { + LOG4CXX_WARN(logger_, "Session not found in this connection!"); + return false; + } + + const Session& session = session_it->second; + return session.FindService(service_type); +} + #endif // ENABLE_SECURITY ConnectionHandle Connection::connection_handle() const { diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index c8f3dd8932..ac8bad2205 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -412,18 +412,17 @@ void ConnectionHandlerImpl::OnSessionStartedCallback( const BsonObject* params) { LOG4CXX_AUTO_TRACE(logger_); - uint32_t new_session_id = 0; - uint32_t hash_id = protocol_handler::HASH_ID_WRONG; + std::vector<std::string> rejected_params; + protocol_handler::SessionContext context(connection_handle, + session_id, + 0, + service_type, + protocol_handler::HASH_ID_WRONG, + is_protected); #ifdef ENABLE_SECURITY if (!AllowProtection(get_settings(), service_type, is_protected)) { - std::vector<std::string> empty; - protocol_handler_->NotifySessionStartedResult(connection_handle, - session_id, - new_session_id, - hash_id, - is_protected, - empty); + protocol_handler_->NotifySessionStarted(context, rejected_params); return; } #endif // ENABLE_SECURITY @@ -431,19 +430,22 @@ void ConnectionHandlerImpl::OnSessionStartedCallback( ConnectionList::iterator it = connection_list_.find(connection_handle); if (connection_list_.end() == it) { LOG4CXX_ERROR(logger_, "Unknown connection!"); - NotifySessionStartedFailure(connection_handle, session_id, is_protected); + protocol_handler_->NotifySessionStarted(context, rejected_params); return; } Connection* connection = it->second; + context.is_new_service_ = + !connection->SessionServiceExists(session_id, service_type); + if ((0 == session_id) && (protocol_handler::kRpc == service_type)) { - new_session_id = connection->AddNewSession(); - if (0 == new_session_id) { + context.new_session_id_ = connection->AddNewSession(); + if (0 == context.new_session_id_) { LOG4CXX_ERROR(logger_, "Couldn't start new session!"); - NotifySessionStartedFailure(connection_handle, session_id, is_protected); + protocol_handler_->NotifySessionStarted(context, rejected_params); return; } - hash_id = KeyFromPair(connection_handle, new_session_id); + context.hash_id_ = KeyFromPair(connection_handle, context.new_session_id_); } else { // Could be create new service or protected exists one if (!connection->AddNewService(session_id, service_type, is_protected)) { LOG4CXX_ERROR(logger_, @@ -453,22 +455,25 @@ void ConnectionHandlerImpl::OnSessionStartedCallback( #endif // ENABLE_SECURITY << " service " << static_cast<int>(service_type) << " for session " << static_cast<int>(session_id)); - NotifySessionStartedFailure(connection_handle, session_id, is_protected); + protocol_handler_->NotifySessionStarted(context, rejected_params); return; } - new_session_id = session_id; - hash_id = protocol_handler::HASH_ID_NOT_SUPPORTED; + context.new_session_id_ = session_id; + context.hash_id_ = protocol_handler::HASH_ID_NOT_SUPPORTED; } sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_); if (connection_handler_observer_) { - const uint32_t session_key = KeyFromPair(connection_handle, new_session_id); + const uint32_t session_key = + KeyFromPair(connection_handle, context.new_session_id_); + + uint32_t app_id = 0; + GetDataOnSessionKey( + session_key, &app_id, NULL, static_cast<DeviceHandle*>(NULL)); + if (app_id > 0) { + context.is_ptu_required_ = + !connection_handler_observer_->CheckAppIsNavi(app_id); + } - ServiceStartedContext context(connection_handle, - session_id, - new_session_id, - service_type, - hash_id, - is_protected); { sync_primitives::AutoLock auto_lock(start_service_context_map_lock_); start_service_context_map_[session_key] = context; @@ -481,13 +486,7 @@ void ConnectionHandlerImpl::OnSessionStartedCallback( params); } else { if (protocol_handler_) { - std::vector<std::string> empty; - protocol_handler_->NotifySessionStartedResult(connection_handle, - session_id, - new_session_id, - hash_id, - is_protected, - empty); + protocol_handler_->NotifySessionStarted(context, rejected_params); } } } @@ -498,11 +497,10 @@ void ConnectionHandlerImpl::NotifyServiceStartedResult( std::vector<std::string>& rejected_params) { LOG4CXX_AUTO_TRACE(logger_); - ServiceStartedContext context; + protocol_handler::SessionContext context; { sync_primitives::AutoLock auto_lock(start_service_context_map_lock_); - std::map<uint32_t, ServiceStartedContext>::iterator it = - start_service_context_map_.find(session_key); + auto it = start_service_context_map_.find(session_key); if (it == start_service_context_map_.end()) { LOG4CXX_ERROR(logger_, "context for start service not found!"); return; @@ -514,8 +512,7 @@ void ConnectionHandlerImpl::NotifyServiceStartedResult( Connection* connection = NULL; { sync_primitives::AutoReadLock lock(connection_list_lock_); - ConnectionList::iterator it = - connection_list_.find(context.connection_handle_); + ConnectionList::iterator it = connection_list_.find(context.connection_id_); if (connection_list_.end() == it) { LOG4CXX_ERROR(logger_, "connection not found"); return; @@ -529,35 +526,14 @@ void ConnectionHandlerImpl::NotifyServiceStartedResult( if (protocol_handler::kRpc == context.service_type_) { connection->RemoveSession(context.new_session_id_); } else { - connection->RemoveService(context.session_id_, context.service_type_); + connection->RemoveService(context.initial_session_id_, + context.service_type_); } context.new_session_id_ = 0; } if (protocol_handler_ != NULL) { - protocol_handler_->NotifySessionStartedResult(context.connection_handle_, - context.session_id_, - context.new_session_id_, - context.hash_id_, - context.is_protected_, - rejected_params); - } -} - -void ConnectionHandlerImpl::NotifySessionStartedFailure( - const transport_manager::ConnectionUID connection_handle, - const uint8_t session_id, - bool is_protected) { - LOG4CXX_AUTO_TRACE(logger_); - if (protocol_handler_) { - std::vector<std::string> empty; - protocol_handler_->NotifySessionStartedResult( - connection_handle, - session_id, - 0, - protocol_handler::HASH_ID_WRONG, - is_protected, - empty); + protocol_handler_->NotifySessionStarted(context, rejected_params); } } @@ -899,6 +875,24 @@ void ConnectionHandlerImpl::SetProtectionFlag( connection.SetProtectionFlag(session_id, service_type); } +bool ConnectionHandlerImpl::SessionServiceExists( + const uint32_t connection_key, + const protocol_handler::ServiceType& service_type) const { + LOG4CXX_AUTO_TRACE(logger_); + transport_manager::ConnectionUID connection_handle = 0; + uint8_t session_id = 0; + PairFromKey(connection_key, &connection_handle, &session_id); + + sync_primitives::AutoReadLock lock(connection_list_lock_); + ConnectionList::const_iterator it = connection_list_.find(connection_handle); + if (connection_list_.end() == it) { + LOG4CXX_ERROR(logger_, "Unknown connection!"); + return false; + } + const Connection& connection = *it->second; + return connection.SessionServiceExists(session_id, service_type); +} + security_manager::SSLContext::HandshakeContext ConnectionHandlerImpl::GetHandshakeContext(uint32_t key) const { return connection_handler_observer_->GetHandshakeContext(key); diff --git a/src/components/connection_handler/test/connection_handler_impl_test.cc b/src/components/connection_handler/test/connection_handler_impl_test.cc index b6783c64ef..a951598917 100644 --- a/src/components/connection_handler/test/connection_handler_impl_test.cc +++ b/src/components/connection_handler/test/connection_handler_impl_test.cc @@ -61,6 +61,7 @@ using ::testing::Mock; using ::testing::Return; using ::testing::ReturnRefOfCopy; using ::testing::SaveArg; +using ::testing::SaveArgPointee; // custom action to call a member function with 3 arguments ACTION_P5(InvokeMemberFuncWithArg3, ptr, memberFunc, a, b, c) { @@ -118,42 +119,51 @@ class ConnectionHandlerTest : public ::testing::Test { void AddTestSession() { protocol_handler_test::MockProtocolHandler temp_protocol_handler; connection_handler_->set_protocol_handler(&temp_protocol_handler); - EXPECT_CALL(temp_protocol_handler, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce( - DoAll(SaveArg<2>(&start_session_id_), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(temp_protocol_handler, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&out_context_)); connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); connection_handler_->set_protocol_handler(NULL); - EXPECT_NE(0u, start_session_id_); - EXPECT_EQ(SessionHash(uid_, start_session_id_), out_hash_id_); - connection_key_ = connection_handler_->KeyFromPair(uid_, start_session_id_); - CheckSessionExists(uid_, start_session_id_); + EXPECT_NE(0u, out_context_.new_session_id_); + EXPECT_EQ(SessionHash(uid_, out_context_.new_session_id_), + out_context_.hash_id_); + connection_key_ = + connection_handler_->KeyFromPair(uid_, out_context_.new_session_id_); + CheckSessionExists(uid_, out_context_.new_session_id_); } uint32_t SessionHash(const uint32_t connection, const uint32_t session) { return connection_handler_->KeyFromPair(connection, session); } void AddTestService(ServiceType service_type) { - EXPECT_NE(0u, start_session_id_); - EXPECT_EQ(SessionHash(uid_, start_session_id_), out_hash_id_); - connection_key_ = connection_handler_->KeyFromPair(uid_, start_session_id_); - CheckSessionExists(uid_, start_session_id_); + EXPECT_NE(0u, out_context_.new_session_id_); + EXPECT_EQ(SessionHash(uid_, out_context_.new_session_id_), + out_context_.hash_id_); + connection_key_ = + connection_handler_->KeyFromPair(uid_, out_context_.new_session_id_); + CheckSessionExists(uid_, out_context_.new_session_id_); + + // Set protocol version to 3 if audio or video service should be tested + if (service_type == ServiceType::kAudio || + service_type == ServiceType::kMobileNav) { + ChangeProtocol(uid_, + out_context_.new_session_id_, + protocol_handler::PROTOCOL_VERSION_3); + } - uint32_t session_id = 0; + SessionContext context; protocol_handler_test::MockProtocolHandler temp_protocol_handler; connection_handler_->set_protocol_handler(&temp_protocol_handler); - EXPECT_CALL(temp_protocol_handler, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id)); + EXPECT_CALL(temp_protocol_handler, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&context)); connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, service_type, PROTECTION_OFF, static_cast<BsonObject*>(0)); connection_handler_->set_protocol_handler(NULL); - EXPECT_EQ(session_id, start_session_id_); + EXPECT_EQ(context.new_session_id_, out_context_.new_session_id_); } // Check Service Wrapper @@ -279,8 +289,7 @@ class ConnectionHandlerTest : public ::testing::Test { transport_manager::DeviceHandle device_handle_; transport_manager::ConnectionUID uid_; uint32_t connection_key_; - uint32_t start_session_id_; - uint32_t out_hash_id_; + protocol_handler::SessionContext out_context_; std::string connection_type_; std::string device_name_; @@ -295,17 +304,17 @@ TEST_F(ConnectionHandlerTest, StartSession_NoConnection) { // Null sessionId for start new session const uint8_t sessionID = 0; // Start new session with RPC service - uint32_t result_fail = 0; + protocol_handler::SessionContext context; + connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&result_fail), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&context)); connection_handler_->OnSessionStartedCallback( uid_, sessionID, kRpc, PROTECTION_ON, static_cast<BsonObject*>(NULL)); // Unknown connection error is '0' - EXPECT_EQ(0u, result_fail); - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); + EXPECT_EQ(0u, context.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, context.hash_id_); ASSERT_TRUE(connection_handler_->getConnectionList().empty()); } @@ -340,7 +349,7 @@ TEST_F(ConnectionHandlerTest, GetAppIdOnSessionKey) { AddTestSession(); uint32_t app_id = 0; - const uint32_t testid = SessionHash(uid_, start_session_id_); + const uint32_t testid = SessionHash(uid_, out_context_.new_session_id_); connection_handler::DeviceHandle null_handle = 0; EXPECT_EQ(0, @@ -407,7 +416,8 @@ TEST_F(ConnectionHandlerTest, GetApplicationsOnDevice) { 0, connection_handler_->GetDataOnDeviceID(handle, NULL, &applications_list)); - uint32_t test_id = connection_handler_->KeyFromPair(uid_, start_session_id_); + uint32_t test_id = + connection_handler_->KeyFromPair(uid_, out_context_.new_session_id_); EXPECT_EQ(1u, applications_list.size()); EXPECT_EQ(test_id, applications_list.front()); @@ -419,7 +429,7 @@ TEST_F(ConnectionHandlerTest, GetDefaultProtocolVersion) { uint8_t protocol_version = 0; EXPECT_TRUE(connection_handler_->ProtocolVersionUsed( - uid_, start_session_id_, protocol_version)); + uid_, out_context_.new_session_id_, protocol_version)); EXPECT_EQ(PROTOCOL_VERSION_2, protocol_version); } @@ -427,11 +437,11 @@ TEST_F(ConnectionHandlerTest, GetDefaultProtocolVersion) { TEST_F(ConnectionHandlerTest, GetProtocolVersion) { AddTestDeviceConnection(); AddTestSession(); - ChangeProtocol(uid_, start_session_id_, PROTOCOL_VERSION_3); + ChangeProtocol(uid_, out_context_.new_session_id_, PROTOCOL_VERSION_3); uint8_t protocol_version = 0; EXPECT_TRUE(connection_handler_->ProtocolVersionUsed( - uid_, start_session_id_, protocol_version)); + uid_, out_context_.new_session_id_, protocol_version)); EXPECT_EQ(PROTOCOL_VERSION_3, protocol_version); } @@ -441,14 +451,14 @@ TEST_F(ConnectionHandlerTest, GetProtocolVersionAfterBinding) { AddTestSession(); uint8_t protocol_version = 0; EXPECT_TRUE(connection_handler_->ProtocolVersionUsed( - uid_, start_session_id_, protocol_version)); + uid_, out_context_.new_session_id_, protocol_version)); EXPECT_EQ(PROTOCOL_VERSION_2, protocol_version); connection_handler_->BindProtocolVersionWithSession(connection_key_, PROTOCOL_VERSION_3); EXPECT_TRUE(connection_handler_->ProtocolVersionUsed( - uid_, start_session_id_, protocol_version)); + uid_, out_context_.new_session_id_, protocol_version)); EXPECT_EQ(PROTOCOL_VERSION_3, protocol_version); } @@ -460,15 +470,15 @@ TEST_F(ConnectionHandlerTest, GetPairFromKey) { uint32_t test_uid = 0; connection_handler_->PairFromKey(connection_key_, &test_uid, &session_id); EXPECT_EQ(uid_, test_uid); - EXPECT_EQ(start_session_id_, session_id); + EXPECT_EQ(out_context_.new_session_id_, session_id); } TEST_F(ConnectionHandlerTest, IsHeartBeatSupported) { AddTestDeviceConnection(); AddTestSession(); - ChangeProtocol(uid_, start_session_id_, PROTOCOL_VERSION_3); - EXPECT_TRUE( - connection_handler_->IsHeartBeatSupported(uid_, start_session_id_)); + ChangeProtocol(uid_, out_context_.new_session_id_, PROTOCOL_VERSION_3); + EXPECT_TRUE(connection_handler_->IsHeartBeatSupported( + uid_, out_context_.new_session_id_)); } MATCHER_P(SameDevice, device, "") { @@ -561,8 +571,8 @@ TEST_F(ConnectionHandlerTest, OnApplicationFloodCallBack) { connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) - .Times(1); + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)).Times(1); InSequence seq; EXPECT_CALL(mock_connection_handler_observer, OnServiceEndedCallback(connection_key_, kMobileNav, kCommon)); @@ -588,7 +598,8 @@ TEST_F(ConnectionHandlerTest, OnApplicationFloodCallBack_SessionFound) { &mock_connection_handler_observer); connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)); + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)); InSequence seq; EXPECT_CALL(mock_connection_handler_observer, OnServiceEndedCallback(connection_key_, kMobileNav, kFlood)); @@ -862,7 +873,8 @@ TEST_F(ConnectionHandlerTest, CloseSessionWithCommonReason) { TestAsyncWaiter waiter; uint32_t times = 0; - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)) .WillOnce(NotifyTestAsyncWaiter(&waiter)); times++; @@ -903,7 +915,8 @@ TEST_F(ConnectionHandlerTest, CloseSessionWithFloodReason) { TestAsyncWaiter waiter; uint32_t times = 0; - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)) .WillOnce(NotifyTestAsyncWaiter(&waiter)); times++; @@ -944,8 +957,8 @@ TEST_F(ConnectionHandlerTest, CloseSessionWithMalformedMessage) { TestAsyncWaiter waiter; uint32_t times = 0; - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) - .Times(0); + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)).Times(0); InSequence seq; EXPECT_CALL(mock_connection_handler_observer, @@ -984,8 +997,8 @@ TEST_F(ConnectionHandlerTest, CloseConnectionSessionsWithMalformedMessage) { TestAsyncWaiter waiter; uint32_t times = 0; - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) - .Times(0); + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)).Times(0); InSequence seq; EXPECT_CALL(mock_connection_handler_observer, @@ -1024,7 +1037,8 @@ TEST_F(ConnectionHandlerTest, CloseConnectionSessionsWithCommonReason) { TestAsyncWaiter waiter; uint32_t times = 0; - EXPECT_CALL(mock_protocol_handler_, SendEndSession(uid_, start_session_id_)) + EXPECT_CALL(mock_protocol_handler_, + SendEndSession(uid_, out_context_.new_session_id_)) .WillOnce(NotifyTestAsyncWaiter(&waiter)); times++; @@ -1055,34 +1069,34 @@ TEST_F(ConnectionHandlerTest, StartService_withServices) { // Add virtual device and connection AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); - uint32_t start_audio = 0; - uint32_t start_video = 0; + SessionContext audio_context, video_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&start_audio), SaveArg<3>(&out_hash_id_))) - .WillOnce(DoAll(SaveArg<2>(&start_video), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&audio_context)) + .WillOnce(SaveArg<0>(&video_context)); // Start Audio service connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, start_audio); - CheckServiceExists(uid_, start_session_id_, kAudio, true); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); + EXPECT_NE(0u, audio_context.new_session_id_); + CheckServiceExists(uid_, audio_context.new_session_id_, kAudio, true); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, audio_context.hash_id_); // Start Audio service connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kMobileNav, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, start_video); - CheckServiceExists(uid_, start_session_id_, kMobileNav, true); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); + EXPECT_NE(0u, video_context.new_session_id_); + CheckServiceExists(uid_, video_context.new_session_id_, kMobileNav, true); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, video_context.hash_id_); connection_handler_->set_protocol_handler(NULL); } @@ -1090,22 +1104,27 @@ TEST_F(ConnectionHandlerTest, StartService_withServices) { TEST_F(ConnectionHandlerTest, StartService_withServices_withParams) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); + + SessionContext video_context; - uint32_t start_video = 0; // create a dummy pointer int dummy = 0; std::vector<std::string> empty; BsonObject* dummy_param = reinterpret_cast<BsonObject*>(&dummy); connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, empty)) - .WillOnce(DoAll(SaveArg<2>(&start_video), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, empty)) + .WillOnce(SaveArg<0>(&video_context)); - connection_handler_->OnSessionStartedCallback( - uid_, start_session_id_, kMobileNav, PROTECTION_OFF, dummy_param); - EXPECT_EQ(start_session_id_, start_video); - CheckServiceExists(uid_, start_session_id_, kMobileNav, true); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); + connection_handler_->OnSessionStartedCallback(uid_, + out_context_.new_session_id_, + kMobileNav, + PROTECTION_OFF, + dummy_param); + EXPECT_EQ(out_context_.new_session_id_, video_context.new_session_id_); + CheckServiceExists(uid_, out_context_.new_session_id_, kMobileNav, true); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, video_context.hash_id_); connection_handler_->set_protocol_handler(NULL); } @@ -1126,39 +1145,39 @@ TEST_F(ConnectionHandlerTest, ServiceStop_UnExistService) { uint32_t dummy_hash = 0u; const uint32_t end_session_result = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &dummy_hash, kAudio); + uid_, out_context_.new_session_id_, &dummy_hash, kAudio); EXPECT_EQ(0u, end_session_result); - CheckServiceExists(uid_, start_session_id_, kAudio, false); + CheckServiceExists(uid_, out_context_.new_session_id_, kAudio, false); } TEST_F(ConnectionHandlerTest, ServiceStop) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); - uint32_t start_audio = 0; + SessionContext audio_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillRepeatedly( - DoAll(SaveArg<2>(&start_audio), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillRepeatedly(SaveArg<0>(&audio_context)); // Check ignoring hash_id on stop non-rpc service for (uint32_t some_hash_id = 0; some_hash_id < 0xFF; ++some_hash_id) { // Start audio service connection_handler_->OnSessionStartedCallback( uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, start_audio); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); + EXPECT_EQ(out_context_.new_session_id_, audio_context.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, audio_context.hash_id_); const uint32_t end_session_result = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &some_hash_id, kAudio); + uid_, out_context_.new_session_id_, &some_hash_id, kAudio); EXPECT_EQ(connection_key_, end_session_result); - CheckServiceExists(uid_, start_session_id_, kAudio, false); + CheckServiceExists(uid_, out_context_.new_session_id_, kAudio, false); } } @@ -1172,13 +1191,13 @@ TEST_F(ConnectionHandlerTest, SessionStop_CheckHash) { const uint32_t end_audio_wrong_hash = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &wrong_hash, kRpc); + uid_, out_context_.new_session_id_, &wrong_hash, kRpc); EXPECT_EQ(0u, end_audio_wrong_hash); EXPECT_EQ(protocol_handler::HASH_ID_WRONG, wrong_hash); - CheckSessionExists(uid_, start_session_id_); + CheckSessionExists(uid_, out_context_.new_session_id_); const uint32_t end_audio = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &hash, kRpc); + uid_, out_context_.new_session_id_, &hash, kRpc); EXPECT_EQ(connection_key_, end_audio); CheckSessionExists(uid_, 0); } @@ -1194,13 +1213,13 @@ TEST_F(ConnectionHandlerTest, SessionStop_CheckSpecificHash) { const uint32_t end_audio_wrong_hash = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &wrong_hash, kRpc); + uid_, out_context_.new_session_id_, &wrong_hash, kRpc); EXPECT_EQ(0u, end_audio_wrong_hash); EXPECT_EQ(protocol_handler::HASH_ID_WRONG, wrong_hash); - CheckSessionExists(uid_, start_session_id_); + CheckSessionExists(uid_, out_context_.new_session_id_); const uint32_t end_audio = connection_handler_->OnSessionEndedCallback( - uid_, start_session_id_, &hash, kRpc); + uid_, out_context_.new_session_id_, &hash, kRpc); EXPECT_EQ(connection_key_, end_audio); CheckSessionExists(uid_, 0); } @@ -1209,16 +1228,17 @@ TEST_F(ConnectionHandlerTest, SessionStop_CheckSpecificHash) { TEST_F(ConnectionHandlerTest, SessionStarted_WithRpc) { // Add virtual device and connection AddTestDeviceConnection(); + out_context_.initial_session_id_ = 1u; // Expect that rpc service has started connection_handler_test::MockConnectionHandlerObserver mock_connection_handler_observer; connection_handler_->set_connection_handler_observer( &mock_connection_handler_observer); - uint32_t session_key = - connection_handler_->KeyFromPair(uid_, start_session_id_); std::vector<std::string> empty; + uint32_t session_key = + connection_handler_->KeyFromPair(uid_, out_context_.initial_session_id_); EXPECT_CALL(mock_connection_handler_observer, - OnServiceStartedCallback(device_handle_, session_key, kRpc, NULL)) + OnServiceStartedCallback(device_handle_, _, kRpc, NULL)) .WillOnce(InvokeMemberFuncWithArg3( connection_handler_, &ConnectionHandler::NotifyServiceStartedResult, @@ -1226,22 +1246,25 @@ TEST_F(ConnectionHandlerTest, SessionStarted_WithRpc) { true, ByRef(empty))); - uint32_t new_session_id = 0; + EXPECT_CALL(mock_connection_handler_observer, CheckAppIsNavi(_)) + .WillOnce(Return(true)); + connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&new_session_id), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&out_context_)); // Start new session with RPC service connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_NE(0u, new_session_id); + EXPECT_NE(0u, out_context_.new_session_id_); } TEST_F(ConnectionHandlerTest, ServiceStarted_Video_SUCCESS) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); int dummy = 0; BsonObject* dummy_params = reinterpret_cast<BsonObject*>(&dummy); @@ -1251,7 +1274,7 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_SUCCESS) { connection_handler_->set_connection_handler_observer( &mock_connection_handler_observer); uint32_t session_key = - connection_handler_->KeyFromPair(uid_, start_session_id_); + connection_handler_->KeyFromPair(uid_, out_context_.new_session_id_); std::vector<std::string> empty; EXPECT_CALL(mock_connection_handler_observer, OnServiceStartedCallback( @@ -1262,23 +1285,28 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_SUCCESS) { session_key, true, ByRef(empty))); + EXPECT_CALL(mock_connection_handler_observer, CheckAppIsNavi(_)) + .WillOnce(Return(true)); - // confirm that NotifySessionStartedResult() is called - uint32_t new_session_id = 0; + // confirm that NotifySessionStarted() is called connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, false, empty)) - .WillOnce(DoAll(SaveArg<2>(&new_session_id), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, empty)) + .WillOnce(SaveArg<0>(&out_context_)); - connection_handler_->OnSessionStartedCallback( - uid_, start_session_id_, kMobileNav, PROTECTION_OFF, dummy_params); + connection_handler_->OnSessionStartedCallback(uid_, + out_context_.new_session_id_, + kMobileNav, + PROTECTION_OFF, + dummy_params); - EXPECT_NE(0u, new_session_id); + EXPECT_NE(0u, out_context_.new_session_id_); } TEST_F(ConnectionHandlerTest, ServiceStarted_Video_FAILURE) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); int dummy = 0; BsonObject* dummy_params = reinterpret_cast<BsonObject*>(&dummy); @@ -1288,7 +1316,7 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_FAILURE) { connection_handler_->set_connection_handler_observer( &mock_connection_handler_observer); uint32_t session_key = - connection_handler_->KeyFromPair(uid_, start_session_id_); + connection_handler_->KeyFromPair(uid_, out_context_.new_session_id_); std::vector<std::string> empty; EXPECT_CALL(mock_connection_handler_observer, OnServiceStartedCallback( @@ -1299,18 +1327,21 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_FAILURE) { session_key, false, ByRef(empty))); + EXPECT_CALL(mock_connection_handler_observer, CheckAppIsNavi(_)) + .WillOnce(Return(true)); - // confirm that NotifySessionStartedResult() is called - uint32_t new_session_id = 0; + // confirm that NotifySessionStarted() is called connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, false, empty)) - .WillOnce(DoAll(SaveArg<2>(&new_session_id), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, empty)) + .WillOnce(SaveArg<0>(&out_context_)); - connection_handler_->OnSessionStartedCallback( - uid_, start_session_id_, kMobileNav, PROTECTION_OFF, dummy_params); + connection_handler_->OnSessionStartedCallback(uid_, + out_context_.new_session_id_, + kMobileNav, + PROTECTION_OFF, + dummy_params); - EXPECT_EQ(0u, new_session_id); + EXPECT_EQ(0u, out_context_.new_session_id_); } /* @@ -1321,17 +1352,13 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_FAILURE) { TEST_F(ConnectionHandlerTest, ServiceStarted_Video_Multiple) { AddTestDeviceConnection(); - uint32_t rpc_session_id1; - uint32_t rpc_session_id2; - uint32_t hash_id1; - uint32_t hash_id2; + SessionContext context_first, context_second; protocol_handler_test::MockProtocolHandler temp_protocol_handler; connection_handler_->set_protocol_handler(&temp_protocol_handler); - EXPECT_CALL(temp_protocol_handler, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&rpc_session_id1), SaveArg<3>(&hash_id1))) - .WillOnce(DoAll(SaveArg<2>(&rpc_session_id2), SaveArg<3>(&hash_id2))); + EXPECT_CALL(temp_protocol_handler, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&context_first)) + .WillOnce(SaveArg<0>(&context_second)); // add two sessions connection_handler_->OnSessionStartedCallback( @@ -1339,12 +1366,14 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_Multiple) { connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_NE(0u, rpc_session_id1); - EXPECT_NE(0u, rpc_session_id2); - EXPECT_EQ(SessionHash(uid_, rpc_session_id1), hash_id1); - EXPECT_EQ(SessionHash(uid_, rpc_session_id2), hash_id2); - CheckSessionExists(uid_, rpc_session_id1); - CheckSessionExists(uid_, rpc_session_id2); + EXPECT_NE(0u, context_first.new_session_id_); + EXPECT_NE(0u, context_second.new_session_id_); + EXPECT_EQ(SessionHash(uid_, context_first.new_session_id_), + context_first.hash_id_); + EXPECT_EQ(SessionHash(uid_, context_second.new_session_id_), + context_second.hash_id_); + CheckSessionExists(uid_, context_first.new_session_id_); + CheckSessionExists(uid_, context_second.new_session_id_); connection_handler_->set_protocol_handler(NULL); @@ -1356,11 +1385,17 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_Multiple) { connection_handler_->set_connection_handler_observer( &mock_connection_handler_observer); uint32_t session_key1 = - connection_handler_->KeyFromPair(uid_, rpc_session_id1); + connection_handler_->KeyFromPair(uid_, context_first.new_session_id_); uint32_t session_key2 = - connection_handler_->KeyFromPair(uid_, rpc_session_id2); + connection_handler_->KeyFromPair(uid_, context_second.new_session_id_); std::vector<std::string> empty; + ChangeProtocol(uid_, + context_first.new_session_id_, + protocol_handler::PROTOCOL_VERSION_3); + ChangeProtocol(uid_, + context_second.new_session_id_, + protocol_handler::PROTOCOL_VERSION_3); EXPECT_CALL(mock_connection_handler_observer, OnServiceStartedCallback( @@ -1384,27 +1419,30 @@ TEST_F(ConnectionHandlerTest, ServiceStarted_Video_Multiple) { session_key1, true, ByRef(empty)))); + EXPECT_CALL(mock_connection_handler_observer, CheckAppIsNavi(_)) + .Times(2) + .WillRepeatedly(Return(true)); // verify that connection handler will not mix up the two results - uint32_t new_session_id1 = 0; - uint32_t new_session_id2 = 0; + SessionContext new_context_first, new_context_second; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL( - mock_protocol_handler_, - NotifySessionStartedResult(_, rpc_session_id1, _, _, false, empty)) - .WillOnce(SaveArg<2>(&new_session_id1)); - EXPECT_CALL( - mock_protocol_handler_, - NotifySessionStartedResult(_, rpc_session_id2, _, _, false, empty)) - .WillOnce(SaveArg<2>(&new_session_id2)); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, empty)) + .WillOnce(SaveArg<0>(&new_context_second)) + .WillOnce(SaveArg<0>(&new_context_first)); - connection_handler_->OnSessionStartedCallback( - uid_, rpc_session_id1, kMobileNav, PROTECTION_OFF, dummy_params); - connection_handler_->OnSessionStartedCallback( - uid_, rpc_session_id2, kMobileNav, PROTECTION_OFF, dummy_params); + connection_handler_->OnSessionStartedCallback(uid_, + context_first.new_session_id_, + kMobileNav, + PROTECTION_OFF, + dummy_params); + connection_handler_->OnSessionStartedCallback(uid_, + context_second.new_session_id_, + kMobileNav, + PROTECTION_OFF, + dummy_params); - EXPECT_NE(0u, new_session_id1); // result is positive - EXPECT_EQ(0u, new_session_id2); // result is negative + EXPECT_NE(0u, new_context_first.new_session_id_); // result is positive + EXPECT_EQ(0u, new_context_second.new_session_id_); // result is negative } TEST_F(ConnectionHandlerTest, @@ -1417,23 +1455,23 @@ TEST_F(ConnectionHandlerTest, protected_services_.push_back(kRpc); SetSpecificServices(); - uint32_t session_id_fail = 0; - uint32_t session_id = 0; + SessionContext fail_context; + SessionContext positive_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&session_id_fail), SaveArg<3>(&out_hash_id_))) - .WillOnce(DoAll(SaveArg<2>(&session_id), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&fail_context)) + .WillOnce(SaveArg<0>(&positive_context)); // Start new session with RPC service connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(0u, session_id_fail); - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); + EXPECT_EQ(0u, fail_context.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, fail_context.hash_id_); #else - EXPECT_EQ(1u, session_id_fail); - EXPECT_EQ(SessionHash(uid_, session_id_fail), out_hash_id_); + EXPECT_EQ(1u, fail_context.new_session_id_); + EXPECT_EQ(SessionHash(uid_, fail_context.new_session_id_), + fail_context.hash_id_); #endif // ENABLE_SECURITY // Allow start kRPC without encryption @@ -1443,9 +1481,11 @@ TEST_F(ConnectionHandlerTest, // Start new session with RPC service connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_NE(0u, session_id); - CheckService(uid_, session_id, kRpc, NULL, PROTECTION_OFF); - EXPECT_EQ(SessionHash(uid_, session_id), out_hash_id_); + EXPECT_NE(0u, positive_context.new_session_id_); + CheckService( + uid_, positive_context.new_session_id_, kRpc, NULL, PROTECTION_OFF); + EXPECT_EQ(SessionHash(uid_, positive_context.new_session_id_), + positive_context.hash_id_); } TEST_F(ConnectionHandlerTest, @@ -1459,21 +1499,20 @@ TEST_F(ConnectionHandlerTest, unprotected_services_.push_back(kControl); SetSpecificServices(); - uint32_t session_id_fail = 0; - uint32_t session_id = 0; + SessionContext fail_context; + SessionContext positive_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id_fail)) - .WillOnce(DoAll(SaveArg<2>(&session_id), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&fail_context)) + .WillOnce(SaveArg<0>(&positive_context)); // Start new session with RPC service connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_ON, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(0u, session_id_fail); + EXPECT_EQ(0u, fail_context.new_session_id_); #else - EXPECT_EQ(1u, session_id_fail); + EXPECT_EQ(1u, fail_context.new_session_id_); #endif // ENABLE_SECURITY // Allow start kRPC with encryption @@ -1483,17 +1522,21 @@ TEST_F(ConnectionHandlerTest, // Start new session with RPC service connection_handler_->OnSessionStartedCallback( uid_, 0, kRpc, PROTECTION_ON, static_cast<BsonObject*>(NULL)); - EXPECT_NE(0u, session_id); - EXPECT_EQ(SessionHash(uid_, session_id), out_hash_id_); + EXPECT_NE(0u, positive_context.new_session_id_); + EXPECT_EQ(SessionHash(uid_, positive_context.new_session_id_), + positive_context.hash_id_); // Protection steal FALSE because of APPlink Protocol implementation - CheckService(uid_, session_id, kRpc, NULL, PROTECTION_OFF); + CheckService( + uid_, positive_context.new_session_id_, kRpc, NULL, PROTECTION_OFF); } TEST_F(ConnectionHandlerTest, SessionStarted_StartService_SecureSpecific_Unprotect) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); // Forbid start kAudio without encryption protected_services_.push_back(UnnamedService::kServedService1); @@ -1502,24 +1545,22 @@ TEST_F(ConnectionHandlerTest, protected_services_.push_back(kControl); SetSpecificServices(); - uint32_t session_id2 = 0; - uint32_t session_id3 = 0; + SessionContext context_first, context_second; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id2)) - .WillOnce(DoAll(SaveArg<2>(&session_id3), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&context_first)) + .WillOnce(SaveArg<0>(&context_second)); // Start new session with Audio service connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(0u, session_id2); + EXPECT_EQ(0u, context_first.new_session_id_); #else - EXPECT_EQ(1u, session_id2); + EXPECT_EQ(1u, context_first.new_session_id_); #endif // ENABLE_SECURITY // Allow start kAudio without encryption protected_services_.clear(); @@ -1529,18 +1570,19 @@ TEST_F(ConnectionHandlerTest, protected_services_.push_back(kControl); SetSpecificServices(); connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); // Returned original session id #ifdef ENABLE_SECURITY - EXPECT_EQ(start_session_id_, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); - CheckService(uid_, session_id3, kRpc, NULL, PROTECTION_OFF); + EXPECT_EQ(out_context_.new_session_id_, context_second.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, context_second.hash_id_); + CheckService( + uid_, context_second.new_session_id_, kRpc, NULL, PROTECTION_OFF); #else - EXPECT_EQ(0u, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); + EXPECT_EQ(0u, context_second.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, context_second.hash_id_); #endif // ENABLE_SECURITY } @@ -1548,6 +1590,8 @@ TEST_F(ConnectionHandlerTest, SessionStarted_StartService_SecureSpecific_Protect) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); // Forbid start kAudio with encryption unprotected_services_.push_back(UnnamedService::kServedService1); @@ -1556,101 +1600,103 @@ TEST_F(ConnectionHandlerTest, unprotected_services_.push_back(kControl); SetSpecificServices(); - uint32_t session_id_reject = 0; - uint32_t session_id3 = 0; + SessionContext rejected_context, positive_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id_reject)) - .WillOnce(DoAll(SaveArg<2>(&session_id3), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&rejected_context)) + .WillOnce(SaveArg<0>(&positive_context)); // Start new session with Audio service connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_ON, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(0u, session_id_reject); + EXPECT_EQ(0u, rejected_context.new_session_id_); #else - EXPECT_EQ(1u, session_id_reject); + EXPECT_EQ(1u, rejected_context.new_session_id_); #endif // ENABLE_SECURITY // Allow start kAudio with encryption unprotected_services_.clear(); SetSpecificServices(); connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_ON, static_cast<BsonObject*>(NULL)); // Returned original session id #ifdef ENABLE_SECURITY - EXPECT_EQ(start_session_id_, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); - CheckService(uid_, session_id3, kAudio, NULL, PROTECTION_ON); + EXPECT_EQ(out_context_.new_session_id_, positive_context.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, positive_context.hash_id_); + CheckService( + uid_, positive_context.new_session_id_, kAudio, NULL, PROTECTION_ON); #else - EXPECT_EQ(0u, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); - CheckService(uid_, start_session_id_, kAudio, NULL, PROTECTION_OFF); + EXPECT_EQ(0u, positive_context.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, positive_context.hash_id_); + CheckService( + uid_, positive_context.new_session_id_, kAudio, NULL, PROTECTION_OFF); #endif // ENABLE_SECURITY } TEST_F(ConnectionHandlerTest, SessionStarted_DealyProtect) { AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); - uint32_t session_id_new = 0; - uint32_t session_id2 = 0; - uint32_t session_id3 = 0; + SessionContext context_new, context_second, context_third; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&session_id_new), SaveArg<3>(&out_hash_id_))) - .WillOnce(DoAll(SaveArg<2>(&session_id2), SaveArg<3>(&out_hash_id_))) - .WillOnce(DoAll(SaveArg<2>(&session_id3), SaveArg<3>(&out_hash_id_))); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&context_new)) + .WillOnce(SaveArg<0>(&context_second)) + .WillOnce(SaveArg<0>(&context_third)); // Start RPC protection connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kRpc, PROTECTION_ON, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(start_session_id_, session_id_new); + EXPECT_EQ(out_context_.new_session_id_, context_new.new_session_id_); // Post protection nedd no hash - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); - CheckService(uid_, start_session_id_, kRpc, NULL, PROTECTION_ON); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, context_new.hash_id_); + CheckService(uid_, context_new.new_session_id_, kRpc, NULL, PROTECTION_ON); #else - EXPECT_EQ(0u, session_id_new); + EXPECT_EQ(0u, context_new.new_session_id_); // Post protection nedd no hash - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); - CheckService(uid_, start_session_id_, kRpc, NULL, PROTECTION_OFF); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, context_new.hash_id_); + CheckService(uid_, context_new.new_session_id_, kRpc, NULL, PROTECTION_OFF); #endif // ENABLE_SECURITY // Start Audio session without protection connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_OFF, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, session_id2); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); - CheckService(uid_, start_session_id_, kAudio, NULL, PROTECTION_OFF); + EXPECT_EQ(out_context_.new_session_id_, context_second.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, context_second.hash_id_); + CheckService( + uid_, context_second.new_session_id_, kAudio, NULL, PROTECTION_OFF); // Start Audio protection connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_ON, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(start_session_id_, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, out_hash_id_); - CheckService(uid_, start_session_id_, kAudio, NULL, PROTECTION_ON); + EXPECT_EQ(out_context_.new_session_id_, context_third.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_NOT_SUPPORTED, context_third.hash_id_); + CheckService( + uid_, context_third.new_session_id_, kAudio, NULL, PROTECTION_ON); #else - EXPECT_EQ(0u, session_id3); - EXPECT_EQ(protocol_handler::HASH_ID_WRONG, out_hash_id_); - CheckService(uid_, start_session_id_, kAudio, NULL, PROTECTION_OFF); + EXPECT_EQ(0u, context_third.new_session_id_); + EXPECT_EQ(protocol_handler::HASH_ID_WRONG, context_third.hash_id_); + CheckService( + uid_, context_third.new_session_id_, kAudio, NULL, PROTECTION_OFF); #endif // ENABLE_SECURITY } @@ -1658,22 +1704,21 @@ TEST_F(ConnectionHandlerTest, SessionStarted_DealyProtectBulk) { AddTestDeviceConnection(); AddTestSession(); - uint32_t session_id_new = 0; + SessionContext new_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id_new)); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&new_context)); connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kBulk, PROTECTION_ON, static_cast<BsonObject*>(NULL)); #ifdef ENABLE_SECURITY - EXPECT_EQ(start_session_id_, session_id_new); - CheckService(uid_, start_session_id_, kRpc, NULL, PROTECTION_ON); + EXPECT_EQ(out_context_.new_session_id_, new_context.new_session_id_); + CheckService(uid_, new_context.new_session_id_, kRpc, NULL, PROTECTION_ON); #else - EXPECT_EQ(0u, session_id_new); - CheckService(uid_, start_session_id_, kRpc, NULL, PROTECTION_OFF); + EXPECT_EQ(0u, new_context.new_session_id_); + CheckService(uid_, new_context.new_session_id_, kRpc, NULL, PROTECTION_OFF); #endif // ENABLE_SECURITY } @@ -1752,6 +1797,9 @@ TEST_F(ConnectionHandlerTest, GetSSLContext_ByProtectedService) { testing::StrictMock<security_manager_test::MockSSLContext> mock_ssl_context; AddTestDeviceConnection(); AddTestSession(); + ChangeProtocol( + uid_, out_context_.new_session_id_, protocol_handler::PROTOCOL_VERSION_3); + EXPECT_EQ( connection_handler_->SetSSLContext(connection_key_, &mock_ssl_context), ::security_manager::SecurityManager::ERROR_SUCCESS); @@ -1763,20 +1811,23 @@ TEST_F(ConnectionHandlerTest, GetSSLContext_ByProtectedService) { EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kAudio), reinterpret_cast<security_manager::SSLContext*>(NULL)); - uint32_t session_id = 0; + SessionContext new_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id)); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&new_context)); // Open kAudio service connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kAudio, PROTECTION_ON, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(session_id, start_session_id_); - CheckService(uid_, session_id, kAudio, &mock_ssl_context, PROTECTION_ON); + EXPECT_EQ(new_context.new_session_id_, out_context_.new_session_id_); + CheckService(uid_, + new_context.new_session_id_, + kAudio, + &mock_ssl_context, + PROTECTION_ON); // kAudio is not exists yet EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kAudio), @@ -1797,20 +1848,23 @@ TEST_F(ConnectionHandlerTest, GetSSLContext_ByDealyProtectedRPC) { EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kRpc), reinterpret_cast<security_manager::SSLContext*>(NULL)); - uint32_t session_id = 0; + SessionContext new_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id)); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&new_context)); // Protect kRpc (Bulk will be protect also) connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kRpc, PROTECTION_ON, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, session_id); - CheckService(uid_, session_id, kRpc, &mock_ssl_context, PROTECTION_ON); + EXPECT_EQ(out_context_.new_session_id_, new_context.new_session_id_); + CheckService(uid_, + new_context.new_session_id_, + kRpc, + &mock_ssl_context, + PROTECTION_ON); // kRpc is protected EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kRpc), @@ -1834,20 +1888,23 @@ TEST_F(ConnectionHandlerTest, GetSSLContext_ByDealyProtectedBulk) { EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kRpc), reinterpret_cast<security_manager::SSLContext*>(NULL)); - uint32_t session_id = 0; + SessionContext new_context; connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, - NotifySessionStartedResult(_, _, _, _, _, _)) - .WillOnce(SaveArg<2>(&session_id)); + EXPECT_CALL(mock_protocol_handler_, NotifySessionStarted(_, _)) + .WillOnce(SaveArg<0>(&new_context)); // Protect Bulk (kRpc will be protected also) connection_handler_->OnSessionStartedCallback(uid_, - start_session_id_, + out_context_.new_session_id_, kBulk, PROTECTION_ON, static_cast<BsonObject*>(NULL)); - EXPECT_EQ(start_session_id_, session_id); - CheckService(uid_, session_id, kRpc, &mock_ssl_context, PROTECTION_ON); + EXPECT_EQ(out_context_.new_session_id_, new_context.new_session_id_); + CheckService(uid_, + new_context.new_session_id_, + kRpc, + &mock_ssl_context, + PROTECTION_ON); // kRpc is protected EXPECT_EQ(connection_handler_->GetSSLContext(connection_key_, kRpc), @@ -1863,8 +1920,9 @@ TEST_F(ConnectionHandlerTest, SendHeartBeat) { AddTestDeviceConnection(); AddTestSession(); connection_handler_->set_protocol_handler(&mock_protocol_handler_); - EXPECT_CALL(mock_protocol_handler_, SendHeartBeat(uid_, start_session_id_)); - connection_handler_->SendHeartBeat(uid_, start_session_id_); + EXPECT_CALL(mock_protocol_handler_, + SendHeartBeat(uid_, out_context_.new_session_id_)); + connection_handler_->SendHeartBeat(uid_, out_context_.new_session_id_); } TEST_F(ConnectionHandlerTest, RunAppOnDevice_NoAppOnDevice_UNSUCCESS) { diff --git a/src/components/connection_handler/test/connection_test.cc b/src/components/connection_handler/test/connection_test.cc index 4582cc10ee..5fd6b40e0e 100644 --- a/src/components/connection_handler/test/connection_test.cc +++ b/src/components/connection_handler/test/connection_test.cc @@ -71,6 +71,11 @@ class ConnectionTest : public ::testing::Test { delete connection_handler_; } void StartSession() { + StartDefaultSession(); + connection_->UpdateProtocolVersionSession( + session_id, protocol_handler::PROTOCOL_VERSION_3); + } + void StartDefaultSession() { session_id = connection_->AddNewSession(); EXPECT_NE(session_id, 0u); const SessionMap sessionMap = connection_->session_map(); @@ -142,13 +147,13 @@ TEST_F(ConnectionTest, Session_TryGetProtocolVersionWithoutSession) { } TEST_F(ConnectionTest, Session_GetDefaultProtocolVersion) { - StartSession(); + StartDefaultSession(); uint8_t protocol_version; EXPECT_TRUE(connection_->ProtocolVersion(session_id, protocol_version)); EXPECT_EQ(static_cast<uint8_t>(PROTOCOL_VERSION_2), protocol_version); } TEST_F(ConnectionTest, Session_UpdateProtocolVersion) { - StartSession(); + StartDefaultSession(); uint8_t protocol_version = static_cast<uint8_t>(PROTOCOL_VERSION_3); connection_->UpdateProtocolVersionSession(session_id, protocol_version); EXPECT_TRUE(connection_->ProtocolVersion(session_id, protocol_version)); @@ -157,7 +162,7 @@ TEST_F(ConnectionTest, Session_UpdateProtocolVersion) { TEST_F(ConnectionTest, HeartBeat_NotSupported) { // Arrange - StartSession(); + StartDefaultSession(); uint8_t protocol_version; EXPECT_TRUE(connection_->ProtocolVersion(session_id, protocol_version)); EXPECT_EQ(static_cast<uint8_t>(PROTOCOL_VERSION_2), protocol_version); diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h index 7eb17264eb..1bd919f30e 100644 --- a/src/components/include/connection_handler/connection_handler_observer.h +++ b/src/components/include/connection_handler/connection_handler_observer.h @@ -141,8 +141,21 @@ class ConnectionHandlerObserver { virtual void OnDeviceSwitchingFinish(const std::string& device_uid) = 0; #ifdef ENABLE_SECURITY + /** + * @brief Get unique handshake context by application id + * @param key id of application + * @return generated handshake context or empty context if application with + * provided id does not exist + */ virtual security_manager::SSLContext::HandshakeContext GetHandshakeContext( uint32_t key) const = 0; + + /** + * @brief Check if application with specified app_id has NAVIGATION HMI type + * @param app_id id of application to check + * @return true if application is navi otherwise returns false + */ + virtual bool CheckAppIsNavi(const uint32_t app_id) const = 0; #endif // ENABLE_SECURITY protected: /** diff --git a/src/components/include/protocol_handler/protocol_handler.h b/src/components/include/protocol_handler/protocol_handler.h index 34135617bd..6aafd7d53f 100644 --- a/src/components/include/protocol_handler/protocol_handler.h +++ b/src/components/include/protocol_handler/protocol_handler.h @@ -43,6 +43,8 @@ namespace protocol_handler { class ProtocolObserver; class SessionObserver; +struct SessionContext; + /** * \class ProtocolHandler * \brief Interface for component parsing protocol header @@ -121,7 +123,7 @@ class ProtocolHandler { * Only valid when generated_session_id is 0. Note, even if * generated_session_id is 0, the list may be empty. */ - virtual void NotifySessionStartedResult( + DEPRECATED virtual void NotifySessionStartedResult( int32_t connection_id, uint8_t session_id, uint8_t generated_session_id, @@ -129,6 +131,18 @@ class ProtocolHandler { bool protection, std::vector<std::string>& rejected_params) = 0; + /** + * @brief Called by connection handler to notify the context of + * OnSessionStartedCallback(). + * @param context reference to structure with started session data + * @param rejected_params list of parameters name that are rejected. + * Only valid when generated_session_id is 0. Note, even if + * generated_session_id is 0, the list may be empty. + */ + virtual void NotifySessionStarted( + const SessionContext& context, + std::vector<std::string>& rejected_params) = 0; + protected: /** * \brief Destructor diff --git a/src/components/include/protocol_handler/session_observer.h b/src/components/include/protocol_handler/session_observer.h index 4648e678c2..ccf000a18d 100644 --- a/src/components/include/protocol_handler/session_observer.h +++ b/src/components/include/protocol_handler/session_observer.h @@ -56,6 +56,60 @@ namespace protocol_handler { enum { HASH_ID_NOT_SUPPORTED = 0, HASH_ID_WRONG = 0xFFFF0000 }; /** + * @brief Struct with data containing attributes of starting session + **/ +struct SessionContext { + transport_manager::ConnectionUID connection_id_; + uint8_t initial_session_id_; + uint8_t new_session_id_; + protocol_handler::ServiceType service_type_; + uint32_t hash_id_; + bool is_protected_; + bool is_new_service_; + bool is_ptu_required_; + + /** + * @brief Constructor + */ + SessionContext() + : connection_id_(0) + , initial_session_id_(0) + , new_session_id_(0) + , service_type_(protocol_handler::kInvalidServiceType) + , hash_id_(0) + , is_protected_(false) + , is_new_service_(false) + , is_ptu_required_(false) {} + + /** + * @brief Constructor + * @param connection_id_ Connection identifier within which session is + * started. + * @param session_id Session ID specified to OnSessionStartedCallback() + * @param new_session_id Session ID generated + * @param service_type Type of service + * @param hash_id Hash ID generated from connection_handle and + * new_session_id + * @param is_protected Whether service will be protected + * @param is_new_service Whether service was already established + **/ + SessionContext(transport_manager::ConnectionUID connection_id, + uint8_t session_id, + uint8_t new_session_id, + protocol_handler::ServiceType service_type, + uint32_t hash_id, + const bool is_protected) + : connection_id_(connection_id) + , initial_session_id_(session_id) + , new_session_id_(new_session_id) + , service_type_(service_type) + , hash_id_(hash_id) + , is_protected_(is_protected) + , is_new_service_(false) + , is_ptu_required_(false) {} +}; + +/** * \class SessionObserver * \brief Interface for making a bridge between ProtocolHandler and * ConnectionHandler components. @@ -88,7 +142,7 @@ class SessionObserver { /** * \brief Callback function used by ProtocolHandler * when Mobile Application initiates start of new session. - * Result must be notified through NotifySessionStartedResult(). + * Result must be notified through NotifySessionStartedContext(). * \param connection_handle Connection identifier within which session * has to be started. * \param sessionId Identifier of the session to be start @@ -273,6 +327,16 @@ class SessionObserver { const uint32_t& key, const protocol_handler::ServiceType& service_type) = 0; + /** + * @brief Check if session contains service with specified service type + * @param connection_key unique id of session to check + * @param service_type type of service to check + * @return true if session contains service with specified service type + */ + virtual bool SessionServiceExists( + const uint32_t connection_key, + const protocol_handler::ServiceType& service_type) const = 0; + virtual security_manager::SSLContext::HandshakeContext GetHandshakeContext( uint32_t key) const = 0; #endif // ENABLE_SECURITY diff --git a/src/components/include/security_manager/security_manager.h b/src/components/include/security_manager/security_manager.h index 8ed0ff2912..8f772f6a13 100644 --- a/src/components/include/security_manager/security_manager.h +++ b/src/components/include/security_manager/security_manager.h @@ -128,6 +128,24 @@ class SecurityManager : public protocol_handler::ProtocolObserver { virtual void StartHandshake(uint32_t connection_key) = 0; /** + * @brief Check whether certificate should be updated + * @return true if certificate should be updated otherwise false + */ + virtual bool IsCertificateUpdateRequired() = 0; + + /** + * @brief Notify all listeners that certificate update required + * Allows to notify that certificate should be updated + */ + virtual void NotifyOnCertificateUpdateRequired() = 0; + + /** + * @brief Check if policy certificate data is empty + * @return true if policy certificate data is empty otherwise false + */ + virtual bool IsPolicyCertificateDataEmpty() = 0; + + /** * \brief Add/Remove for SecurityManagerListener */ virtual void AddListener(SecurityManagerListener* const listener) = 0; diff --git a/src/components/include/security_manager/security_manager_listener.h b/src/components/include/security_manager/security_manager_listener.h index 577c7c4378..aeb3334a56 100644 --- a/src/components/include/security_manager/security_manager_listener.h +++ b/src/components/include/security_manager/security_manager_listener.h @@ -31,6 +31,9 @@ */ #ifndef SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_SECURITY_MANAGER_LISTENER_H_ #define SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_SECURITY_MANAGER_LISTENER_H_ + +#include <string> + namespace security_manager { class SecurityManagerListener { @@ -48,6 +51,14 @@ class SecurityManagerListener { * @brief Notify listeners that certificate update is required. */ virtual void OnCertificateUpdateRequired() = 0; + + /** + * @brief Get certificate data from policy + * @param reference to string where to save certificate data + * @return true if listener saved some data to string otherwise false + */ + virtual bool GetPolicyCertificateData(std::string& data) const = 0; + virtual ~SecurityManagerListener() {} }; } // namespace security_manager diff --git a/src/components/include/test/connection_handler/mock_connection_handler_observer.h b/src/components/include/test/connection_handler/mock_connection_handler_observer.h index bb5ad7cad0..1e92106688 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler_observer.h +++ b/src/components/include/test/connection_handler/mock_connection_handler_observer.h @@ -48,11 +48,10 @@ class MockConnectionHandlerObserver MOCK_METHOD0(OnFindNewApplicationsRequest, void()); MOCK_METHOD1(RemoveDevice, void(const connection_handler::DeviceHandle& device_handle)); - DEPRECATED MOCK_METHOD3( - OnServiceStartedCallback, - bool(const connection_handler::DeviceHandle& device_handle, - const int32_t& session_key, - const protocol_handler::ServiceType& type)); + DEPRECATED MOCK_METHOD3(OnServiceStartedCallback, + bool(const connection_handler::DeviceHandle& device_handle, + const int32_t& session_key, + const protocol_handler::ServiceType& type)); MOCK_METHOD4(OnServiceStartedCallback, void(const connection_handler::DeviceHandle& device_handle, const int32_t& session_key, @@ -71,6 +70,7 @@ class MockConnectionHandlerObserver void(const connection_handler::Device& device_from, const connection_handler::Device& device_to)); MOCK_METHOD1(OnDeviceSwitchingFinish, void(const std::string& device_uid)); + MOCK_CONST_METHOD1(CheckAppIsNavi, bool(const uint32_t app_id)); }; } // namespace connection_handler_test diff --git a/src/components/include/test/protocol_handler/mock_protocol_handler.h b/src/components/include/test/protocol_handler/mock_protocol_handler.h index 37fbbb9742..12f8279ded 100644 --- a/src/components/include/test/protocol_handler/mock_protocol_handler.h +++ b/src/components/include/test/protocol_handler/mock_protocol_handler.h @@ -62,13 +62,16 @@ class MockProtocolHandler : public ::protocol_handler::ProtocolHandler { MOCK_CONST_METHOD0(get_settings, const ::protocol_handler::ProtocolHandlerSettings&()); MOCK_METHOD0(get_session_observer, protocol_handler::SessionObserver&()); - MOCK_METHOD6(NotifySessionStartedResult, + DEPRECATED MOCK_METHOD6(NotifySessionStartedResult, void(int32_t connection_id, uint8_t session_id, uint8_t generated_session_id, uint32_t hash_id, bool protection, std::vector<std::string>& rejected_params)); + MOCK_METHOD2(NotifySessionStarted, + void(const ::protocol_handler::SessionContext& context, + std::vector<std::string>& rejected_params)); }; } // namespace protocol_handler_test } // namespace components diff --git a/src/components/include/test/protocol_handler/mock_session_observer.h b/src/components/include/test/protocol_handler/mock_session_observer.h index 350704ae86..3d54b97fad 100644 --- a/src/components/include/test/protocol_handler/mock_session_observer.h +++ b/src/components/include/test/protocol_handler/mock_session_observer.h @@ -126,6 +126,9 @@ class MockSessionObserver : public ::protocol_handler::SessionObserver { MOCK_METHOD2(SetProtectionFlag, void(const uint32_t& key, const protocol_handler::ServiceType& service_type)); + MOCK_CONST_METHOD2(SessionServiceExists, + bool(const uint32_t connection_key, + const protocol_handler::ServiceType& service_type)); MOCK_CONST_METHOD1( GetHandshakeContext, security_manager::SSLContext::HandshakeContext(uint32_t key)); diff --git a/src/components/include/test/security_manager/mock_security_manager.h b/src/components/include/test/security_manager/mock_security_manager.h index e3d95cd94f..11890cb071 100644 --- a/src/components/include/test/security_manager/mock_security_manager.h +++ b/src/components/include/test/security_manager/mock_security_manager.h @@ -65,6 +65,9 @@ class MockSecurityManager : public ::security_manager::SecurityManager { void(const ::protocol_handler::RawMessagePtr)); MOCK_METHOD1(OnMobileMessageSent, void(const ::protocol_handler::RawMessagePtr)); + MOCK_METHOD0(IsCertificateUpdateRequired, bool()); + MOCK_METHOD0(NotifyOnCertificateUpdateRequired, void()); + MOCK_METHOD0(IsPolicyCertificateDataEmpty, bool()); }; /* diff --git a/src/components/include/test/security_manager/mock_security_manager_listener.h b/src/components/include/test/security_manager/mock_security_manager_listener.h index 9e5dd03698..a06762a09d 100644 --- a/src/components/include/test/security_manager/mock_security_manager_listener.h +++ b/src/components/include/test/security_manager/mock_security_manager_listener.h @@ -48,6 +48,7 @@ class MockSecurityManagerListener bool(uint32_t connection_key, ::security_manager::SSLContext::HandshakeResult result)); MOCK_METHOD0(OnCertificateUpdateRequired, void()); + MOCK_CONST_METHOD1(GetPolicyCertificateData, bool(std::string& data)); }; } // namespace security_manager_test } // namespace components diff --git a/src/components/protocol_handler/include/protocol_handler/handshake_handler.h b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h new file mode 100644 index 0000000000..0ef40290f2 --- /dev/null +++ b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_START_SESSION_HANDLER_H_ +#define SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_START_SESSION_HANDLER_H_ + +#include <memory> + +#include "protocol_handler/protocol_handler_impl.h" +#include "protocol_handler/protocol_packet.h" +#include "protocol_handler/session_observer.h" +#include "security_manager/security_manager_listener.h" + +namespace protocol_handler { + +class ProtocolHandlerImpl; + +/** + * @brief HandshakeHandler class for handling SSL handshake and sending + * Ack/Nack on its success or fail + */ +class HandshakeHandler : public security_manager::SecurityManagerListener { + public: + DEPRECATED HandshakeHandler(ProtocolHandlerImpl& protocol_handler, + SessionObserver& session_observer, + uint32_t connection_key, + ConnectionID connection_id, + uint8_t session_id, + uint8_t protocol_version, + uint32_t hash_id, + ServiceType service_type, + const std::vector<int>& force_protected_service, + const bool is_new_service, + ProtocolPacket::ProtocolVersion& full_version, + std::shared_ptr<uint8_t> payload); + + HandshakeHandler(ProtocolHandlerImpl& protocol_handler, + SessionObserver& session_observer, + ProtocolPacket::ProtocolVersion& full_version, + const SessionContext& context, + const uint8_t protocol_version, + std::shared_ptr<uint8_t> payload); + + ~HandshakeHandler(); + + /** + * @brief Get certificate data from policy + * @param reference to string where to save certificate data + * @return true if listener saved some data to string otherwise false + */ + bool GetPolicyCertificateData(std::string& data) const OVERRIDE; + + /** + * @brief Notification about protection result + * @param connection_key Unique key of session which triggrs handshake + * @param result result of connection protection + * @return true on success notification handling or false otherwise + */ + bool OnHandshakeDone( + uint32_t connection_key, + security_manager::SSLContext::HandshakeResult result) OVERRIDE; + + /** + * @brief Notification that certificate update is required. + */ + void OnCertificateUpdateRequired() OVERRIDE; + + /** + * @brief Get connection key of this handler + * @return connection key + */ + uint32_t connection_key() const; + + private: + /** + * @brief Performs related actions if handshake was successfully finished + * @param connection_key Unique key of session which triggrs handshake + * @param params set of params used in bson part of message + */ + void ProcessSuccessfulHandshake(const uint32_t connection_key, + BsonObject& params); + + /** + * @brief Performs related actions if handshake was failed + * @param params set of params used in bson part of message + */ + void ProcessFailedHandshake(BsonObject& params); + + ProtocolHandlerImpl& protocol_handler_; + SessionObserver& session_observer_; + SessionContext context_; + ProtocolPacket::ProtocolVersion full_version_; + const uint8_t protocol_version_; + std::shared_ptr<uint8_t> payload_; +}; + +} // namespace protocol_handler + +#endif // SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_START_SESSION_HANDLER_H_ 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 90aad65ed4..0efb81cdd7 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 @@ -56,6 +56,7 @@ #include "transport_manager/transport_manager.h" #include "transport_manager/transport_manager_listener_empty.h" #include "connection_handler/connection_handler.h" +#include "application_manager/policies/policy_handler_observer.h" #ifdef TELEMETRY_MONITOR #include "protocol_handler/telemetry_observer.h" @@ -64,6 +65,7 @@ #ifdef ENABLE_SECURITY #include "security_manager/security_manager.h" +#include "protocol_handler/handshake_handler.h" #endif // ENABLE_SECURITY namespace connection_handler { @@ -77,6 +79,7 @@ class ConnectionHandlerImpl; namespace protocol_handler { class ProtocolObserver; class SessionObserver; +class HandshakeHandler; class MessagesFromMobileAppHandler; class MessagesToMobileAppHandler; @@ -141,6 +144,7 @@ typedef threads::MessageLoopThread< class ProtocolHandlerImpl : public ProtocolHandler, public TransportManagerListenerEmpty, + public policy::PolicyHandlerObserver, public impl::FromMobileQueue::Handler, public impl::ToMobileQueue::Handler #ifdef TELEMETRY_MONITOR @@ -389,7 +393,7 @@ class ProtocolHandlerImpl * Only valid when generated_session_id is 0. Note, even if * generated_session_id is 0, the list may be empty. */ - void NotifySessionStartedResult( + DEPRECATED void NotifySessionStartedResult( int32_t connection_id, uint8_t session_id, uint8_t generated_session_id, @@ -397,6 +401,17 @@ class ProtocolHandlerImpl bool protection, std::vector<std::string>& rejected_params) OVERRIDE; + /** + * @brief Called by connection handler to notify the result of + * OnSessionStartedCallback(). + * @param context reference to structure with started session data + * @param rejected_params list of parameters name that are rejected. + * Only valid when generated_session_id is 0. Note, even if + * generated_session_id is 0, the list may be empty. + */ + void NotifySessionStarted(const SessionContext& context, + std::vector<std::string>& rejected_params) OVERRIDE; + #ifdef BUILD_TESTS const impl::FromMobileQueue& get_from_mobile_queue() const { return raw_ford_messages_from_mobile_; @@ -458,6 +473,14 @@ class ProtocolHandlerImpl const transport_manager::ConnectionUID connection_id) OVERRIDE; /** + * @brief OnPTUFinished the callback which signals PTU has finished + * + * @param ptu_result the result from the PTU - true if successful, + * otherwise false. + */ + void OnPTUFinished(const bool ptu_result) OVERRIDE; + + /** * @brief Notifies subscribers about message * received from mobile device. * @param message Message with already parsed header. @@ -660,6 +683,10 @@ class ProtocolHandlerImpl #ifdef ENABLE_SECURITY security_manager::SecurityManager* security_manager_; + + bool is_ptu_triggered_; + std::list<std::shared_ptr<HandshakeHandler> > ptu_pending_handlers_; + sync_primitives::Lock ptu_handlers_lock_; #endif // ENABLE_SECURITY // Thread that pumps non-parsed messages coming from mobile side. diff --git a/src/components/protocol_handler/src/handshake_handler.cc b/src/components/protocol_handler/src/handshake_handler.cc new file mode 100644 index 0000000000..055ff2cf45 --- /dev/null +++ b/src/components/protocol_handler/src/handshake_handler.cc @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2017, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "protocol_handler/handshake_handler.h" + +#include <bson_object.h> + +#include "protocol_handler/protocol_handler_impl.h" +#include "protocol_handler/protocol_packet.h" +#include "security_manager/security_manager.h" +#include "protocol_handler/session_observer.h" + +namespace protocol_handler { + +CREATE_LOGGERPTR_GLOBAL(logger_, "ProtocolHandler") + +HandshakeHandler::HandshakeHandler( + ProtocolHandlerImpl& protocol_handler, + SessionObserver& session_observer, + uint32_t connection_key, + ConnectionID connection_id, + uint8_t session_id, + uint8_t protocol_version, + uint32_t hash_id, + ServiceType service_type, + const std::vector<int>& force_protected_service, + const bool is_new_service, + ProtocolPacket::ProtocolVersion& full_version, + std::shared_ptr<uint8_t> payload) + : protocol_handler_(protocol_handler) + , session_observer_(session_observer) + , context_() + , full_version_(full_version) + , protocol_version_(protocol_version) + , payload_(payload) {} + +HandshakeHandler::HandshakeHandler( + ProtocolHandlerImpl& protocol_handler, + SessionObserver& session_observer, + ProtocolPacket::ProtocolVersion& full_version, + const SessionContext& context, + const uint8_t protocol_version, + std::shared_ptr<uint8_t> payload) + : protocol_handler_(protocol_handler) + , session_observer_(session_observer) + , context_(context) + , full_version_(full_version) + , protocol_version_(protocol_version) + , payload_(payload) {} + +HandshakeHandler::~HandshakeHandler() { + LOG4CXX_DEBUG(logger_, "Destroying of HandshakeHandler: " << this); +} + +uint32_t HandshakeHandler::connection_key() const { + return session_observer_.KeyFromPair(context_.connection_id_, + context_.new_session_id_); +} + +bool HandshakeHandler::GetPolicyCertificateData(std::string& data) const { + return false; +} + +void HandshakeHandler::OnCertificateUpdateRequired() {} + +bool HandshakeHandler::OnHandshakeDone( + uint32_t connection_key, + security_manager::SSLContext::HandshakeResult result) { + LOG4CXX_AUTO_TRACE(logger_); + + if (connection_key != this->connection_key()) { + LOG4CXX_DEBUG(logger_, + "Listener " << this + << " expects notification for connection id: " + << this->connection_key() + << ". Received notification for connection id " + << connection_key << " will be ignored"); + return false; + } + + const bool success = + result == security_manager::SSLContext::Handshake_Result_Success; + + BsonObject params; + if (payload_) { + params = bson_object_from_bytes(payload_.get()); + } else { + bson_object_initialize_default(¶ms); + } + + if (success) { + ProcessSuccessfulHandshake(connection_key, params); + } else { + ProcessFailedHandshake(params); + } + + bson_object_deinitialize(¶ms); + return true; +} + +void HandshakeHandler::ProcessSuccessfulHandshake(const uint32_t connection_key, + BsonObject& params) { + LOG4CXX_AUTO_TRACE(logger_); + const std::vector<int>& force_unprotected = + protocol_handler_.get_settings().force_unprotected_service(); + + const bool can_be_protected = + std::find(force_unprotected.begin(), + force_unprotected.end(), + context_.service_type_) == force_unprotected.end(); + + const bool is_service_already_protected = + session_observer_.GetSSLContext(connection_key, context_.service_type_) != + NULL; + + LOG4CXX_DEBUG(logger_, + "Service can be protected: " << can_be_protected + << " and service was protected: " + << is_service_already_protected); + + if (can_be_protected && !is_service_already_protected) { + session_observer_.SetProtectionFlag(connection_key, context_.service_type_); + protocol_handler_.SendStartSessionAck(context_.connection_id_, + context_.new_session_id_, + protocol_version_, + context_.hash_id_, + context_.service_type_, + can_be_protected, + full_version_, + params); + } else { + protocol_handler_.SendStartSessionNAck(context_.connection_id_, + context_.new_session_id_, + protocol_version_, + context_.service_type_); + } +} + +void HandshakeHandler::ProcessFailedHandshake(BsonObject& params) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Handshake failed"); + const std::vector<int>& force_protected = + protocol_handler_.get_settings().force_protected_service(); + + const bool can_be_unprotected = + std::find(force_protected.begin(), + force_protected.end(), + context_.service_type_) == force_protected.end(); + + LOG4CXX_DEBUG(logger_, + "Service can be unprotected: " << can_be_unprotected + << " and this is a new service: " + << context_.is_new_service_); + + if (can_be_unprotected && context_.is_new_service_) { + protocol_handler_.SendStartSessionAck(context_.connection_id_, + context_.new_session_id_, + protocol_version_, + context_.hash_id_, + context_.service_type_, + PROTECTION_OFF, + full_version_, + params); + } else { + protocol_handler_.SendStartSessionNAck(context_.connection_id_, + context_.new_session_id_, + protocol_version_, + context_.service_type_); + } +} + +} // namespace protocol_handler diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index 0c4b72b535..47d546657f 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -77,8 +77,9 @@ ProtocolHandlerImpl::ProtocolHandlerImpl( security_manager_(NULL) , #endif // ENABLE_SECURITY - raw_ford_messages_from_mobile_( - "PH FromMobile", this, threads::ThreadOptions(kStackSize)) + is_ptu_triggered_(false) + , raw_ford_messages_from_mobile_( + "PH FromMobile", this, threads::ThreadOptions(kStackSize)) , raw_ford_messages_to_mobile_( "PH ToMobile", this, threads::ThreadOptions(kStackSize)) , start_session_frame_map_lock_() @@ -838,6 +839,59 @@ void ProtocolHandlerImpl::OnConnectionClosed( multiframe_builder_.RemoveConnection(connection_id); } +void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { + LOG4CXX_AUTO_TRACE(logger_); + +#ifdef ENABLE_SECURITY + sync_primitives::AutoLock lock(ptu_handlers_lock_); + + if (!is_ptu_triggered_) { + LOG4CXX_ERROR(logger_, + "PTU was not triggered by service starting. Ignored"); + return; + } + + const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired(); + for (auto handler : ptu_pending_handlers_) { + security_manager::SSLContext* ssl_context = + is_cert_expired + ? NULL + : security_manager_->CreateSSLContext(handler->connection_key()); + + if (!ssl_context) { + const std::string error("CreateSSLContext failed"); + LOG4CXX_ERROR(logger_, error); + security_manager_->SendInternalError( + handler->connection_key(), + security_manager::SecurityManager::ERROR_INTERNAL, + error); + + handler->OnHandshakeDone( + handler->connection_key(), + security_manager::SSLContext::Handshake_Result_Fail); + + continue; + } + + if (ssl_context->IsInitCompleted()) { + handler->OnHandshakeDone( + handler->connection_key(), + security_manager::SSLContext::Handshake_Result_Success); + } else { + security_manager_->AddListener(new HandshakeHandler(*handler)); + if (!ssl_context->IsHandshakePending()) { + // Start handshake process + security_manager_->StartHandshake(handler->connection_key()); + } + } + } + + LOG4CXX_DEBUG(logger_, "Handshake handlers were notified"); + ptu_pending_handlers_.clear(); + is_ptu_triggered_ = false; +#endif // ENABLE_SECURITY +} + RESULT_CODE ProtocolHandlerImpl::SendFrame(const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); if (!packet) { @@ -1188,125 +1242,6 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndServiceACK( return RESULT_OK; } -#ifdef ENABLE_SECURITY -namespace { -/** - * \brief SecurityManagerListener for send Ack/NAck on success or fail - * SSL handshake - */ -class StartSessionHandler : public security_manager::SecurityManagerListener { - public: - StartSessionHandler(uint32_t connection_key, - ProtocolHandlerImpl* protocol_handler, - SessionObserver& session_observer, - ConnectionID connection_id, - int32_t session_id, - uint8_t protocol_version, - uint32_t hash_id, - ServiceType service_type, - const std::vector<int>& force_protected_service) - : connection_key_(connection_key) - , protocol_handler_(protocol_handler) - , session_observer_(session_observer) - , connection_id_(connection_id) - , session_id_(session_id) - , protocol_version_(protocol_version) - , hash_id_(hash_id) - , service_type_(service_type) - , force_protected_service_(force_protected_service) - , full_version_() - , payload_(NULL) {} - StartSessionHandler(uint32_t connection_key, - ProtocolHandlerImpl* protocol_handler, - SessionObserver& session_observer, - ConnectionID connection_id, - int32_t session_id, - uint8_t protocol_version, - uint32_t hash_id, - ServiceType service_type, - const std::vector<int>& force_protected_service, - ProtocolPacket::ProtocolVersion& full_version, - uint8_t* payload) - : connection_key_(connection_key) - , protocol_handler_(protocol_handler) - , session_observer_(session_observer) - , connection_id_(connection_id) - , session_id_(session_id) - , protocol_version_(protocol_version) - , hash_id_(hash_id) - , service_type_(service_type) - , force_protected_service_(force_protected_service) - , full_version_(full_version) - , payload_(payload) {} - - bool OnHandshakeDone( - const uint32_t connection_key, - security_manager::SSLContext::HandshakeResult result) OVERRIDE { - if (connection_key != connection_key_) { - delete[] payload_; - return false; - } - const bool success = - result == security_manager::SSLContext::Handshake_Result_Success; - // check current service protection - const bool was_service_protection_enabled = - session_observer_.GetSSLContext(connection_key_, service_type_) != NULL; - if (was_service_protection_enabled) { - if (!success) { - protocol_handler_->SendStartSessionNAck( - connection_id_, session_id_, protocol_version_, service_type_); - } else { - // Could not be success handshake and not already protected service - NOTREACHED(); - } - } else { - if (success) { - session_observer_.SetProtectionFlag(connection_key_, service_type_); - } - BsonObject params; - if (payload_ != NULL) { - params = bson_object_from_bytes(payload_); - } else { - bson_object_initialize_default(¶ms); - } - protocol_handler_->SendStartSessionAck(connection_id_, - session_id_, - protocol_version_, - hash_id_, - service_type_, - success, - full_version_, - params); - bson_object_deinitialize(¶ms); - } - delete[] payload_; - delete this; - return true; - } - - void OnCertificateUpdateRequired() OVERRIDE {} - - virtual const std::vector<int>& force_protected_service() const { - return force_protected_service_; - } - - private: - const uint32_t connection_key_; - ProtocolHandlerImpl* protocol_handler_; - SessionObserver& session_observer_; - - const ConnectionID connection_id_; - const int32_t session_id_; - const uint8_t protocol_version_; - const uint32_t hash_id_; - const ServiceType service_type_; - const std::vector<int> force_protected_service_; - ProtocolPacket::ProtocolVersion full_version_; - uint8_t* payload_; -}; -} // namespace -#endif // ENABLE_SECURITY - // Suppress warning for deprecated method used within another deprecated method #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -1404,17 +1339,18 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( *fullVersion); } else { security_manager_->AddListener( - new StartSessionHandler(connection_key, - this, - session_observer_, - connection_id, - session_id, - packet.protocol_version(), - hash_id, - service_type, - get_settings().force_protected_service(), - *fullVersion, - NULL)); + new HandshakeHandler(*this, + session_observer_, + connection_key, + connection_id, + session_id, + packet.protocol_version(), + hash_id, + service_type, + get_settings().force_protected_service(), + false, + *fullVersion, + NULL)); if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); @@ -1512,11 +1448,25 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( uint32_t hash_id, bool protection, std::vector<std::string>& rejected_params) { + LOG4CXX_AUTO_TRACE(logger_); + protocol_handler::SessionContext context(connection_id, + session_id, + generated_session_id, + ServiceType::kInvalidServiceType, + hash_id, + protection); + NotifySessionStarted(context, rejected_params); +} + +void ProtocolHandlerImpl::NotifySessionStarted( + const SessionContext& context, std::vector<std::string>& rejected_params) { + LOG4CXX_AUTO_TRACE(logger_); + ProtocolFramePtr packet; { sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_); StartSessionFrameMap::iterator it = start_session_frame_map_.find( - std::make_pair(connection_id, session_id)); + std::make_pair(context.connection_id_, context.initial_session_id_)); if (it == start_session_frame_map_.end()) { LOG4CXX_ERROR(logger_, "Cannot find Session Started packet"); return; @@ -1528,11 +1478,11 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( const ServiceType service_type = ServiceTypeFromByte(packet->service_type()); const uint8_t protocol_version = packet->protocol_version(); - if (0 == generated_session_id) { + if (0 == context.new_session_id_) { LOG4CXX_WARN(logger_, "Refused by session_observer to create service " << static_cast<int32_t>(service_type) << " type."); - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), @@ -1540,8 +1490,9 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( return; } - BsonObject start_session_ack_params; - bson_object_initialize_default(&start_session_ack_params); + std::shared_ptr<BsonObject> start_session_ack_params( + new BsonObject(), [](BsonObject* obj) { bson_object_deinitialize(obj); }); + bson_object_initialize_default(start_session_ack_params.get()); // when video service is successfully started, copy input parameters // ("width", "height", "videoProtocol", "videoCodec") to the ACK packet if (packet->service_type() == kMobileNav && packet->data() != NULL) { @@ -1550,13 +1501,13 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( if ((element = bson_object_get(&req_param, strings::height)) != NULL && element->type == TYPE_INT32) { - bson_object_put_int32(&start_session_ack_params, + bson_object_put_int32(start_session_ack_params.get(), strings::height, bson_object_get_int32(&req_param, strings::height)); } if ((element = bson_object_get(&req_param, strings::width)) != NULL && element->type == TYPE_INT32) { - bson_object_put_int32(&start_session_ack_params, + bson_object_put_int32(start_session_ack_params.get(), strings::width, bson_object_get_int32(&req_param, strings::width)); } @@ -1564,17 +1515,17 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( bson_object_get_string(&req_param, strings::video_protocol); if (protocol != NULL) { bson_object_put_string( - &start_session_ack_params, strings::video_protocol, protocol); + start_session_ack_params.get(), strings::video_protocol, protocol); } char* codec = bson_object_get_string(&req_param, strings::video_codec); if (codec != NULL) { bson_object_put_string( - &start_session_ack_params, strings::video_codec, codec); + start_session_ack_params.get(), strings::video_codec, codec); } bson_object_deinitialize(&req_param); } - ProtocolPacket::ProtocolVersion* fullVersion; + std::shared_ptr<ProtocolPacket::ProtocolVersion> fullVersion; // Can't check protocol_version because the first packet is v1, but there // could still be a payload, in which case we can get the real protocol @@ -1584,24 +1535,68 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( char* version_param = bson_object_get_string(&request_params, strings::protocol_version); std::string version_string(version_param == NULL ? "" : version_param); - fullVersion = new ProtocolPacket::ProtocolVersion(version_string); + fullVersion = + std::make_shared<ProtocolPacket::ProtocolVersion>(version_string); // Constructed payloads added in Protocol v5 if (fullVersion->majorVersion < PROTOCOL_VERSION_5) { rejected_params.push_back(std::string(strings::protocol_version)); } bson_object_deinitialize(&request_params); } else { - fullVersion = new ProtocolPacket::ProtocolVersion(); + fullVersion = std::make_shared<ProtocolPacket::ProtocolVersion>(); } #ifdef ENABLE_SECURITY // for packet is encrypted and security plugin is enable - if (protection && security_manager_) { - const uint32_t connection_key = - session_observer_.KeyFromPair(connection_id, generated_session_id); + if (context.is_protected_ && security_manager_) { + const uint32_t connection_key = session_observer_.KeyFromPair( + context.connection_id_, context.new_session_id_); + + std::shared_ptr<uint8_t> bson_object_bytes( + bson_object_to_bytes(start_session_ack_params.get()), + [](uint8_t* p) { delete[] p; }); + + std::shared_ptr<HandshakeHandler> handler = + std::make_shared<HandshakeHandler>(*this, + session_observer_, + *fullVersion, + context, + packet->protocol_version(), + bson_object_bytes); + + 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 " + << handler.get() + << " is required and certificate data is empty"); + + sync_primitives::AutoLock lock(ptu_handlers_lock_); + if (!is_ptu_triggered_) { + LOG4CXX_DEBUG(logger_, + "PTU is not triggered yet. " + << "Starting PTU and postponing SSL handshake"); + + ptu_pending_handlers_.push_back(handler); + is_ptu_triggered_ = true; + security_manager_->NotifyOnCertificateUpdateRequired(); + } else { + LOG4CXX_DEBUG(logger_, "PTU has been triggered. Added to pending."); + ptu_pending_handlers_.push_back(handler); + } + return; + } security_manager::SSLContext* ssl_context = - security_manager_->CreateSSLContext(connection_key); + is_certificate_expired + ? NULL + : security_manager_->CreateSSLContext(connection_key); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -1609,22 +1604,15 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( connection_key, security_manager::SecurityManager::ERROR_INTERNAL, error); - // Start service without protection - SendStartSessionAck(connection_id, - generated_session_id, - packet->protocol_version(), - hash_id, - packet->service_type(), - PROTECTION_OFF, - *fullVersion, - start_session_ack_params); - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); + + handler->OnHandshakeDone( + connection_key, security_manager::SSLContext::Handshake_Result_Fail); + return; } if (!rejected_params.empty()) { - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), @@ -1633,36 +1621,21 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( // mark service as protected session_observer_.SetProtectionFlag(connection_key, service_type); // Start service as protected with current SSLContext - SendStartSessionAck(connection_id, - generated_session_id, + SendStartSessionAck(context.connection_id_, + context.new_session_id_, packet->protocol_version(), - hash_id, + context.hash_id_, packet->service_type(), PROTECTION_ON, *fullVersion, - start_session_ack_params); + *start_session_ack_params); } else { - // Need a copy because fullVersion will be deleted - ProtocolPacket::ProtocolVersion fullVersionCopy(*fullVersion); - security_manager_->AddListener(new StartSessionHandler( - connection_key, - this, - session_observer_, - connection_id, - generated_session_id, - packet->protocol_version(), - hash_id, - service_type, - get_settings().force_protected_service(), - fullVersionCopy, - bson_object_to_bytes(&start_session_ack_params))); + security_manager_->AddListener(new HandshakeHandler(*handler)); if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); } } - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); LOG4CXX_DEBUG(logger_, "Protection establishing for connection " << connection_key << " is in progress"); @@ -1670,23 +1643,21 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( } #endif // ENABLE_SECURITY if (rejected_params.empty()) { - SendStartSessionAck(connection_id, - generated_session_id, + SendStartSessionAck(context.connection_id_, + context.new_session_id_, packet->protocol_version(), - hash_id, + context.hash_id_, packet->service_type(), PROTECTION_OFF, *fullVersion, - start_session_ack_params); + *start_session_ack_params); } else { - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), rejected_params); } - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); } RESULT_CODE ProtocolHandlerImpl::HandleControlMessageHeartBeat( 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 d7850e4df1..cb11eca887 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -105,6 +105,7 @@ using ::testing::An; using ::testing::AnyOf; using ::testing::ByRef; using ::testing::DoAll; +using ::testing::SaveArg; using ::testing::Eq; using ::testing::_; using ::testing::Invoke; @@ -114,12 +115,14 @@ using ::testing::SetArgPointee; typedef std::vector<uint8_t> UCharDataVector; // custom action to call a member function with 6 arguments -ACTION_P8(InvokeMemberFuncWithArg6, ptr, memberFunc, a, b, c, d, e, f) { - (ptr->*memberFunc)(a, b, c, d, e, f); +ACTION_P4(InvokeMemberFuncWithArg2, ptr, memberFunc, a, b) { + (ptr->*memberFunc)(a, b); } namespace { const uint32_t kAsyncExpectationsTimeout = 10000u; +const uint32_t kMicrosecondsInMillisecond = 1000u; +const uint32_t kAddSessionWaitTimeMs = 100u; } class ProtocolHandlerImplTest : public ::testing::Test { @@ -145,6 +148,13 @@ class ProtocolHandlerImplTest : public ::testing::Test { .WillByDefault(Return(malformd_max_messages)); ON_CALL(protocol_handler_settings_mock, multiframe_waiting_timeout()) .WillByDefault(Return(multiframe_waiting_timeout)); +#ifdef ENABLE_SECURITY + ON_CALL(protocol_handler_settings_mock, force_protected_service()) + .WillByDefault(ReturnRefOfCopy(force_protected_services)); + ON_CALL(protocol_handler_settings_mock, force_unprotected_service()) + .WillByDefault(ReturnRefOfCopy(force_unprotected_services)); +#endif + protocol_handler_impl.reset( new ProtocolHandlerImpl(protocol_handler_settings_mock, session_observer_mock, @@ -189,6 +199,21 @@ class ProtocolHandlerImplTest : public ::testing::Test { connection_id); } + protocol_handler::SessionContext GetSessionContext( + const transport_manager::ConnectionUID connection_id, + const uint8_t initial_session_id, + const uint8_t new_session_id, + const protocol_handler::ServiceType service_type, + const uint32_t hash_id, + const bool protection_flag) { + return protocol_handler::SessionContext(connection_id, + initial_session_id, + new_session_id, + service_type, + hash_id, + protection_flag); + } + void AddSession(const ::utils::SharedPtr<TestAsyncWaiter>& waiter, uint32_t& times) { using namespace protocol_handler; @@ -206,6 +231,14 @@ class ProtocolHandlerImplTest : public ::testing::Test { const bool callback_protection_flag = PROTECTION_OFF; #endif // ENABLE_SECURITY + const protocol_handler::SessionContext context = + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + callback_protection_flag); + // Expect ConnectionHandler check EXPECT_CALL(session_observer_mock, OnSessionStartedCallback(connection_id, @@ -215,16 +248,12 @@ class ProtocolHandlerImplTest : public ::testing::Test { An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll(NotifyTestAsyncWaiter(waiter), - InvokeMemberFuncWithArg6( - protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - callback_protection_flag, - ByRef(empty_rejected_param_)))); + WillOnce(DoAll( + NotifyTestAsyncWaiter(waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + context, + ByRef(empty_rejected_param_)))); times++; // Expect send Ack with PROTECTION_OFF (on no Security Manager) @@ -236,6 +265,8 @@ class ProtocolHandlerImplTest : public ::testing::Test { SendControlMessage( PROTECTION_ON, start_service, NEW_SESSION_ID, FRAME_DATA_START_SERVICE); + + usleep(kAddSessionWaitTimeMs * kMicrosecondsInMillisecond); } #ifdef ENABLE_SECURITY @@ -316,6 +347,8 @@ class ProtocolHandlerImplTest : public ::testing::Test { testing::NiceMock<security_manager_test::MockSecurityManager> security_manager_mock; testing::NiceMock<security_manager_test::MockSSLContext> ssl_context_mock; + std::vector<int> force_protected_services; + std::vector<int> force_unprotected_services; #endif // ENABLE_SECURITY std::vector<std::string> empty_rejected_param_; }; @@ -371,6 +404,7 @@ TEST_F(ProtocolHandlerImplTest, TestAsyncWaiter waiter; uint32_t times = 0; + ServiceType service_type; // Expect ConnectionHandler check EXPECT_CALL( session_observer_mock, @@ -382,16 +416,18 @@ TEST_F(ProtocolHandlerImplTest, .Times(call_times) . // Return sessions start rejection - WillRepeatedly(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - SESSION_START_REJECT, - HASH_ID_WRONG, - PROTECTION_OFF, - ByRef(empty_rejected_param_)))); + WillRepeatedly( + DoAll(NotifyTestAsyncWaiter(&waiter), + SaveArg<2>(&service_type), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + SESSION_START_REJECT, + service_type, + HASH_ID_WRONG, + PROTECTION_OFF), + ByRef(empty_rejected_param_)))); times += call_times; // Expect send NAck @@ -436,6 +472,7 @@ TEST_F(ProtocolHandlerImplTest, StartSession_Protected_SessionObserverReject) { TestAsyncWaiter waiter; uint32_t times = 0; + ServiceType service_type; // Expect ConnectionHandler check EXPECT_CALL( session_observer_mock, @@ -449,13 +486,15 @@ TEST_F(ProtocolHandlerImplTest, StartSession_Protected_SessionObserverReject) { // Return sessions start rejection WillRepeatedly(DoAll( NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - SESSION_START_REJECT, - HASH_ID_WRONG, - callback_protection_flag, + SaveArg<2>(&service_type), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + SESSION_START_REJECT, + service_type, + HASH_ID_WRONG, + callback_protection_flag), ByRef(empty_rejected_param_)))); times += call_times; @@ -501,16 +540,17 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_OFF, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_OFF), + ByRef(empty_rejected_param_)))); times++; SetProtocolVersion2(); @@ -614,7 +654,7 @@ TEST_F(ProtocolHandlerImplTest, start_service, PROTECTION_OFF, An<const BsonObject*>())) - // don't call NotifySessionStartedResult() immediately, instead call it + // don't call NotifySessionStartedContext() immediately, instead call it // after second OnSessionStartedCallback() .WillOnce(NotifyTestAsyncWaiter(&waiter)); times++; @@ -640,21 +680,23 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) .WillOnce(DoAll( NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id2, - session_id2, - SESSION_START_REJECT, - HASH_ID_WRONG, - PROTECTION_OFF, + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id2, + session_id2, + SESSION_START_REJECT, + start_service, + HASH_ID_WRONG, + PROTECTION_OFF), ByRef(rejected_param_list)), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id1, - session_id1, - generated_session_id1, - HASH_ID_WRONG, - PROTECTION_OFF, + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id1, + session_id1, + generated_session_id1, + start_service, + HASH_ID_WRONG, + PROTECTION_OFF), ByRef(empty_rejected_param_)))); times++; @@ -802,10 +844,6 @@ TEST_F(ProtocolHandlerImplTest, EndSession_Success) { } #ifdef ENABLE_SECURITY -/* - * ProtocolHandler shall not call Security logics with Protocol version 1 - * Check session_observer with PROTECTION_OFF and Ack with PROTECTION_OFF - */ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtocoloV1) { using namespace protocol_handler; ::utils::SharedPtr<TestAsyncWaiter> waiter = @@ -826,16 +864,17 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtocoloV1) { An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_OFF, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_OFF), + ByRef(empty_rejected_param_)))); times++; SetProtocolVersion2(); @@ -881,16 +920,17 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionUnprotected) { An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_OFF, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_OFF), + ByRef(empty_rejected_param_)))); times++; SetProtocolVersion2(); @@ -917,6 +957,15 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtected_Fail) { TestAsyncWaiter waiter; uint32_t times = 0; + + protocol_handler::SessionContext context = GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON); + context.is_new_service_ = true; + // Expect ConnectionHandler check EXPECT_CALL(session_observer_mock, OnSessionStartedCallback(connection_id, @@ -926,16 +975,12 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtected_Fail) { An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + context, + ByRef(empty_rejected_param_)))); times++; SetProtocolVersion2(); @@ -980,16 +1025,17 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON), + ByRef(empty_rejected_param_)))); times++; SetProtocolVersion2(); @@ -1038,6 +1084,14 @@ TEST_F(ProtocolHandlerImplTest, TestAsyncWaiter waiter; uint32_t times = 0; + protocol_handler::SessionContext context = GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON); + context.is_new_service_ = true; + // Expect ConnectionHandler check EXPECT_CALL(session_observer_mock, OnSessionStartedCallback(connection_id, @@ -1047,24 +1101,20 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + context, + ByRef(empty_rejected_param_)))); times++; std::vector<int> services; // TODO(AKutsan) : APPLINK-21398 use named constants instead of magic numbers services.push_back(0x0A); services.push_back(0x0B); - ON_CALL(protocol_handler_settings_mock, force_protected_service()) - .WillByDefault(ReturnRefOfCopy(services)); + EXPECT_CALL(protocol_handler_settings_mock, force_protected_service()) + .WillOnce(ReturnRefOfCopy(services)); // call new SSLContext creation EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) @@ -1093,13 +1143,6 @@ TEST_F(ProtocolHandlerImplTest, connection_key, security_manager::SSLContext::Handshake_Result_Fail))); - // Listener check SSLContext - EXPECT_CALL(session_observer_mock, - GetSSLContext(connection_key, start_service)) - . - // Emulate protection for service is not enabled - WillOnce(ReturnNull()); - // Expect send Ack with PROTECTION_OFF (on fail handshake) EXPECT_CALL(transport_manager_mock, SendMessageToDevice( @@ -1139,16 +1182,17 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON), + ByRef(empty_rejected_param_)))); times++; // call new SSLContext creation @@ -1236,16 +1280,17 @@ TEST_F( An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON), + ByRef(empty_rejected_param_)))); times++; // call new SSLContext creation @@ -1331,16 +1376,17 @@ TEST_F(ProtocolHandlerImplTest, An<const BsonObject*>())) . // Return sessions start success - WillOnce(DoAll( - NotifyTestAsyncWaiter(&waiter), - InvokeMemberFuncWithArg6(protocol_handler_impl.get(), - &ProtocolHandler::NotifySessionStartedResult, - connection_id, - NEW_SESSION_ID, - session_id, - HASH_ID_WRONG, - PROTECTION_ON, - ByRef(empty_rejected_param_)))); + WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + InvokeMemberFuncWithArg2(protocol_handler_impl.get(), + &ProtocolHandler::NotifySessionStarted, + GetSessionContext(connection_id, + NEW_SESSION_ID, + session_id, + start_service, + HASH_ID_WRONG, + PROTECTION_ON), + ByRef(empty_rejected_param_)))); times++; // call new SSLContext creation diff --git a/src/components/security_manager/include/security_manager/crypto_manager_impl.h b/src/components/security_manager/include/security_manager/crypto_manager_impl.h index 4daf58b004..4e48858e5c 100644 --- a/src/components/security_manager/include/security_manager/crypto_manager_impl.h +++ b/src/components/security_manager/include/security_manager/crypto_manager_impl.h @@ -137,6 +137,11 @@ class CryptoManagerImpl : public CryptoManager { int pull_number_from_buf(char* buf, int* idx); void asn1_time_to_tm(ASN1_TIME* time); + /** + * @brief Sets initial certificate datetime + */ + void InitCertExpTime(); + const utils::SharedPtr<const CryptoManagerSettings> settings_; SSL_CTX* context_; mutable struct tm expiration_time_; diff --git a/src/components/security_manager/include/security_manager/security_manager_impl.h b/src/components/security_manager/include/security_manager/security_manager_impl.h index d4231ffaa0..469b97d1e1 100644 --- a/src/components/security_manager/include/security_manager/security_manager_impl.h +++ b/src/components/security_manager/include/security_manager/security_manager_impl.h @@ -141,6 +141,12 @@ class SecurityManagerImpl : public SecurityManager, void StartHandshake(uint32_t connection_key) OVERRIDE; /** + * @brief Checks whether certificate should be updated + * @return true if certificate should be updated otherwise false + */ + bool IsCertificateUpdateRequired() OVERRIDE; + + /** * \brief Add/Remove for SecurityManagerListener */ void AddListener(SecurityManagerListener* const listener) OVERRIDE; @@ -158,7 +164,19 @@ class SecurityManagerImpl : public SecurityManager, * @brief Notifiers for listeners. * Allows to notify that certificate should be updated */ - void NotifyOnCertififcateUpdateRequired(); + DEPRECATED void NotifyOnCertififcateUpdateRequired(); + + /** + * @brief Notifiers for listeners. + * Allows to notify that certificate should be updated + */ + void NotifyOnCertificateUpdateRequired() OVERRIDE; + + /** + * @brief Check is policy certificate data is empty + * @return true if policy certificate data is not empty otherwise false + */ + bool IsPolicyCertificateDataEmpty() OVERRIDE; /** * @brief SecurityConfigSection diff --git a/src/components/security_manager/src/crypto_manager_impl.cc b/src/components/security_manager/src/crypto_manager_impl.cc index 00fcb1385a..6bee28a976 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -93,6 +93,7 @@ CryptoManagerImpl::CryptoManagerImpl( OpenSSL_add_all_algorithms(); SSL_library_init(); } + InitCertExpTime(); } CryptoManagerImpl::~CryptoManagerImpl() { @@ -295,6 +296,8 @@ const CryptoManagerSettings& CryptoManagerImpl::get_settings() const { } bool CryptoManagerImpl::set_certificate(const std::string& cert_data) { + LOG4CXX_AUTO_TRACE(logger_); + if (cert_data.empty()) { LOG4CXX_WARN(logger_, "Empty certificate"); return false; @@ -324,20 +327,35 @@ bool CryptoManagerImpl::set_certificate(const std::string& cert_data) { } if (!SSL_CTX_use_certificate(context_, cert)) { - LOG4CXX_WARN(logger_, "Could not use certificate"); + LOG4CXX_WARN(logger_, "Could not use certificate: " << LastError()); return false; } asn1_time_to_tm(X509_get_notAfter(cert)); if (!SSL_CTX_use_PrivateKey(context_, pkey)) { - LOG4CXX_ERROR(logger_, "Could not use key"); + LOG4CXX_ERROR(logger_, "Could not use key: " << LastError()); return false; } + if (!SSL_CTX_check_private_key(context_)) { - LOG4CXX_ERROR(logger_, "Could not use certificate "); + LOG4CXX_ERROR(logger_, "Could not use certificate: " << LastError()); return false; } + + X509_STORE* store = SSL_CTX_get_cert_store(context_); + if (store) { + X509* extra_cert = NULL; + while ((extra_cert = PEM_read_bio_X509(bio_cert, NULL, 0, 0))) { + if (extra_cert != cert) { + LOG4CXX_DEBUG(logger_, + "Added new certificate to store: " << extra_cert); + X509_STORE_add_cert(store, extra_cert); + } + } + } + + LOG4CXX_DEBUG(logger_, "Certificate and key successfully updated"); return true; } @@ -384,4 +402,8 @@ void CryptoManagerImpl::asn1_time_to_tm(ASN1_TIME* time) { } } +void CryptoManagerImpl::InitCertExpTime() { + strptime("1 Jan 1970 00:00:00", "%d %b %Y %H:%M:%S", &expiration_time_); +} + } // namespace security_manager diff --git a/src/components/security_manager/src/security_manager_impl.cc b/src/components/security_manager/src/security_manager_impl.cc index 556cc291d1..1853b218b4 100644 --- a/src/components/security_manager/src/security_manager_impl.cc +++ b/src/components/security_manager/src/security_manager_impl.cc @@ -188,10 +188,6 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { return; } - if (crypto_manager_->IsCertificateUpdateRequired()) { - NotifyOnCertififcateUpdateRequired(); - } - if (ssl_context->IsInitCompleted()) { NotifyListenersOnHandshakeDone(connection_key, SSLContext::Handshake_Result_Success); @@ -219,14 +215,22 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { SendHandshakeBinData(connection_key, data, data_size); } } + +bool SecurityManagerImpl::IsCertificateUpdateRequired() { + LOG4CXX_AUTO_TRACE(logger_); + return crypto_manager_->IsCertificateUpdateRequired(); +} + void SecurityManagerImpl::AddListener(SecurityManagerListener* const listener) { if (!listener) { LOG4CXX_ERROR(logger_, "Invalid (NULL) pointer to SecurityManagerListener."); return; } + LOG4CXX_DEBUG(logger_, "Adding listener " << listener); listeners_.push_back(listener); } + void SecurityManagerImpl::RemoveListener( SecurityManagerListener* const listener) { if (!listener) { @@ -236,13 +240,15 @@ void SecurityManagerImpl::RemoveListener( } listeners_.remove(listener); } + void SecurityManagerImpl::NotifyListenersOnHandshakeDone( const uint32_t& connection_key, SSLContext::HandshakeResult error) { LOG4CXX_AUTO_TRACE(logger_); std::list<SecurityManagerListener*>::iterator it = listeners_.begin(); while (it != listeners_.end()) { if ((*it)->OnHandshakeDone(connection_key, error)) { - // On get notification remove listener + LOG4CXX_DEBUG(logger_, "Destroying listener: " << *it); + delete (*it); it = listeners_.erase(it); } else { ++it; @@ -251,6 +257,10 @@ void SecurityManagerImpl::NotifyListenersOnHandshakeDone( } void SecurityManagerImpl::NotifyOnCertififcateUpdateRequired() { + NotifyOnCertificateUpdateRequired(); +} + +void SecurityManagerImpl::NotifyOnCertificateUpdateRequired() { LOG4CXX_AUTO_TRACE(logger_); std::list<SecurityManagerListener*>::iterator it = listeners_.begin(); while (it != listeners_.end()) { @@ -259,6 +269,19 @@ void SecurityManagerImpl::NotifyOnCertififcateUpdateRequired() { } } +bool SecurityManagerImpl::IsPolicyCertificateDataEmpty() { + LOG4CXX_AUTO_TRACE(logger_); + + std::string certificate_data; + for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { + if ((*it)->GetPolicyCertificateData(certificate_data)) { + LOG4CXX_DEBUG(logger_, "Certificate data received from listener"); + return certificate_data.empty(); + } + } + return false; +} + bool SecurityManagerImpl::ProccessHandshakeData( const SecurityMessage& inMessage) { LOG4CXX_INFO(logger_, "SendHandshakeData processing"); diff --git a/src/components/security_manager/test/security_manager_test.cc b/src/components/security_manager/test/security_manager_test.cc index 1178efbc0d..b334e78e19 100644 --- a/src/components/security_manager/test/security_manager_test.cc +++ b/src/components/security_manager/test/security_manager_test.cc @@ -31,6 +31,7 @@ */ #include <string> +#include <memory> #include "gtest/gtest.h" #include "utils/byte_order.h" @@ -98,7 +99,9 @@ class SecurityManagerTest : public ::testing::Test { security_manager_.reset(new SecurityManagerImpl()); security_manager_->set_session_observer(&mock_session_observer); security_manager_->set_protocol_handler(&mock_protocol_handler); - security_manager_->AddListener(&mock_sm_listener); + mock_sm_listener.reset(new testing::StrictMock< + security_manager_test::MockSecurityManagerListener>()); + security_manager_->AddListener(mock_sm_listener.get()); } void SetMockCryptoManager() { @@ -161,8 +164,8 @@ class SecurityManagerTest : public ::testing::Test { mock_ssl_context_new; testing::StrictMock<security_manager_test::MockSSLContext> mock_ssl_context_exists; - testing::StrictMock<security_manager_test::MockSecurityManagerListener> - mock_sm_listener; + std::unique_ptr<testing::StrictMock< + security_manager_test::MockSecurityManagerListener> > mock_sm_listener; }; // Test Bodies @@ -190,15 +193,15 @@ TEST_F(SecurityManagerTest, Listeners_NULL) { * Twice remove listener */ TEST_F(SecurityManagerTest, Listeners_TwiceRemoveListeners) { - security_manager_->RemoveListener(&mock_sm_listener); - security_manager_->RemoveListener(&mock_sm_listener); + security_manager_->RemoveListener(mock_sm_listener.get()); + security_manager_->RemoveListener(mock_sm_listener.get()); } /* * Add and remove listeners */ TEST_F(SecurityManagerTest, Listeners_NoListeners) { // Check correct removing listener - security_manager_->RemoveListener(&mock_sm_listener); + security_manager_->RemoveListener(mock_sm_listener.get()); // Expect no calls testing::StrictMock<MockSecurityManagerListener> mock_listener2; @@ -215,49 +218,51 @@ TEST_F(SecurityManagerTest, Listeners_NoListeners) { */ TEST_F(SecurityManagerTest, Listeners_Notifying) { // Check correct removing listener - security_manager_->RemoveListener(&mock_sm_listener); + security_manager_->RemoveListener(mock_sm_listener.get()); - testing::StrictMock<MockSecurityManagerListener> mock_listener1; - testing::StrictMock<MockSecurityManagerListener> mock_listener2; + testing::StrictMock<MockSecurityManagerListener>* mock_listener1 = + new testing::StrictMock<MockSecurityManagerListener>(); + testing::StrictMock<MockSecurityManagerListener>* mock_listener2 = + new testing::StrictMock<MockSecurityManagerListener>(); const SSLContext::HandshakeResult first_call_value = SSLContext::Handshake_Result_Success; // Expect call both listeners on 1st call - EXPECT_CALL(mock_listener1, OnHandshakeDone(key, first_call_value)) + EXPECT_CALL(*mock_listener1, OnHandshakeDone(key, first_call_value)) . // Emulate false (reject) result WillOnce(Return(false)); - EXPECT_CALL(mock_listener2, OnHandshakeDone(key, first_call_value)) + EXPECT_CALL(*mock_listener2, OnHandshakeDone(key, first_call_value)) . // Emulate true (accept) result WillOnce(Return(true)); // First listener was not removed from listener list // So this callback wil lbe either call. - EXPECT_CALL(mock_listener1, OnCertificateUpdateRequired()); + EXPECT_CALL(*mock_listener1, OnCertificateUpdateRequired()); const SSLContext::HandshakeResult second_call_value = SSLContext::Handshake_Result_Fail; // Expect call last listener on 2d call - EXPECT_CALL(mock_listener1, OnHandshakeDone(key, second_call_value)) + EXPECT_CALL(*mock_listener1, OnHandshakeDone(key, second_call_value)) . // Emulate false (reject) result WillOnce(Return(true)); // Expect no call 3d call - security_manager_->AddListener(&mock_listener1); - security_manager_->AddListener(&mock_listener2); + security_manager_->AddListener(mock_listener1); + security_manager_->AddListener(mock_listener2); // 1st call security_manager_->NotifyListenersOnHandshakeDone(key, first_call_value); - security_manager_->NotifyOnCertififcateUpdateRequired(); + security_manager_->NotifyOnCertificateUpdateRequired(); // 2nd call security_manager_->NotifyListenersOnHandshakeDone(key, second_call_value); - security_manager_->NotifyOnCertififcateUpdateRequired(); + security_manager_->NotifyOnCertificateUpdateRequired(); // 3nd call security_manager_->NotifyListenersOnHandshakeDone( key, SSLContext::Handshake_Result_Fail); - security_manager_->NotifyOnCertififcateUpdateRequired(); + security_manager_->NotifyOnCertificateUpdateRequired(); } /* @@ -495,7 +500,7 @@ TEST_F(SecurityManagerTest, StartHandshake_ServiceStillUnprotected) { SendMessageToMobileApp( InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final)); // Expect notifying listeners (unsuccess) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(Return(true)); @@ -504,6 +509,9 @@ TEST_F(SecurityManagerTest, StartHandshake_ServiceStillUnprotected) { .WillOnce(ReturnNull()); security_manager_->StartHandshake(key); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall send InternallError on SSL error and notify listeners @@ -527,7 +535,7 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInternalError) { SendMessageToMobileApp( InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final)); // Expect notifying listeners (unsuccess) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(Return(true)); @@ -543,6 +551,9 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInternalError) { Return(SSLContext::Handshake_Result_Fail))); security_manager_->StartHandshake(key); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall send data on call StartHandshake @@ -598,7 +609,7 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsComplete) { SetMockCryptoManager(); // Expect no message send // Expect notifying listeners (success) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Success)) .WillOnce(Return(true)); @@ -607,10 +618,11 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsComplete) { .WillOnce(Return(&mock_ssl_context_exists)); EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted()) .WillOnce(Return(true)); - EXPECT_CALL(mock_crypto_manager, IsCertificateUpdateRequired()) - .WillOnce(Return(false)); security_manager_->StartHandshake(key); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall send InternallError on @@ -667,7 +679,7 @@ TEST_F(SecurityManagerTest, times++; // Expect notifying listeners (unsuccess) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); times++; @@ -681,6 +693,9 @@ TEST_F(SecurityManagerTest, EmulateMobileMessageHandshake(data, sizeof(data) / sizeof(data[0])); EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall send InternallError on getting @@ -718,7 +733,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_InvalidData) { .WillRepeatedly(NotifyTestAsyncWaiter(&waiter)); times += handshake_emulates; // Expect notifying listeners (unsuccess) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); times++; @@ -761,6 +776,9 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_InvalidData) { handshake_data, handshake_data_size, handshake_emulates); EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall send HandshakeData on getting SEND_HANDSHAKE_DATA from mobile side @@ -796,7 +814,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_Answer) { times += handshake_emulates; // Expect notifying listeners (unsuccess) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); times++; @@ -833,6 +851,9 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_Answer) { handshake_data, handshake_data_size, handshake_emulates); EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall call all listeners on success end handshake @@ -848,7 +869,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_HandshakeFinished) { uint32_t times = 0; // Expect no errors // Expect notifying listeners (success) - EXPECT_CALL(mock_sm_listener, + EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Success)) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); times++; @@ -924,6 +945,9 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_HandshakeFinished) { handshake_data, handshake_data_size, handshake_emulates); EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); + + // Listener was destroyed after OnHandshakeDone call + mock_sm_listener.release(); } /* * Shall not any query on getting empty SEND_INTERNAL_ERROR diff --git a/src/components/security_manager/test/ssl_certificate_handshake_test.cc b/src/components/security_manager/test/ssl_certificate_handshake_test.cc index 9375d6cc32..dc335c8da2 100644 --- a/src/components/security_manager/test/ssl_certificate_handshake_test.cc +++ b/src/components/security_manager/test/ssl_certificate_handshake_test.cc @@ -372,11 +372,8 @@ TEST_F(SSLHandshakeTest, CAVerification_ServerSide) { } TEST_F(SSLHandshakeTest, CAVerification_ServerSide_NoCACertificate) { - ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2, - server_certificate, - "ALL", - verify_peer, - "unex")) + ASSERT_TRUE(InitServerManagers( + security_manager::TLSv1_2, "", "ALL", verify_peer, "unex")) << server_manager->LastError(); ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2, client_certificate, @@ -423,7 +420,7 @@ TEST_F(SSLHandshakeTest, CAVerification_ClientSide_NoCACertificate) { "")) << server_manager->LastError(); ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2, - client_certificate, + "", "ALL", verify_peer, "client_ca_cert_filename")) |