From 546cd986780759dd5eee64998f99bc66099a3b32 Mon Sep 17 00:00:00 2001 From: Andriy Byzhynar Date: Fri, 23 Feb 2018 17:54:43 +0200 Subject: Implement fully functional GetSystemTime feature Implemented fully working GetSystemTime feature Fixed UT in the security manager due to code changes Disable randomly failed test --- src/appMain/CMakeLists.txt | 2 + src/appMain/life_cycle.cc | 9 +- src/appMain/life_cycle.h | 7 +- src/components/application_manager/CMakeLists.txt | 11 ++ .../application_manager/application_manager_impl.h | 7 + .../basic_communication_get_system_time_request.h | 69 ++++++++ .../basic_communication_get_system_time_response.h | 72 +++++++++ .../hmi/on_system_time_ready_notification.h | 75 +++++++++ .../include/application_manager/message_helper.h | 9 ++ .../application_manager/smart_object_keys.h | 16 +- .../system_time/system_time_handler_impl.h | 157 ++++++++++++++++++ .../src/application_manager_impl.cc | 4 + .../basic_communication_get_system_time_request.cc | 49 ++++++ ...basic_communication_get_system_time_response.cc | 57 +++++++ .../hmi/on_system_time_ready_notification.cc | 56 +++++++ .../src/commands/hmi/request_to_hmi.cc | 4 +- .../application_manager/src/hmi_command_factory.cc | 18 +++ .../src/message_helper/message_helper.cc | 14 ++ .../src/policies/policy_handler.cc | 10 +- .../application_manager/src/smart_object_keys.cc | 17 +- .../src/system_time/system_time_handler_impl.cc | 169 ++++++++++++++++++++ .../src/connection_handler_impl.cc | 1 + .../policy/policy_regular/policy/policy_manager.h | 6 + .../include/protocol_handler/protocol_handler.h | 6 + .../include/security_manager/crypto_manager.h | 13 +- .../include/security_manager/security_manager.h | 46 +++++- .../security_manager/security_manager_listener.h | 6 + .../include/security_manager/ssl_context.h | 11 +- .../policy_regular/policy/mock_cache_manager.h | 2 +- .../test/protocol_handler/mock_protocol_handler.h | 1 + .../test/security_manager/mock_crypto_manager.h | 4 +- .../test/security_manager/mock_security_manager.h | 10 +- .../mock_security_manager_listener.h | 1 + .../test/security_manager/mock_ssl_context.h | 2 + .../include/test/utils/mock_system_time_handler.h | 69 ++++++++ src/components/interfaces/HMI_API.xml | 10 ++ .../policy_regular/include/policy/cache_manager.h | 6 + .../include/policy/cache_manager_interface.h | 7 + .../include/policy/policy_manager_impl.h | 2 + .../policy/policy_regular/src/cache_manager.cc | 7 + .../policy_regular/src/policy_manager_impl.cc | 7 + .../include/protocol_handler/handshake_handler.h | 7 + .../protocol_handler/protocol_handler_impl.h | 4 + .../protocol_handler/src/handshake_handler.cc | 11 ++ .../protocol_handler/src/protocol_handler_impl.cc | 46 ++++-- .../test/protocol_handler_tm_test.cc | 49 ++++-- .../include/security_manager/crypto_manager_impl.h | 24 ++- .../security_manager/security_manager_impl.h | 80 +++++++++- .../security_manager/src/crypto_manager_impl.cc | 67 ++------ .../security_manager/src/security_manager_impl.cc | 175 +++++++++++++++++++-- .../security_manager/src/ssl_context_impl.cc | 96 +++++++++++ .../test/crypto_manager_impl_test.cc | 9 +- .../security_manager/test/security_manager_test.cc | 129 ++++----------- .../test/ssl_certificate_handshake_test.cc | 3 + src/components/utils/CMakeLists.txt | 1 + .../utils/include/utils/system_time_handler.h | 151 ++++++++++++++++++ src/components/utils/src/system_time_handler.cc | 63 ++++++++ 57 files changed, 1737 insertions(+), 227 deletions(-) create mode 100644 src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_request.h create mode 100644 src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_response.h create mode 100644 src/components/application_manager/include/application_manager/commands/hmi/on_system_time_ready_notification.h create mode 100644 src/components/application_manager/include/application_manager/system_time/system_time_handler_impl.h create mode 100644 src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_request.cc create mode 100644 src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_response.cc create mode 100644 src/components/application_manager/src/commands/hmi/on_system_time_ready_notification.cc create mode 100644 src/components/application_manager/src/system_time/system_time_handler_impl.cc create mode 100644 src/components/include/test/utils/mock_system_time_handler.h create mode 100644 src/components/utils/include/utils/system_time_handler.h create mode 100644 src/components/utils/src/system_time_handler.cc diff --git a/src/appMain/CMakeLists.txt b/src/appMain/CMakeLists.txt index 514867624a..f59f21e5c3 100644 --- a/src/appMain/CMakeLists.txt +++ b/src/appMain/CMakeLists.txt @@ -109,7 +109,9 @@ set(LIBRARIES jsoncpp ConfigProfile Resumption + SystemTimeLibrary ) + if(REMOTE_CONTROL) SET (LIBRARIES ${LIBRARIES} diff --git a/src/appMain/life_cycle.cc b/src/appMain/life_cycle.cc index fc8441f28c..90a23465be 100644 --- a/src/appMain/life_cycle.cc +++ b/src/appMain/life_cycle.cc @@ -34,6 +34,7 @@ #include "utils/signals.h" #include "utils/make_shared.h" #include "config_profile/profile.h" +#include "application_manager/system_time/system_time_handler_impl.h" #include "resumption/last_state_impl.h" #ifdef ENABLE_SECURITY @@ -119,7 +120,11 @@ bool LifeCycle::StartComponents() { } #ifdef ENABLE_SECURITY - security_manager_ = new security_manager::SecurityManagerImpl(); + auto system_time_handler = + std::unique_ptr( + new application_manager::SystemTimeHandlerImpl(*app_manager_)); + security_manager_ = + new security_manager::SecurityManagerImpl(std::move(system_time_handler)); crypto_manager_ = new security_manager::CryptoManagerImpl( utils::MakeShared( profile_, app_manager_->GetPolicyHandler().RetrieveCertificate())); @@ -131,7 +136,7 @@ bool LifeCycle::StartComponents() { security_manager_->set_crypto_manager(crypto_manager_); security_manager_->AddListener(app_manager_); - app_manager_->AddPolicyObserver(crypto_manager_); + app_manager_->AddPolicyObserver(security_manager_); app_manager_->AddPolicyObserver(protocol_handler_); if (!crypto_manager_->Init()) { LOG4CXX_ERROR(logger_, "CryptoManager initialization fail."); diff --git a/src/appMain/life_cycle.h b/src/appMain/life_cycle.h index db18892cd3..e37da3fa1d 100644 --- a/src/appMain/life_cycle.h +++ b/src/appMain/life_cycle.h @@ -33,8 +33,9 @@ #ifndef SRC_APPMAIN_LIFE_CYCLE_H_ #define SRC_APPMAIN_LIFE_CYCLE_H_ #include +#include #include "utils/macro.h" -#include "unistd.h" +#include "utils/shared_ptr.h" #include "config_profile/profile.h" #include "hmi_message_handler/hmi_message_handler_impl.h" @@ -65,6 +66,10 @@ class SecurityManagerImpl; } // namespace security_manager #endif // ENABLE_SECURITY +namespace utils { +class SystemTimeHandler; +} // namespace utils + namespace main_namespace { class LifeCycle { public: diff --git a/src/components/application_manager/CMakeLists.txt b/src/components/application_manager/CMakeLists.txt index e9f2f8ec7b..966dbee353 100644 --- a/src/components/application_manager/CMakeLists.txt +++ b/src/components/application_manager/CMakeLists.txt @@ -52,6 +52,7 @@ include_directories ( ${COMPONENTS_DIR}/config_profile/include ${COMPONENTS_DIR}/request_watchdog/include ${COMPONENTS_DIR}/resumption/include + ${COMPONENTS_DIR}/system_time/ ${COMPONENTS_DIR}/rpc_base/include ${COMPONENTS_DIR}/interfaces ${POLICY_PATH}/include/ @@ -85,6 +86,9 @@ set (MESSAGE_HELPER_PATHS ) collect_sources(MESSAGE_HELPER_SOURCES "${MESSAGE_HELPER_PATHS}") +set (SYSTEM_TIME_SOURCES + ${AM_SOURCE_DIR}/src/system_time/system_time_handler_impl.cc +) set (POLICIES_SOURCE_DIR ${AM_SOURCE_DIR}/src/policies @@ -146,6 +150,9 @@ set (HMI_COMMANDS_SOURCES ${COMMANDS_SOURCE_DIR}/hmi/activate_app_response.cc ${COMMANDS_SOURCE_DIR}/hmi/get_system_info_request.cc ${COMMANDS_SOURCE_DIR}/hmi/get_system_info_response.cc + ${COMMANDS_SOURCE_DIR}/hmi/basic_communication_get_system_time_request.cc + ${COMMANDS_SOURCE_DIR}/hmi/basic_communication_get_system_time_response.cc + ${COMMANDS_SOURCE_DIR}/hmi/on_system_time_ready_notification.cc ${COMMANDS_SOURCE_DIR}/hmi/sdl_get_list_of_permissions_request.cc ${COMMANDS_SOURCE_DIR}/hmi/sdl_get_list_of_permissions_response.cc ${COMMANDS_SOURCE_DIR}/hmi/sdl_get_user_friendly_message_request.cc @@ -447,6 +454,10 @@ target_link_libraries("AMHMICommandsLibrary" ${LIBRARIES} AMEventEngine) add_library("MessageHelper" ${MESSAGE_HELPER_SOURCES}) target_link_libraries("MessageHelper" ${LIBRARIES}) +add_library("SystemTimeLibrary" ${SYSTEM_TIME_SOURCES}) +target_link_libraries("SystemTimeLibrary" ${LIBRARIES} AMEventEngine) +add_dependencies("MessageHelper" HMI_API MOBILE_API) + add_library("AMMobileCommandsLibrary" ${MOBILE_COMMANDS_SOURCES} ) target_link_libraries("AMMobileCommandsLibrary" ${LIBRARIES} AMEventEngine) 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 286ad87018..d3fe69efcb 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 @@ -957,6 +957,13 @@ class ApplicationManagerImpl uint32_t connection_key, security_manager::SSLContext::HandshakeResult result) OVERRIDE; + /** + * @brief OnHandshakeFailed currently does nothing. + * This method is declared as pure virtual in common base class + * therefore it has to be present and should be implemented + * to allow creation of current class instances + */ + void OnHandshakeFailed() OVERRIDE; /** * @brief Notification that certificate update is required. */ diff --git a/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_request.h b/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_request.h new file mode 100644 index 0000000000..1638b2f51b --- /dev/null +++ b/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_request.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_REQUEST_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_REQUEST_H_ + +#include "application_manager/commands/hmi/request_to_hmi.h" +#include "utils/macro.h" + +namespace application_manager { +namespace commands { + +/** + * @brief The BasicCommunicationGetSystemTimeRequest class sends the request + * to the HMI in order to receive current system time. + */ +class BasicCommunicationGetSystemTimeRequest : public RequestToHMI { + public: + /** + * @brief BasicCommunicationGetSystemTimeRequest does nothing except of + * initializing base class with the passed parameters. + * @param message the message to send to HMI + * @param application_manager application manager. Location service which + * is provides neccessary api to send the request. + */ + BasicCommunicationGetSystemTimeRequest( + const MessageSharedPtr& message, ApplicationManager& application_manager); + + private: + /** + * @brief onTimeOut allows to handle case when + * system does not respond for certain request in + * appropriate time window. + */ + void onTimeOut() FINAL; +}; + +} // namespace commands +} // namespace application_manager +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_REQUEST_H_ diff --git a/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_response.h b/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_response.h new file mode 100644 index 0000000000..1bf7447c7d --- /dev/null +++ b/src/components/application_manager/include/application_manager/commands/hmi/basic_communication_get_system_time_response.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_RESPONSE_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_RESPONSE_H_ + +#include "application_manager/commands/hmi/response_from_hmi.h" + +#include "utils/macro.h" +#include "application_manager/application_manager_impl.h" + +namespace application_manager { + +namespace commands { + +/** + * @brief The BasicCommunicationGetSystemTimeResponse class represents the + * HMI response which is contains data obtained from HMI. + */ +class BasicCommunicationGetSystemTimeResponse : public ResponseFromHMI { + public: + /** + * @brief BasicCommunicationGetSystemTimeResponse does nothing except of + * initializing base class with the passed parameters. + * @param message the message to send to HMI + * @param application_manager Location service which which is provides + * neccessary api to send the request. + */ + BasicCommunicationGetSystemTimeResponse( + const MessageSharedPtr& message, ApplicationManager& application_manager); + + private: + /** + * @brief Run takes the message obtained from the HMI and + * sends this data to the subscribed on certain event class + */ + void Run() FINAL; +}; + +} // namespace commands +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_BASIC_COMMUNICATION_GET_SYSTEM_TIME_RESPONSE_H_ diff --git a/src/components/application_manager/include/application_manager/commands/hmi/on_system_time_ready_notification.h b/src/components/application_manager/include/application_manager/commands/hmi/on_system_time_ready_notification.h new file mode 100644 index 0000000000..9b8763da42 --- /dev/null +++ b/src/components/application_manager/include/application_manager/commands/hmi/on_system_time_ready_notification.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_SYSTEM_TIME_READY_NOTIFICATION_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_SYSTEM_TIME_READY_NOTIFICATION_H_ + +#include "application_manager/commands/hmi/notification_from_hmi.h" +#include "application_manager/application_manager_impl.h" + +namespace application_manager { + +namespace commands { + +/** + * @brief OnSystemTimeReadyNotification command class. + * Notifies SDL whenever system time module is ready. + * It could be GPS or any other module which is allows + * to obtain system time. Once SDL receive this notification + * it is allowed to use GetSystemTimeRequest to rerieve system time. + */ +class OnSystemTimeReadyNotification : public NotificationFromHMI { + public: + /** + * @brief OnSystemTimeReadyNotification create the command. + * @param message content of the command. Passed directy to base class. + */ + OnSystemTimeReadyNotification(const MessageSharedPtr& message, + ApplicationManager& application_manager); + + /** + * @brief ~OnSystemTimeReadyNotification destroys the command object. + */ + ~OnSystemTimeReadyNotification(); + + private: + /** + * @brief Run creates SystemTimeReady event + * and notifies all the subscribers. + */ + void Run() FINAL; +}; + +} // namespace commands +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_SYSTEM_TIME_READY_NOTIFICATION_H_ diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h index b94609c01b..0a476712d6 100644 --- a/src/components/application_manager/include/application_manager/message_helper.h +++ b/src/components/application_manager/include/application_manager/message_helper.h @@ -107,6 +107,15 @@ class MessageHelper { static void SendDecryptCertificateToHMI(const std::string& file_name, ApplicationManager& app_mngr); + /** + * @brief SendGetSystemTimeRequest sends mentioned request to HMI. + * @param correlation_id the message correlation id, required for proper + * response processing. + * @param app_mngr + */ + static void SendGetSystemTimeRequest(const uint32_t correlation_id, + ApplicationManager& app_mngr); + /* * @brief Retrieve vehicle data map for param name in mobile request * to VehicleDataType diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h index 32a2315f23..e79b34c55f 100644 --- a/src/components/application_manager/include/application_manager/smart_object_keys.h +++ b/src/components/application_manager/include/application_manager/smart_object_keys.h @@ -406,7 +406,19 @@ extern const char* kFull; extern const char* kLimited; extern const char* kBackground; extern const char* kNone; -} +} // namespace hmi_levels + +namespace time_keys { +extern const char* millisecond; +extern const char* second; +extern const char* minute; +extern const char* hour; +extern const char* day; +extern const char* month; +extern const char* year; +extern const char* tz_hour; +extern const char* tz_minute; +} // namespace time_keys namespace hmi_request { extern const char* parent_id; @@ -478,7 +490,7 @@ extern const char* num_custom_presets_available; extern const char* urls; extern const char* policy_app_id; extern const char* enabled; - +extern const char* system_time; } // namespace hmi_response namespace hmi_notification { diff --git a/src/components/application_manager/include/application_manager/system_time/system_time_handler_impl.h b/src/components/application_manager/include/application_manager/system_time/system_time_handler_impl.h new file mode 100644 index 0000000000..28ba629e19 --- /dev/null +++ b/src/components/application_manager/include/application_manager/system_time/system_time_handler_impl.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SYSTEM_TIME_SYSTEM_TIME_HANDLER_IMPL_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SYSTEM_TIME_SYSTEM_TIME_HANDLER_IMPL_H_ + +#include +#include + +#include "utils/lock.h" +#include "utils/macro.h" +#include "utils/system_time_handler.h" +#include "application_manager/application_manager_impl.h" +#include "application_manager/event_engine/event_observer.h" + +namespace application_manager { + +/** + * @brief The SystemTimeHandlerImpl class. + * Responsible for the system time notification. It keeps the list + * of system time listeners, sends appropriate request to the system + * and notifies the listeners with new time right after response has appeared. + */ +class SystemTimeHandlerImpl : public utils::SystemTimeHandler, + public event_engine::EventObserver { + public: + /** + * @brief SystemTimeHandlerImpl creates the instance of the class. + */ + explicit SystemTimeHandlerImpl(ApplicationManager& application_manager); + + /** + * @brief ~SystemTimeHandlerImpl + */ + ~SystemTimeHandlerImpl(); + + private: + /** + * @brief on_event allows to process certain events from the system. + * Event which are handles within this methods are: OnSystemTimeReady + * in order to send system time query and GetSystemTimeResponse in order + * to retrieve utc time and notify all the listeners with new time value. + */ + void on_event(const application_manager::event_engine::Event& event) FINAL; + + /** + * @brief DoSystemTimeQuery sends the appropriate request to the system + * and subscribes the class to the response. This is asynchronous request + * thus it won't block until the system respond and returns immediately. + */ + void DoSystemTimeQuery() FINAL; + + /** + * @brief DoSubscribe allows to subscribe certain listener for + * SystemTime. This certain implementation does not maintain + * listeners collection instead it save the pointer to listener. + * @note the class is not reponsible for the pointer's lifecycle. + * So consider to explicitly unsibsscribe from event when listener + * is going to be destroyed. + * @param listener the listener which will be notified + * in case of SystemTime appeared. + */ + void DoSubscribe(utils::SystemTimeListener* listener) FINAL; + + /** + * @brief DoUnsubscribe assigns the pointer to listener to NULL. + * This certain implementation ignores passed parameter. + * @param listener pointer to the object which should be + * unsubscribed from events. + */ + void DoUnsubscribe(utils::SystemTimeListener* listener) FINAL; + + /** + * @brief FetchSystemTime this method allows to obtain + * recently received utc time. + * @note it is up to user to check whether the returned + * argument is valid + * @return the time value returned by system. + */ + time_t FetchSystemTime() FINAL; + + /** + * @brief SendTimeRequest sends the request to the system + * and subscribes for response. + */ + void SendTimeRequest(); + + /** + * @brief ProcessSystemTimeResponse allows to process GetSystemTimeResponse + * @param event contains response parameters aka "systemTime". + */ + void ProcessSystemTimeResponse( + const application_manager::event_engine::Event& event); + + /** + * @brief ProcessSystemTimeReadyNotification allows to process + * OnSystemTimeready notification + * from HMI. It unsubscribes from the mentioned notification and sends + * GetSystemTimeRequest to HMI in order to obtain system time + */ + void ProcessSystemTimeReadyNotification(); + + /** + * @brief Checks if UTC time is ready to provided by HMI + * and can be requested by GetSystemTime request + * @return True if HMI is ready to provide UTC time + * otherwise False + */ + bool utc_time_can_be_received() const FINAL; + + mutable sync_primitives::Lock state_lock_; + // Variable means HMI readiness to provide system time by request + volatile bool utc_time_can_be_received_; + // Varible used to schedule next GetSystemTime request + // if at the moment of sending first GetSystemTime request + // HMI is not ready to provide system time + volatile bool schedule_request_; + // Varible used to store result for GetSystemTime request + time_t last_time_; + + sync_primitives::Lock system_time_listener_lock_; + utils::SystemTimeListener* system_time_listener_; + ApplicationManager& app_manager_; +}; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SYSTEM_TIME_SYSTEM_TIME_HANDLER_IMPL_H_ diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 248b54fee5..5aa72d77e5 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -1691,6 +1691,10 @@ bool ApplicationManagerImpl::OnHandshakeDone( return false; } +void ApplicationManagerImpl::OnHandshakeFailed() { + LOG4CXX_AUTO_TRACE(logger_); +} + void ApplicationManagerImpl::OnCertificateUpdateRequired() { LOG4CXX_AUTO_TRACE(logger_); GetPolicyHandler().OnPTExchangeNeeded(); diff --git a/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_request.cc b/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_request.cc new file mode 100644 index 0000000000..215b0404a7 --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_request.cc @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, 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 + * distribut wiion. + * + * 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 "application_manager/commands/hmi/basic_communication_get_system_time_request.h" + +namespace application_manager { + +namespace commands { + +BasicCommunicationGetSystemTimeRequest::BasicCommunicationGetSystemTimeRequest( + const MessageSharedPtr& message, ApplicationManager& application_manager) + : RequestToHMI(message, application_manager) {} + +void BasicCommunicationGetSystemTimeRequest::onTimeOut() { + LOG4CXX_AUTO_TRACE(logger_); + application_manager_.protocol_handler().NotifyOnFailedHandshake(); +} + +} // namespace commands +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_response.cc b/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_response.cc new file mode 100644 index 0000000000..26dd115d1a --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/basic_communication_get_system_time_response.cc @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 "application_manager/commands/hmi/basic_communication_get_system_time_response.h" +#include "utils/logger.h" + +CREATE_LOGGERPTR_GLOBAL(logger_, "Commands") + +namespace application_manager { +namespace commands { + +BasicCommunicationGetSystemTimeResponse:: + BasicCommunicationGetSystemTimeResponse( + const MessageSharedPtr& message, + ApplicationManager& application_manager) + : ResponseFromHMI(message, application_manager) {} + +void BasicCommunicationGetSystemTimeResponse::Run() { + LOG4CXX_AUTO_TRACE(logger_); + + event_engine::Event event( + hmi_apis::FunctionID::BasicCommunication_GetSystemTime); + event.set_smart_object(*message_); + event.raise(application_manager_.event_dispatcher()); +} + +} // namespace commands +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/on_system_time_ready_notification.cc b/src/components/application_manager/src/commands/hmi/on_system_time_ready_notification.cc new file mode 100644 index 0000000000..d2376e6dfe --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/on_system_time_ready_notification.cc @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 "application_manager/commands/hmi/on_system_time_ready_notification.h" + +#include "application_manager/event_engine/event.h" +#include "interfaces/HMI_API.h" + +namespace application_manager { + +namespace commands { + +OnSystemTimeReadyNotification::OnSystemTimeReadyNotification( + const MessageSharedPtr& message, ApplicationManager& application_manager) + : NotificationFromHMI(message, application_manager) {} + +OnSystemTimeReadyNotification::~OnSystemTimeReadyNotification() {} + +void OnSystemTimeReadyNotification::Run() { + event_engine::Event event( + hmi_apis::FunctionID::BasicCommunication_OnSystemTimeReady); + event.set_smart_object(*message_); + event.raise(application_manager_.event_dispatcher()); +} + +} // namespace commands +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/request_to_hmi.cc b/src/components/application_manager/src/commands/hmi/request_to_hmi.cc index 6905e7cdef..23c020bca2 100644 --- a/src/components/application_manager/src/commands/hmi/request_to_hmi.cc +++ b/src/components/application_manager/src/commands/hmi/request_to_hmi.cc @@ -74,7 +74,9 @@ bool RequestToHMI::CleanUp() { return true; } -void RequestToHMI::Run() {} +void RequestToHMI::Run() { + SendRequest(); +} void RequestToHMI::SendRequest() { (*message_)[strings::params][strings::protocol_type] = hmi_protocol_type_; diff --git a/src/components/application_manager/src/hmi_command_factory.cc b/src/components/application_manager/src/hmi_command_factory.cc index a7f3ce7e6b..5ef8605999 100644 --- a/src/components/application_manager/src/hmi_command_factory.cc +++ b/src/components/application_manager/src/hmi_command_factory.cc @@ -224,6 +224,7 @@ #include "application_manager/commands/hmi/navi_get_way_points_request.h" #include "application_manager/commands/hmi/navi_get_way_points_response.h" #include "application_manager/commands/hmi/on_ready_notification.h" +#include "application_manager/commands/hmi/on_system_time_ready_notification.h" #include "application_manager/commands/hmi/on_device_chosen_notification.h" #include "application_manager/commands/hmi/on_file_removed_notification.h" #include "application_manager/commands/hmi/on_system_context_notification.h" @@ -269,6 +270,8 @@ #include "application_manager/commands/hmi/on_system_error_notification.h" #include "application_manager/commands/hmi/basic_communication_system_request.h" #include "application_manager/commands/hmi/basic_communication_system_response.h" +#include "application_manager/commands/hmi/basic_communication_get_system_time_request.h" +#include "application_manager/commands/hmi/basic_communication_get_system_time_response.h" #include "application_manager/commands/hmi/basic_communication_on_awake_sdl.h" #include "application_manager/commands/hmi/sdl_policy_update.h" #include "application_manager/commands/hmi/sdl_policy_update_response.h" @@ -1285,6 +1288,11 @@ CommandSharedPtr HMICommandFactory::CreateCommand( new commands::OnReadyNotification(message, application_manager)); break; } + case hmi_apis::FunctionID::BasicCommunication_OnSystemTimeReady: { + command.reset(new commands::OnSystemTimeReadyNotification( + message, application_manager)); + break; + } case hmi_apis::FunctionID::BasicCommunication_OnDeviceChosen: { command.reset(new commands::OnDeviceChosenNotification( message, application_manager)); @@ -2221,6 +2229,16 @@ CommandSharedPtr HMICommandFactory::CreateCommand( } break; } + case hmi_apis::FunctionID::BasicCommunication_GetSystemTime: { + if (is_response) { + command.reset(new commands::BasicCommunicationGetSystemTimeResponse( + message, application_manager)); + } else { + command.reset(new commands::BasicCommunicationGetSystemTimeRequest( + message, application_manager)); + } + break; + } case hmi_apis::FunctionID::Navigation_SendLocation: { if (is_response) { command.reset(new commands::NaviSendLocationResponse( diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc index 6a908c4ebc..9a10c908f1 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -365,6 +365,20 @@ void MessageHelper::SendDecryptCertificateToHMI(const std::string& file_name, app_mngr.ManageHMICommand(message); } +void MessageHelper::SendGetSystemTimeRequest(const uint32_t correlation_id, + ApplicationManager& app_mngr) { + using namespace smart_objects; + SmartObjectSPtr message = + CreateMessageForHMI(hmi_apis::messageType::request, correlation_id); + + DCHECK(message); + + (*message)[strings::params][strings::function_id] = + hmi_apis::FunctionID::BasicCommunication_GetSystemTime; + + app_mngr.ManageHMICommand(message); +} + void MessageHelper::SendHashUpdateNotification(const uint32_t app_id, ApplicationManager& app_mngr) { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc index bbf391a9f1..98fb6bae65 100644 --- a/src/components/application_manager/src/policies/policy_handler.cc +++ b/src/components/application_manager/src/policies/policy_handler.cc @@ -1765,11 +1765,11 @@ void PolicyHandler::OnCertificateDecrypted(bool is_succeeded) { void PolicyHandler::OnCertificateUpdated(const std::string& certificate_data) { LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoLock lock(listeners_lock_); - HandlersCollection::const_iterator it = listeners_.begin(); - for (; it != listeners_.end(); ++it) { - PolicyHandlerObserver* observer = *it; - observer->OnCertificateUpdated(certificate_data); - } + std::for_each( + listeners_.begin(), + listeners_.end(), + std::bind2nd(std::mem_fun(&PolicyHandlerObserver::OnCertificateUpdated), + certificate_data)); } #endif // EXTERNAL_PROPRIETARY_MODE diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc index c3aba90dd5..888943d4d6 100644 --- a/src/components/application_manager/src/smart_object_keys.cc +++ b/src/components/application_manager/src/smart_object_keys.cc @@ -351,7 +351,7 @@ const char* instance_follow_redirect = "InstanceFollowRedirect"; const char* charset = "charset"; const char* content_lenght = "Content_Lenght"; const char* GET = "GET"; -} // http_request +} // namespace http_request namespace mobile_notification { const char* state = "state"; @@ -364,7 +364,17 @@ const char* kFull = "FULL"; const char* kLimited = "LIMITED"; const char* kBackground = "BACKGROUND"; const char* kNone = "NONE"; -} +} // namespace hmi_levels + +namespace time_keys { +const char* millisecond = "millisecond"; +const char* second = "second"; +const char* minute = "minute"; +const char* hour = "hour"; +const char* day = "day"; +const char* month = "month"; +const char* year = "year"; +} // namespace time_keys namespace hmi_request { const char* parent_id = "parentID"; @@ -436,7 +446,7 @@ const char* num_custom_presets_available = "numCustomPresetsAvailable"; const char* urls = "urls"; const char* policy_app_id = "policyAppID"; const char* enabled = "enabled"; - +const char* system_time = "systemTime"; } // namespace hmi_response namespace hmi_notification { @@ -451,7 +461,6 @@ const char* policyfile = "policyfile"; const char* is_active = "isActive"; const char* is_deactivated = "isDeactivated"; const char* event_name = "eventName"; - } // namespace hmi_notification } // namespace application_manager diff --git a/src/components/application_manager/src/system_time/system_time_handler_impl.cc b/src/components/application_manager/src/system_time/system_time_handler_impl.cc new file mode 100644 index 0000000000..a91fb16197 --- /dev/null +++ b/src/components/application_manager/src/system_time/system_time_handler_impl.cc @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018, 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 "application_manager/system_time/system_time_handler_impl.h" + +#include + +#include "application_manager/message_helper.h" +#include "application_manager/smart_object_keys.h" +#include "interfaces/HMI_API.h" +#include "utils/logger.h" + +namespace application_manager { + +SystemTimeHandlerImpl::SystemTimeHandlerImpl( + ApplicationManager& application_manager) + : event_engine::EventObserver(application_manager.event_dispatcher()) + , utc_time_can_be_received_(false) + , schedule_request_(false) + , system_time_listener_(NULL) + , app_manager_(application_manager) { + LOG4CXX_AUTO_TRACE(logger_); + subscribe_on_event( + hmi_apis::FunctionID::BasicCommunication_OnSystemTimeReady); +} + +SystemTimeHandlerImpl::~SystemTimeHandlerImpl() { + LOG4CXX_AUTO_TRACE(logger_); + unsubscribe_from_all_events(); +} + +void SystemTimeHandlerImpl::DoSystemTimeQuery() { + LOG4CXX_AUTO_TRACE(logger_); + using namespace application_manager; + + sync_primitives::AutoLock lock(state_lock_); + if (!utc_time_can_be_received_) { + LOG4CXX_INFO(logger_, + "Navi module is not yet ready." + << "Will process request once it became ready."); + schedule_request_ = true; + return; + } + SendTimeRequest(); +} + +void SystemTimeHandlerImpl::DoSubscribe(utils::SystemTimeListener* listener) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(listener); + sync_primitives::AutoLock lock(system_time_listener_lock_); + system_time_listener_ = listener; +} + +void SystemTimeHandlerImpl::DoUnsubscribe(utils::SystemTimeListener* listener) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(system_time_listener_lock_); + system_time_listener_ = NULL; +} + +time_t SystemTimeHandlerImpl::FetchSystemTime() { + LOG4CXX_AUTO_TRACE(logger_); + return last_time_; +} + +bool SystemTimeHandlerImpl::utc_time_can_be_received() const { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(state_lock_); + return utc_time_can_be_received_; +} + +void SystemTimeHandlerImpl::SendTimeRequest() { + LOG4CXX_AUTO_TRACE(logger_); + using namespace application_manager; + uint32_t correlation_id = app_manager_.GetNextHMICorrelationID(); + subscribe_on_event(hmi_apis::FunctionID::BasicCommunication_GetSystemTime, + correlation_id); + MessageHelper::SendGetSystemTimeRequest(correlation_id, app_manager_); +} + +void SystemTimeHandlerImpl::on_event( + const application_manager::event_engine::Event& event) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace application_manager; + using namespace hmi_apis::FunctionID; + switch (event.id()) { + case BasicCommunication_OnSystemTimeReady: + ProcessSystemTimeReadyNotification(); + break; + case BasicCommunication_GetSystemTime: + ProcessSystemTimeResponse(event); + break; + default: + LOG4CXX_ERROR(logger_, "Unknown Event received"); + break; + } +} + +void SystemTimeHandlerImpl::ProcessSystemTimeReadyNotification() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(state_lock_); + utc_time_can_be_received_ = true; + if (schedule_request_) { + SendTimeRequest(); + schedule_request_ = false; + } + unsubscribe_from_event( + hmi_apis::FunctionID::BasicCommunication_OnSystemTimeReady); +} + +void SystemTimeHandlerImpl::ProcessSystemTimeResponse( + const application_manager::event_engine::Event& event) { + LOG4CXX_AUTO_TRACE(logger_); + const smart_objects::SmartObject& message = event.smart_object(); + const smart_objects::SmartObject& system_time_so = + message[strings::msg_params][hmi_response::system_time]; + + struct tm system_time; + memset(&system_time, 0, sizeof(struct tm)); + + system_time.tm_sec = system_time_so[time_keys::second].asInt(); + system_time.tm_min = system_time_so[time_keys::minute].asInt(); + // According to tm specification of tm type hour should be decreased by 1 + system_time.tm_hour = system_time_so[time_keys::hour].asInt() - 1; + system_time.tm_mday = system_time_so[time_keys::day].asInt(); + // According to tm specification of tm type mon should be decreased by 1 + system_time.tm_mon = system_time_so[time_keys::month].asInt() - 1; + // According to tm specification of tm type + // tm_year - number of years since 1900 + system_time.tm_year = system_time_so[time_keys::year].asInt() - 1900; + + // Normalize and convert time from 'tm' format to 'time_t' + last_time_ = mktime(&system_time); + + sync_primitives::AutoLock lock(system_time_listener_lock_); + if (system_time_listener_) { + system_time_listener_->OnSystemTimeArrived(last_time_); + } +} + +} // namespace application_manager diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 5b26304302..b97c6eacd4 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -316,6 +316,7 @@ void ConnectionHandlerImpl::RemoveConnection( bool AllowProtection(const ConnectionHandlerSettings& settings, const protocol_handler::ServiceType& service_type, const bool is_protected) { + LOG4CXX_AUTO_TRACE(logger_); const std::vector& force_unprotected_list = is_protected ? settings.force_unprotected_service() : settings.force_protected_service(); diff --git a/src/components/include/policy/policy_regular/policy/policy_manager.h b/src/components/include/policy/policy_regular/policy/policy_manager.h index 3e90cfc094..f14cce6c4f 100644 --- a/src/components/include/policy/policy_regular/policy/policy_manager.h +++ b/src/components/include/policy/policy_regular/policy/policy_manager.h @@ -504,6 +504,12 @@ class PolicyManager : public usage_statistics::StatisticsManager { */ virtual bool HasCertificate() const = 0; + /** + * @brief Sets decrypted certificate in policy table + * @param certificate content of certificate + */ + virtual void SetDecryptedCertificate(const std::string& certificate) = 0; + /** * @brief Getter for policy settings * @return policy settings instance diff --git a/src/components/include/protocol_handler/protocol_handler.h b/src/components/include/protocol_handler/protocol_handler.h index 6aafd7d53f..1da8d61e52 100644 --- a/src/components/include/protocol_handler/protocol_handler.h +++ b/src/components/include/protocol_handler/protocol_handler.h @@ -103,6 +103,12 @@ class ProtocolHandler { virtual void SendEndService(int32_t connection_id, uint8_t session_id, uint8_t service_type) = 0; + + /** + * \brief Called to notify all handsheke handlers about handshake failure. + */ + virtual void NotifyOnFailedHandshake() = 0; + /** * \brief Protocol handler settings getter * \return pointer to protocol handler settings class diff --git a/src/components/include/security_manager/crypto_manager.h b/src/components/include/security_manager/crypto_manager.h index 18c06ffe06..486b6da64f 100644 --- a/src/components/include/security_manager/crypto_manager.h +++ b/src/components/include/security_manager/crypto_manager.h @@ -33,6 +33,7 @@ #ifndef SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_CRYPTO_MANAGER_H_ #define SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_CRYPTO_MANAGER_H_ +#include #include "application_manager/policies/policy_handler_observer.h" #include "security_manager/security_manager_settings.h" @@ -65,8 +66,16 @@ class CryptoManager : public policy::PolicyHandlerObserver { virtual bool OnCertificateUpdated(const std::string& data) = 0; virtual void ReleaseSSLContext(SSLContext* context) = 0; virtual std::string LastError() const = 0; - - virtual bool IsCertificateUpdateRequired() const = 0; + /** + * @brief IsCertificateUpdateRequired checks if certificate update is needed + * @param system_time - time with which certificate expiration time + * should be compared + * @param certificates_time - certificate expiration time + * @return True if certificate expired and need to be updated + * otherwise False + */ + virtual bool IsCertificateUpdateRequired( + const time_t system_time, const time_t certificates_time) const = 0; /** * \brief Crypto manager settings getter * \return pointer to crypto manager settings class diff --git a/src/components/include/security_manager/security_manager.h b/src/components/include/security_manager/security_manager.h index 8f772f6a13..6ad5e96989 100644 --- a/src/components/include/security_manager/security_manager.h +++ b/src/components/include/security_manager/security_manager.h @@ -41,6 +41,7 @@ #include "protocol_handler/session_observer.h" #include "security_manager/security_manager_listener.h" +#include "application_manager/policies/policy_handler_observer.h" namespace security_manager { @@ -50,7 +51,8 @@ class CryptoManager; * protocol_handler::ProtocolObserver * and provide interface for handling Security queries from mobile side */ -class SecurityManager : public protocol_handler::ProtocolObserver { +class SecurityManager : public protocol_handler::ProtocolObserver, + public policy::PolicyHandlerObserver { public: /** * \brief InternalErrors is 1 byte identifier of internal error @@ -70,6 +72,10 @@ class SecurityManager : public protocol_handler::ProtocolObserver { ERROR_INTERNAL = 0xFF, ERROR_UNKNOWN_INTERNAL_ERROR = 0xFE // error value for testing }; + + // SSL context creation strategy + enum ContextCreationStrategy { kUseExisting = 0, kForceRecreation }; + /** * \brief Sets pointer for Connection Handler layer for managing sessions * \param session_observer pointer to object of the class implementing @@ -114,24 +120,42 @@ class SecurityManager : public protocol_handler::ProtocolObserver { } /** - * \brief Create new SSLContext for connection or return exists + * @brief Create new SSLContext for connection or return exists * Do not notify listeners, send security error on occure - * \param connection_key Unique key used by other components as session + * @param connection_key Unique key used by other components as session * identifier + * @param cc_strategy - SSL context creation strategy * @return new \c SSLContext or \c NULL on any error */ - virtual SSLContext* CreateSSLContext(const uint32_t& connection_key) = 0; + virtual SSLContext* CreateSSLContext(const uint32_t& connection_key, + ContextCreationStrategy cc_strategy) = 0; /** * \brief Start handshake as SSL client */ virtual void StartHandshake(uint32_t connection_key) = 0; + /** + * @brief PostponeHandshake allows to postpone handshake. It notifies + * cryptomanager that certificate should be updated and adds specified + * connection key to the list of the certificate awaiting connections. + * @param connection_key the identifier for connection to postpone handshake. + */ + virtual void PostponeHandshake(const uint32_t connection_key) = 0; + /** * @brief Check whether certificate should be updated + * @param connection_key the connection identifier to check certificate for. * @return true if certificate should be updated otherwise false */ - virtual bool IsCertificateUpdateRequired() = 0; + virtual bool IsCertificateUpdateRequired(const uint32_t connection_key) = 0; + + /** + * @brief Checks whether system time ready notification + * was received from hmi + * @return true if received otherwise false + */ + virtual bool IsSystemTimeProviderReady() const = 0; /** * @brief Notify all listeners that certificate update required @@ -150,6 +174,18 @@ class SecurityManager : public protocol_handler::ProtocolObserver { */ virtual void AddListener(SecurityManagerListener* const listener) = 0; virtual void RemoveListener(SecurityManagerListener* const listener) = 0; + + /** + * @brief OnCertificateUpdated allows to obtain notification when certificate + * has been updated with policy table update. Pass this certificate to crypto + * manager for further processing. Also process postopnes handshake for the + * certain connection key. + * + * @param data the certificates content. + * + * @return always true. + */ + virtual bool OnCertificateUpdated(const std::string& data) = 0; }; } // namespace security_manager #endif // SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_SECURITY_MANAGER_H_ diff --git a/src/components/include/security_manager/security_manager_listener.h b/src/components/include/security_manager/security_manager_listener.h index aeb3334a56..5942839b58 100644 --- a/src/components/include/security_manager/security_manager_listener.h +++ b/src/components/include/security_manager/security_manager_listener.h @@ -47,6 +47,12 @@ class SecurityManagerListener { */ virtual bool OnHandshakeDone(uint32_t connection_key, SSLContext::HandshakeResult result) = 0; + + /** + * @brief Notification about handshake failure + */ + virtual void OnHandshakeFailed() = 0; + /** * @brief Notify listeners that certificate update is required. */ diff --git a/src/components/include/security_manager/ssl_context.h b/src/components/include/security_manager/ssl_context.h index 86997edbd9..9d66e1af2f 100644 --- a/src/components/include/security_manager/ssl_context.h +++ b/src/components/include/security_manager/ssl_context.h @@ -81,10 +81,11 @@ class SSLContext { HandshakeContext(const custom_str::CustomString& exp_sn, const custom_str::CustomString& exp_cn) - : expected_sn(exp_sn), expected_cn(exp_cn) {} + : expected_sn(exp_sn), expected_cn(exp_cn), system_time(time(NULL)) {} custom_str::CustomString expected_sn; custom_str::CustomString expected_cn; + time_t system_time; }; virtual HandshakeResult StartHandshake(const uint8_t** const out_data, @@ -103,6 +104,14 @@ class SSLContext { size_t* out_data_size) = 0; virtual bool IsInitCompleted() const = 0; virtual bool IsHandshakePending() const = 0; + /** + * @brief GetCertificateDueDate gets certificate expiration date + * @param due_date - certificate expiration time to be received + * @return True if certificate expiration date received + * otherwise False + */ + virtual bool GetCertificateDueDate(time_t& due_date) const = 0; + virtual bool HasCertificate() const = 0; virtual size_t get_max_block_size(size_t mtu) const = 0; virtual std::string LastError() const = 0; diff --git a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h index ed3a5088c1..c9f53b8606 100644 --- a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h +++ b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h @@ -206,7 +206,7 @@ class MockCacheManagerInterface : public CacheManagerInterface { MOCK_METHOD1(GetHMITypes, const policy_table::AppHMITypes*(const std::string& app_id)); MOCK_CONST_METHOD0(GetCertificate, std::string()); - MOCK_METHOD1(SetDecryptedCertificate, void(const std::string&)); + MOCK_CONST_METHOD1(SetDecryptedCertificate, void(const std::string&)); MOCK_METHOD1(GetGroups, const policy_table::Strings&(const PTString& app_id)); MOCK_CONST_METHOD2(AppHasHMIType, bool(const std::string& application_id, 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 79c2188cdf..e667911944 100644 --- a/src/components/include/test/protocol_handler/mock_protocol_handler.h +++ b/src/components/include/test/protocol_handler/mock_protocol_handler.h @@ -72,6 +72,7 @@ class MockProtocolHandler : public ::protocol_handler::ProtocolHandler { MOCK_METHOD2(NotifySessionStarted, void(const ::protocol_handler::SessionContext& context, std::vector& rejected_params)); + MOCK_METHOD0(NotifyOnFailedHandshake, void()); }; } // namespace protocol_handler_test } // namespace components diff --git a/src/components/include/test/security_manager/mock_crypto_manager.h b/src/components/include/test/security_manager/mock_crypto_manager.h index 55c364bd89..61ec5183e4 100644 --- a/src/components/include/test/security_manager/mock_crypto_manager.h +++ b/src/components/include/test/security_manager/mock_crypto_manager.h @@ -52,7 +52,9 @@ class MockCryptoManager : public ::security_manager::CryptoManager { MOCK_METHOD0(CreateSSLContext, ::security_manager::SSLContext*()); MOCK_METHOD1(ReleaseSSLContext, void(::security_manager::SSLContext*)); MOCK_CONST_METHOD0(LastError, std::string()); - MOCK_CONST_METHOD0(IsCertificateUpdateRequired, bool()); + MOCK_CONST_METHOD2(IsCertificateUpdateRequired, + bool(const time_t system_time, + const time_t certificates_time)); }; } // namespace security_manager_test } // namespace components 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 11890cb071..153ce85422 100644 --- a/src/components/include/test/security_manager/mock_security_manager.h +++ b/src/components/include/test/security_manager/mock_security_manager.h @@ -54,8 +54,9 @@ class MockSecurityManager : public ::security_manager::SecurityManager { MOCK_METHOD4( SendInternalError, void(const uint32_t, const uint8_t&, const std::string&, const uint32_t)); - MOCK_METHOD1(CreateSSLContext, - ::security_manager::SSLContext*(const uint32_t&)); + MOCK_METHOD2(CreateSSLContext, + ::security_manager::SSLContext*(const uint32_t&, + ContextCreationStrategy)); MOCK_METHOD1(StartHandshake, void(uint32_t)); MOCK_METHOD1(AddListener, void(::security_manager::SecurityManagerListener*)); MOCK_METHOD1(RemoveListener, @@ -65,9 +66,12 @@ class MockSecurityManager : public ::security_manager::SecurityManager { void(const ::protocol_handler::RawMessagePtr)); MOCK_METHOD1(OnMobileMessageSent, void(const ::protocol_handler::RawMessagePtr)); - MOCK_METHOD0(IsCertificateUpdateRequired, bool()); + MOCK_METHOD1(IsCertificateUpdateRequired, bool(const uint32_t)); MOCK_METHOD0(NotifyOnCertificateUpdateRequired, void()); MOCK_METHOD0(IsPolicyCertificateDataEmpty, bool()); + MOCK_METHOD1(OnCertificateUpdated, bool(const std::string&)); + MOCK_METHOD1(PostponeHandshake, void(const uint32_t)); + MOCK_CONST_METHOD0(IsSystemTimeProviderReady, 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 a06762a09d..76273b244d 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 @@ -49,6 +49,7 @@ class MockSecurityManagerListener ::security_manager::SSLContext::HandshakeResult result)); MOCK_METHOD0(OnCertificateUpdateRequired, void()); MOCK_CONST_METHOD1(GetPolicyCertificateData, bool(std::string& data)); + MOCK_METHOD0(OnHandshakeFailed, void()); }; } // namespace security_manager_test } // namespace components diff --git a/src/components/include/test/security_manager/mock_ssl_context.h b/src/components/include/test/security_manager/mock_ssl_context.h index 6b6a26a226..02198d1d22 100644 --- a/src/components/include/test/security_manager/mock_ssl_context.h +++ b/src/components/include/test/security_manager/mock_ssl_context.h @@ -68,6 +68,8 @@ class MockSSLContext : public ::security_manager::SSLContext { MOCK_CONST_METHOD0(LastError, std::string()); MOCK_METHOD0(ResetConnection, void()); MOCK_METHOD1(SetHandshakeContext, void(const HandshakeContext& hsh_ctx)); + MOCK_CONST_METHOD0(HasCertificate, bool()); + MOCK_CONST_METHOD1(GetCertificateDueDate, bool(time_t& due_date)); }; } // namespace security_manager_test } // namespace components diff --git a/src/components/include/test/utils/mock_system_time_handler.h b/src/components/include/test/utils/mock_system_time_handler.h new file mode 100644 index 0000000000..ef80e698f5 --- /dev/null +++ b/src/components/include/test/utils/mock_system_time_handler.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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_INCLUDE_TEST_SECURITY_MANAGER_MOCK_SYSTEM_TIME_HANDLER_H +#define SRC_COMPONENTS_INCLUDE_TEST_SECURITY_MANAGER_MOCK_SYSTEM_TIME_HANDLER_H + +#include "gmock/gmock.h" +#include "utils/system_time_handler.h" + +namespace test { +namespace components { +namespace security_manager_test { + +class MockSystemTimeHandler : public ::utils::SystemTimeHandler { + public: + MockSystemTimeHandler() {} + MOCK_METHOD0(QuerySystemTime, void()); + MOCK_METHOD1(SubscribeOnSystemTime, + void(utils::SystemTimeListener* listener)); + MOCK_METHOD1(UnSubscribeFromSystemTime, + void(utils::SystemTimeListener* listener)); + MOCK_METHOD0(GetUTCTime, time_t()); + MOCK_CONST_METHOD0(system_time_can_be_received, bool()); + ~MockSystemTimeHandler() {} + + private: + void DoSubscribe(utils::SystemTimeListener*) {} + void DoSystemTimeQuery() {} + void DoUnsubscribe(utils::SystemTimeListener* listener) {} + bool utc_time_can_be_received() const { + return true; + } + time_t FetchSystemTime() { + return 0; + } +}; +} // namespace security_manager_test +} // namespace components +} // namespace test +#endif // SRC_COMPONENTS_INCLUDE_TEST_SECURITY_MANAGER_MOCK_SYSTEM_TIME_HANDLER_H diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index ab3933fc0f..5d46fce942 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -2747,6 +2747,16 @@ + + Allows to obtain current sytem time + + + + + + + HMI notifies SDL with this notification that NAVI module is ready to provide system time. + HMI must notify SDL about its readiness to start communication. In fact, this has to be the first message between SDL and HMI. diff --git a/src/components/policy/policy_regular/include/policy/cache_manager.h b/src/components/policy/policy_regular/include/policy/cache_manager.h index 8c0acd44d2..f3fcfccd13 100644 --- a/src/components/policy/policy_regular/include/policy/cache_manager.h +++ b/src/components/policy/policy_regular/include/policy/cache_manager.h @@ -279,6 +279,12 @@ class CacheManager : public CacheManagerInterface { */ bool IsDefaultPolicy(const std::string& app_id) const OVERRIDE; + /** + * @brief Sets decrypted certificate in policy table + * @param certificate content of certificate + */ + void SetDecryptedCertificate(const std::string& certificate) const OVERRIDE; + /** * @brief SetIsDefault Sets is_default flag for application * @param app_id app specific application diff --git a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h index 9f7c7318db..842d8274eb 100644 --- a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h +++ b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h @@ -276,6 +276,13 @@ class CacheManagerInterface { */ virtual bool IsDefaultPolicy(const std::string& app_id) const = 0; + /** + * @brief Sets decrypted certificate in policy table + * @param certificate content of certificate + */ + virtual void SetDecryptedCertificate( + const std::string& certificate) const = 0; + /** * @brief SetIsDefault Sets is_default flag for application * @param app_id app specific application diff --git a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h index 941db1a67f..6329abbb04 100644 --- a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h +++ b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h @@ -570,6 +570,8 @@ class PolicyManagerImpl : public PolicyManager { */ bool HasCertificate() const OVERRIDE; + void SetDecryptedCertificate(const std::string& certificate) OVERRIDE; + /** * @brief Finds the next URL that must be sent on OnSystemRequest retry * @param urls vector of vectors that contain urls for each application diff --git a/src/components/policy/policy_regular/src/cache_manager.cc b/src/components/policy/policy_regular/src/cache_manager.cc index 6a142374d5..8390a232c3 100644 --- a/src/components/policy/policy_regular/src/cache_manager.cc +++ b/src/components/policy/policy_regular/src/cache_manager.cc @@ -1290,6 +1290,13 @@ bool CacheManager::IsDefaultPolicy(const std::string& app_id) const { return result; } +void CacheManager::SetDecryptedCertificate( + const std::string& certificate) const { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock auto_lock(cache_lock_); + *pt_->policy_table.module_config.certificate = certificate; +} + bool CacheManager::SetIsDefault(const std::string& app_id) { CACHE_MANAGER_CHECK(false); sync_primitives::AutoLock auto_lock(cache_lock_); diff --git a/src/components/policy/policy_regular/src/policy_manager_impl.cc b/src/components/policy/policy_regular/src/policy_manager_impl.cc index 39b303cbb5..305424ba4c 100644 --- a/src/components/policy/policy_regular/src/policy_manager_impl.cc +++ b/src/components/policy/policy_regular/src/policy_manager_impl.cc @@ -1021,6 +1021,13 @@ bool PolicyManagerImpl::HasCertificate() const { return !cache_->GetCertificate().empty(); } +void PolicyManagerImpl::SetDecryptedCertificate( + const std::string& certificate) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->SetDecryptedCertificate(certificate); + cache_->Backup(); +} + class CallStatusChange : public utils::Callable { public: CallStatusChange(UpdateStatusManager& upd_manager, diff --git a/src/components/protocol_handler/include/protocol_handler/handshake_handler.h b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h index 0ef40290f2..5d536eebad 100644 --- a/src/components/protocol_handler/include/protocol_handler/handshake_handler.h +++ b/src/components/protocol_handler/include/protocol_handler/handshake_handler.h @@ -89,6 +89,13 @@ class HandshakeHandler : public security_manager::SecurityManagerListener { uint32_t connection_key, security_manager::SSLContext::HandshakeResult result) OVERRIDE; + /** + * @brief Notification about handshake failure + * Gets parameters from payload and processes + * handshake failure procedure + */ + void OnHandshakeFailed() OVERRIDE; + /** * @brief Notification that certificate update is required. */ 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 0efb81cdd7..4d86a78688 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 @@ -235,6 +235,8 @@ class ProtocolHandlerImpl uint8_t session_id, uint8_t service_type); + void NotifyOnFailedHandshake() OVERRIDE; + // TODO(Ezamakhov): move Ack/Nack as interface for StartSessionHandler /** * \brief Sends acknowledgement of starting session to mobile application @@ -686,7 +688,9 @@ class ProtocolHandlerImpl bool is_ptu_triggered_; std::list > ptu_pending_handlers_; + std::list > handshake_handlers_; sync_primitives::Lock ptu_handlers_lock_; + sync_primitives::Lock handshake_handlers_lock_; #endif // ENABLE_SECURITY // Thread that pumps non-parsed messages coming from mobile side. diff --git a/src/components/protocol_handler/src/handshake_handler.cc b/src/components/protocol_handler/src/handshake_handler.cc index 055ff2cf45..74987ac2bd 100644 --- a/src/components/protocol_handler/src/handshake_handler.cc +++ b/src/components/protocol_handler/src/handshake_handler.cc @@ -92,6 +92,17 @@ bool HandshakeHandler::GetPolicyCertificateData(std::string& data) const { void HandshakeHandler::OnCertificateUpdateRequired() {} +void HandshakeHandler::OnHandshakeFailed() { + BsonObject params; + if (payload_) { + params = bson_object_from_bytes(payload_.get()); + } else { + bson_object_initialize_default(¶ms); + } + ProcessFailedHandshake(params); + bson_object_deinitialize(¶ms); +} + bool HandshakeHandler::OnHandshakeDone( uint32_t connection_key, security_manager::SSLContext::HandshakeResult result) { diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index 762b986782..dcb7999ef9 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -149,6 +149,7 @@ ProtocolHandlerImpl::~ProtocolHandlerImpl() { "Not all observers have unsubscribed" " from ProtocolHandlerImpl"); } + handshake_handlers_.clear(); } void ProtocolHandlerImpl::AddProtocolObserver(ProtocolObserver* observer) { @@ -839,6 +840,18 @@ void ProtocolHandlerImpl::OnConnectionClosed( multiframe_builder_.RemoveConnection(connection_id); } +void ProtocolHandlerImpl::NotifyOnFailedHandshake() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(handshake_handlers_lock_); + + std::for_each( + handshake_handlers_.begin(), + handshake_handlers_.end(), + std::bind(&HandshakeHandler::OnHandshakeFailed, std::placeholders::_1)); + + handshake_handlers_.clear(); +} + void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { LOG4CXX_AUTO_TRACE(logger_); @@ -851,12 +864,14 @@ void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { return; } - const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired(); for (auto handler : ptu_pending_handlers_) { + const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired( + handler->connection_key()); security_manager::SSLContext* ssl_context = - is_cert_expired - ? NULL - : security_manager_->CreateSSLContext(handler->connection_key()); + is_cert_expired ? NULL + : security_manager_->CreateSSLContext( + handler->connection_key(), + security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); @@ -1286,7 +1301,8 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( session_observer_.KeyFromPair(connection_id, session_id); security_manager::SSLContext* ssl_context = - security_manager_->CreateSSLContext(connection_key); + security_manager_->CreateSSLContext( + connection_key, security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -1563,14 +1579,11 @@ void ProtocolHandlerImpl::NotifySessionStarted( context, packet->protocol_version(), bson_object_bytes); + handshake_handlers_.push_back(handler); const bool is_certificate_empty = security_manager_->IsPolicyCertificateDataEmpty(); - const bool is_certificate_expired = - is_certificate_empty || - security_manager_->IsCertificateUpdateRequired(); - if (context.is_ptu_required_ && is_certificate_empty) { LOG4CXX_DEBUG(logger_, "PTU for StartSessionHandler " @@ -1586,6 +1599,7 @@ void ProtocolHandlerImpl::NotifySessionStarted( ptu_pending_handlers_.push_back(handler); is_ptu_triggered_ = true; security_manager_->NotifyOnCertificateUpdateRequired(); + security_manager_->PostponeHandshake(connection_key); } else { LOG4CXX_DEBUG(logger_, "PTU has been triggered. Added to pending."); ptu_pending_handlers_.push_back(handler); @@ -1594,9 +1608,11 @@ void ProtocolHandlerImpl::NotifySessionStarted( } security_manager::SSLContext* ssl_context = - is_certificate_expired + is_certificate_empty ? NULL - : security_manager_->CreateSSLContext(connection_key); + : security_manager_->CreateSSLContext( + connection_key, + security_manager::SecurityManager::kUseExisting); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -1630,10 +1646,18 @@ void ProtocolHandlerImpl::NotifySessionStarted( *fullVersion, *start_session_ack_params); } else { + LOG4CXX_DEBUG(logger_, "Adding Handshake handler to listenets:"); security_manager_->AddListener(new HandshakeHandler(*handler)); if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); + if (!security_manager_->IsSystemTimeProviderReady()) { + SendStartSessionNAck(context.connection_id_, + packet->session_id(), + protocol_version, + packet->service_type(), + rejected_params); + } } } LOG4CXX_DEBUG(logger_, 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 77de1705da..028c7ee332 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -46,6 +46,7 @@ #include "security_manager/mock_ssl_context.h" #endif // ENABLE_SECURITY #include "transport_manager/mock_transport_manager.h" +#include "utils/mock_system_time_handler.h" #include "utils/make_shared.h" #include "utils/test_async_waiter.h" #include @@ -95,8 +96,12 @@ using protocol_handler::kBulk; using protocol_handler::kInvalidServiceType; // For TM states using transport_manager::TransportManagerListener; +using test::components::security_manager_test::MockSystemTimeHandler; using transport_manager::E_SUCCESS; using transport_manager::DeviceInfo; +// For security +using ContextCreationStrategy = + security_manager::SecurityManager::ContextCreationStrategy; // For CH entities using connection_handler::DeviceHandle; // Google Testing Framework Entities @@ -987,7 +992,10 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtected_Fail) { SetProtocolVersion2(); // Expect start protection for unprotected session - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return fail protection WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); @@ -1042,7 +1050,7 @@ TEST_F(ProtocolHandlerImplTest, SetProtocolVersion2(); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1119,7 +1127,7 @@ TEST_F(ProtocolHandlerImplTest, .WillOnce(ReturnRefOfCopy(services)); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce(Return(&ssl_context_mock)); @@ -1198,7 +1206,7 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1296,7 +1304,7 @@ TEST_F( times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1392,7 +1400,10 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return new SSLContext WillOnce( @@ -1420,27 +1431,37 @@ TEST_F(ProtocolHandlerImplTest, // Expect add listener for handshake result EXPECT_CALL(security_manager_mock, AddListener(_)) - // Emulate handshake fail - .WillOnce(Invoke(OnHandshakeDoneFunctor( - connection_key, - security_manager::SSLContext::Handshake_Result_Success))); + // Emulate handshake + .WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + Invoke(OnHandshakeDoneFunctor( + connection_key, + security_manager::SSLContext::Handshake_Result_Success)))); + times++; // Listener check SSLContext EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, start_service)) . // Emulate protection for service is not enabled - WillOnce(ReturnNull()); + WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); + times++; + + EXPECT_CALL(security_manager_mock, IsSystemTimeProviderReady()) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); + times++; - // Expect service protection enable EXPECT_CALL(session_observer_mock, - SetProtectionFlag(connection_key, start_service)); + SetProtectionFlag(connection_key, start_service)) + .WillOnce(NotifyTestAsyncWaiter(&waiter)); + times++; - // Expect send Ack with PROTECTION_OFF (on fail handshake) + // Expect send Ack with PROTECTION_ON (on successfull handshake) EXPECT_CALL(transport_manager_mock, SendMessageToDevice( ControlMessage(FRAME_DATA_START_SERVICE_ACK, PROTECTION_ON))) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; SendControlMessage( 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 4e48858e5c..c31e02cf48 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 @@ -71,6 +71,8 @@ class CryptoManagerImpl : public CryptoManager { size_t* out_data_size) OVERRIDE; bool IsInitCompleted() const OVERRIDE; bool IsHandshakePending() const OVERRIDE; + bool GetCertificateDueDate(time_t& due_date) const OVERRIDE; + bool HasCertificate() const OVERRIDE; size_t get_max_block_size(size_t mtu) const OVERRIDE; std::string LastError() const OVERRIDE; void ResetConnection() OVERRIDE; @@ -101,6 +103,22 @@ class CryptoManagerImpl : public CryptoManager { std::string GetTextBy(X509_NAME* name, int object) const; + /** + * @brief Pulls number stored in buffer of chars + * and returns it as integer + * @param buf where symbols stored + * @param idx index of required char to be converted + * @return number in integer representation + */ + int get_number_from_char_buf(char* buf, int* idx) const; + /** + * @brief Converts time from ASN1 format (used in OpenSSL) + * to time_t data type + * @param time_to_convert time to be converted + * @return time in time_t format + */ + time_t convert_asn1_time_to_time_t(ASN1_TIME* time_to_convert) const; + SSL* connection_; BIO* bioIn_; BIO* bioOut_; @@ -128,15 +146,13 @@ class CryptoManagerImpl : public CryptoManager { SSLContext* CreateSSLContext() OVERRIDE; void ReleaseSSLContext(SSLContext* context) OVERRIDE; std::string LastError() const OVERRIDE; - virtual bool IsCertificateUpdateRequired() const OVERRIDE; + bool IsCertificateUpdateRequired( + const time_t system_time, const time_t certificates_time) const OVERRIDE; virtual const CryptoManagerSettings& get_settings() const OVERRIDE; private: bool set_certificate(const std::string& cert_data); - int pull_number_from_buf(char* buf, int* idx); - void asn1_time_to_tm(ASN1_TIME* time); - /** * @brief Sets initial certificate datetime */ 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 469b97d1e1..ab093cc576 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 @@ -35,6 +35,8 @@ #include #include +#include +#include #include "utils/macro.h" #include "utils/message_queue.h" @@ -44,6 +46,7 @@ #include "security_manager/security_query.h" #include "protocol_handler/protocol_handler.h" #include "protocol/common.h" +#include "utils/system_time_handler.h" namespace security_manager { /** @@ -67,12 +70,21 @@ typedef threads::MessageLoopThread SecurityMessageLoop; * \brief SecurityManagerImpl class implements SecurityManager interface */ class SecurityManagerImpl : public SecurityManager, - public SecurityMessageLoop::Handler { + public SecurityMessageLoop::Handler, + public utils::SystemTimeListener { public: /** * \brief Constructor + * \param system_time_handler allows to work with system time. */ - SecurityManagerImpl(); + explicit SecurityManagerImpl( + std::unique_ptr&& system_time_handler); + + /** + * \brief Destructor + */ + ~SecurityManagerImpl(); + /** * \brief Add received from Mobile Application message * Overriden ProtocolObserver::OnMessageReceived method @@ -133,24 +145,41 @@ class SecurityManagerImpl : public SecurityManager, * identifier * @return new \c SSLContext or \c NULL on any error */ - SSLContext* CreateSSLContext(const uint32_t& connection_key) OVERRIDE; + SSLContext* CreateSSLContext(const uint32_t& connection_key, + ContextCreationStrategy cc_strategy) OVERRIDE; /** * \brief Start handshake as SSL client */ void StartHandshake(uint32_t connection_key) OVERRIDE; + /** + * @brief PostponeHandshake allows to postpone handshake. It notifies + * cryptomanager that certificate should be updated and adds specified + * connection key to the list of the certificate awaiting connections. + * @param connection_key the identifier for connection to postpone handshake. + */ + void PostponeHandshake(const uint32_t connection_key) OVERRIDE; + /** * @brief Checks whether certificate should be updated * @return true if certificate should be updated otherwise false */ - bool IsCertificateUpdateRequired() OVERRIDE; + bool IsCertificateUpdateRequired(const uint32_t connection_key) OVERRIDE; + + /** + * @brief Checks whether system time ready notification + * was received from hmi + * @return true if received otherwise false + */ + bool IsSystemTimeProviderReady() const OVERRIDE; /** * \brief Add/Remove for SecurityManagerListener */ void AddListener(SecurityManagerListener* const listener) OVERRIDE; void RemoveListener(SecurityManagerListener* const listener) OVERRIDE; + /** * \brief Notifiers for listeners * \param connection_key Unique key used by other components as session @@ -217,6 +246,39 @@ class SecurityManagerImpl : public SecurityManager, */ void SendQuery(const SecurityQuery& query, const uint32_t connection_key); + /** + * @brief OnCertificateUpdated allows to obtain notification when certificate + * has been updated with policy table update. Pass this certificate to crypto + * manager for further processing. Also process postopnes handshake for the + * certain connection key. + * + * @param data the certificates content. + * @return always true. + */ + bool OnCertificateUpdated(const std::string& data) OVERRIDE; + + /** + * @brief ResumeHandshake allows to resume handshake after certificate has + * been updated. + * @param connection_key the connection identifier to start handshake. + */ + void ResumeHandshake(uint32_t connection_key); + + /** + * @brief ProceedHandshake starts the handshake process. + * @param ssl_context ssl context for the handshake. COntains certificate, + * keys, etc. + * @param connection_key the connection identifier to process handshake. + */ + void ProceedHandshake(SSLContext* ssl_context, uint32_t connection_key); + + /** + * @brief OnSystemTimeArrived method which notifies + * crypto manager with updated time in order to check certificate validity + * @param utc_time the current system time. + */ + void OnSystemTimeArrived(const time_t utc_time) OVERRIDE; + // Thread that pumps handshake data SecurityMessageLoop security_messages_; @@ -235,7 +297,17 @@ class SecurityManagerImpl : public SecurityManager, /** *\brief List of listeners for notify handshake done result */ + std::list listeners_; + + std::unique_ptr system_time_handler_; + sync_primitives::Lock connections_lock_; + std::set awaiting_certificate_connections_; + std::set awaiting_time_connections_; + + mutable sync_primitives::Lock waiters_lock_; + volatile bool waiting_for_certificate_; + volatile bool waiting_for_time_; DISALLOW_COPY_AND_ASSIGN(SecurityManagerImpl); }; } // namespace security_manager diff --git a/src/components/security_manager/src/crypto_manager_impl.cc b/src/components/security_manager/src/crypto_manager_impl.cc index 6bee28a976..8db1d633a7 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -63,7 +63,12 @@ namespace { int debug_callback(int preverify_ok, X509_STORE_CTX* ctx) { if (!preverify_ok) { const int error = X509_STORE_CTX_get_error(ctx); - UNUSED(error); + if (error == X509_V_ERR_CERT_NOT_YET_VALID || + error == X509_V_ERR_CERT_HAS_EXPIRED) { + // return success result code instead of error because start + // and expiration cert dates will be checked by SDL + return 1; + } LOG4CXX_WARN(logger_, "Certificate verification failed with error " << error << " \"" << X509_verify_cert_error_string(error) @@ -264,24 +269,17 @@ std::string CryptoManagerImpl::LastError() const { return std::string(reason ? reason : ""); } -bool CryptoManagerImpl::IsCertificateUpdateRequired() const { +bool CryptoManagerImpl::IsCertificateUpdateRequired( + const time_t system_time, const time_t certificates_time) const { LOG4CXX_AUTO_TRACE(logger_); - const time_t cert_date = mktime(&expiration_time_); + const double seconds = difftime(certificates_time, system_time); - if (cert_date == -1) { - LOG4CXX_WARN(logger_, - "The certifiacte expiration time cannot be represented."); - return false; - } - const time_t now = time(NULL); - const double seconds = difftime(cert_date, now); + LOG4CXX_DEBUG( + logger_, "Certificate UTC time: " << asctime(gmtime(&certificates_time))); - LOG4CXX_DEBUG(logger_, - "Certificate expiration time: " << asctime(&expiration_time_)); - LOG4CXX_DEBUG(logger_, - "Host time: " << asctime(localtime(&now)) - << ". Seconds before expiration: " << seconds); + LOG4CXX_DEBUG(logger_, "Host UTC time: " << asctime(gmtime(&system_time))); + LOG4CXX_DEBUG(logger_, "Seconds before expiration: " << seconds); if (seconds < 0) { LOG4CXX_WARN(logger_, "Certificate is already expired."); return true; @@ -331,8 +329,6 @@ bool CryptoManagerImpl::set_certificate(const std::string& cert_data) { return false; } - asn1_time_to_tm(X509_get_notAfter(cert)); - if (!SSL_CTX_use_PrivateKey(context_, pkey)) { LOG4CXX_ERROR(logger_, "Could not use key: " << LastError()); return false; @@ -359,7 +355,8 @@ bool CryptoManagerImpl::set_certificate(const std::string& cert_data) { return true; } -int CryptoManagerImpl::pull_number_from_buf(char* buf, int* idx) { +int CryptoManagerImpl::SSLContextImpl::get_number_from_char_buf( + char* buf, int* idx) const { if (!idx) { return 0; } @@ -368,40 +365,6 @@ int CryptoManagerImpl::pull_number_from_buf(char* buf, int* idx) { return val; } -void CryptoManagerImpl::asn1_time_to_tm(ASN1_TIME* time) { - char* buf = (char*)time->data; - int index = 0; - const int year = pull_number_from_buf(buf, &index); - if (V_ASN1_GENERALIZEDTIME == time->type) { - expiration_time_.tm_year = - (year * 100 - 1900) + pull_number_from_buf(buf, &index); - } else { - expiration_time_.tm_year = year < 50 ? year + 100 : year; - } - - const int mon = pull_number_from_buf(buf, &index); - const int day = pull_number_from_buf(buf, &index); - const int hour = pull_number_from_buf(buf, &index); - const int mn = pull_number_from_buf(buf, &index); - - expiration_time_.tm_mon = mon - 1; - expiration_time_.tm_mday = day; - expiration_time_.tm_hour = hour; - expiration_time_.tm_min = mn; - - if (buf[index] == 'Z') { - expiration_time_.tm_sec = 0; - } - if ((buf[index] == '+') || (buf[index] == '-')) { - const int mn = pull_number_from_buf(buf, &index); - const int mn1 = pull_number_from_buf(buf, &index); - expiration_time_.tm_sec = (mn * 3600) + (mn1 * 60); - } else { - const int sec = pull_number_from_buf(buf, &index); - expiration_time_.tm_sec = sec; - } -} - void CryptoManagerImpl::InitCertExpTime() { strptime("1 Jan 1970 00:00:00", "%d %b %Y %H:%M:%S", &expiration_time_); } diff --git a/src/components/security_manager/src/security_manager_impl.cc b/src/components/security_manager/src/security_manager_impl.cc index 1853b218b4..d68e6b456e 100644 --- a/src/components/security_manager/src/security_manager_impl.cc +++ b/src/components/security_manager/src/security_manager_impl.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Ford Motor Company + * Copyright (c) 2018, Ford Motor Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,11 +31,13 @@ */ #include "security_manager/security_manager_impl.h" +#include #include "security_manager/crypto_manager_impl.h" #include "protocol_handler/protocol_packet.h" #include "utils/logger.h" #include "utils/byte_order.h" #include "json/json.h" +#include "utils/helpers.h" namespace security_manager { @@ -44,11 +46,22 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "SecurityManager") static const char* kErrId = "id"; static const char* kErrText = "text"; -SecurityManagerImpl::SecurityManagerImpl() +SecurityManagerImpl::SecurityManagerImpl( + std::unique_ptr&& system_time_handler) : security_messages_("SecurityManager", this) , session_observer_(NULL) , crypto_manager_(NULL) - , protocol_handler_(NULL) {} + , protocol_handler_(NULL) + , system_time_handler_(std::move(system_time_handler)) + , waiting_for_certificate_(false) + , waiting_for_time_(false) { + DCHECK(system_time_handler_); + system_time_handler_->SubscribeOnSystemTime(this); +} + +SecurityManagerImpl::~SecurityManagerImpl() { + system_time_handler_->UnSubscribeFromSystemTime(this); +} void SecurityManagerImpl::OnMessageReceived( const ::protocol_handler::RawMessagePtr message) { @@ -136,16 +149,20 @@ void SecurityManagerImpl::Handle(const SecurityMessage message) { } security_manager::SSLContext* SecurityManagerImpl::CreateSSLContext( - const uint32_t& connection_key) { + const uint32_t& connection_key, ContextCreationStrategy cc_strategy) { LOG4CXX_INFO(logger_, "ProtectService processing"); DCHECK(session_observer_); DCHECK(crypto_manager_); - security_manager::SSLContext* ssl_context = session_observer_->GetSSLContext( - connection_key, protocol_handler::kControl); - // return exists SSLCOntext for current connection/session - if (ssl_context) { - return ssl_context; + security_manager::SSLContext* ssl_context = NULL; + if (kUseExisting == cc_strategy) { + security_manager::SSLContext* ssl_context = + session_observer_->GetSSLContext(connection_key, + protocol_handler::kControl); + // If SSLContext for current connection/session exists - return it + if (ssl_context) { + return ssl_context; + } } ssl_context = crypto_manager_->CreateSSLContext(); @@ -172,6 +189,40 @@ security_manager::SSLContext* SecurityManagerImpl::CreateSSLContext( return ssl_context; } +void SecurityManagerImpl::PostponeHandshake(const uint32_t connection_key) { + LOG4CXX_TRACE(logger_, "Handshake postponed"); + sync_primitives::AutoLock lock(connections_lock_); + if (waiting_for_certificate_) { + awaiting_certificate_connections_.insert(connection_key); + } + if (waiting_for_time_) { + awaiting_time_connections_.insert(connection_key); + } +} + +void SecurityManagerImpl::ResumeHandshake(uint32_t connection_key) { + LOG4CXX_TRACE(logger_, "Handshake resumed"); + + security_manager::SSLContext* ssl_context = + CreateSSLContext(connection_key, kForceRecreation); + + if (!ssl_context) { + LOG4CXX_WARN(logger_, + "Unable to resume handshake. No SSL context for key " + << connection_key); + return; + } + + ssl_context->ResetConnection(); + if (!ssl_context->HasCertificate()) { + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); + return; + } + + ProceedHandshake(ssl_context, connection_key); +} + void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { DCHECK(session_observer_); LOG4CXX_INFO(logger_, "StartHandshake: connection_key " << connection_key); @@ -187,6 +238,35 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { SSLContext::Handshake_Result_Fail); return; } + if (!ssl_context->HasCertificate()) { + LOG4CXX_ERROR(logger_, "Security certificate is absent"); + sync_primitives::AutoLock lock(waiters_lock_); + waiting_for_certificate_ = true; + NotifyOnCertififcateUpdateRequired(); + } + + { + sync_primitives::AutoLock lock(waiters_lock_); + waiting_for_time_ = true; + } + + PostponeHandshake(connection_key); + system_time_handler_->QuerySystemTime(); +} + +bool SecurityManagerImpl::IsSystemTimeProviderReady() const { + return system_time_handler_->system_time_can_be_received(); +} + +void SecurityManagerImpl::ProceedHandshake( + security_manager::SSLContext* ssl_context, uint32_t connection_key) { + LOG4CXX_AUTO_TRACE(logger_); + if (!ssl_context) { + LOG4CXX_WARN(logger_, + "Unable to process handshake. No SSL context for key " + << connection_key); + return; + } if (ssl_context->IsInitCompleted()) { NotifyListenersOnHandshakeDone(connection_key, @@ -194,8 +274,33 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { return; } - ssl_context->SetHandshakeContext( - session_observer_->GetHandshakeContext(connection_key)); + time_t cert_due_date; + if (!ssl_context->GetCertificateDueDate(cert_due_date)) { + LOG4CXX_ERROR(logger_, "Failed to get certificate due date!"); + return; + } + + if (crypto_manager_->IsCertificateUpdateRequired( + system_time_handler_->GetUTCTime(), cert_due_date)) { + LOG4CXX_DEBUG(logger_, "Host certificate update required"); + if (helpers::in_range(awaiting_certificate_connections_, connection_key)) { + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_CertExpired); + return; + } + { + sync_primitives::AutoLock lock(waiters_lock_); + waiting_for_certificate_ = true; + } + PostponeHandshake(connection_key); + NotifyOnCertififcateUpdateRequired(); + return; + } + + SSLContext::HandshakeContext handshake_context = + session_observer_->GetHandshakeContext(connection_key); + handshake_context.system_time = system_time_handler_->GetUTCTime(); + ssl_context->SetHandshakeContext(handshake_context); size_t data_size = 0; const uint8_t* data = NULL; @@ -216,9 +321,21 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { } } -bool SecurityManagerImpl::IsCertificateUpdateRequired() { +bool SecurityManagerImpl::IsCertificateUpdateRequired( + const uint32_t connection_key) { LOG4CXX_AUTO_TRACE(logger_); - return crypto_manager_->IsCertificateUpdateRequired(); + security_manager::SSLContext* ssl_context = + CreateSSLContext(connection_key, kUseExisting); + DCHECK_OR_RETURN(ssl_context, true); + LOG4CXX_DEBUG(logger_, + "Set SSL context to connection_key " << connection_key); + time_t cert_due_date; + if (!ssl_context->GetCertificateDueDate(cert_due_date)) { + LOG4CXX_ERROR(logger_, "Failed to get certificate due date!"); + return true; + } + return crypto_manager_->IsCertificateUpdateRequired( + system_time_handler_->GetUTCTime(), cert_due_date); } void SecurityManagerImpl::AddListener(SecurityManagerListener* const listener) { @@ -227,7 +344,6 @@ void SecurityManagerImpl::AddListener(SecurityManagerListener* const listener) { "Invalid (NULL) pointer to SecurityManagerListener."); return; } - LOG4CXX_DEBUG(logger_, "Adding listener " << listener); listeners_.push_back(listener); } @@ -241,6 +357,37 @@ void SecurityManagerImpl::RemoveListener( listeners_.remove(listener); } +bool SecurityManagerImpl::OnCertificateUpdated(const std::string& data) { + LOG4CXX_AUTO_TRACE(logger_); + { + sync_primitives::AutoLock lock(waiters_lock_); + waiting_for_certificate_ = false; + } + crypto_manager_->OnCertificateUpdated(data); + std::for_each( + awaiting_certificate_connections_.begin(), + awaiting_certificate_connections_.end(), + std::bind1st(std::mem_fun(&SecurityManagerImpl::ResumeHandshake), this)); + + std::set().swap(awaiting_certificate_connections_); + return true; +} + +void SecurityManagerImpl::OnSystemTimeArrived(const time_t utc_time) { + LOG4CXX_AUTO_TRACE(logger_); + { + sync_primitives::AutoLock lock(waiters_lock_); + waiting_for_time_ = false; + } + + std::for_each( + awaiting_time_connections_.begin(), + awaiting_time_connections_.end(), + std::bind1st(std::mem_fun(&SecurityManagerImpl::ResumeHandshake), this)); + + std::set().swap(awaiting_time_connections_); +} + void SecurityManagerImpl::NotifyListenersOnHandshakeDone( const uint32_t& connection_key, SSLContext::HandshakeResult error) { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc index 5be5ff8363..69e22dc44e 100644 --- a/src/components/security_manager/src/ssl_context_impl.cc +++ b/src/components/security_manager/src/ssl_context_impl.cc @@ -77,6 +77,7 @@ bool CryptoManagerImpl::SSLContextImpl::IsInitCompleted() const { SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::StartHandshake( const uint8_t** const out_data, size_t* out_data_size) { + LOG4CXX_AUTO_TRACE(logger_); is_handshake_pending_ = true; return DoHandshakeStep(NULL, 0, out_data, out_data_size); } @@ -174,6 +175,7 @@ const std::string CryptoManagerImpl::SSLContextImpl::RemoveDisallowedInfo( void CryptoManagerImpl::SSLContextImpl::PrintCertData( X509* cert, const std::string& cert_owner) { + LOG4CXX_AUTO_TRACE(logger_); if (!cert) { LOG4CXX_DEBUG(logger_, "Empty certificate data"); return; @@ -206,6 +208,7 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertData( } void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() { + LOG4CXX_AUTO_TRACE(logger_); PrintCertData(SSL_get_certificate(connection_), "HU's"); STACK_OF(X509)* peer_certs = SSL_get_peer_cert_chain(connection_); @@ -217,12 +220,42 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() { SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::CheckCertContext() { + LOG4CXX_AUTO_TRACE(logger_); X509* cert = SSL_get_peer_certificate(connection_); if (!cert) { // According to the openssl documentation the peer certificate // might be ommitted for the SERVER but required for the cient. return CLIENT == mode_ ? Handshake_Result_Fail : Handshake_Result_Success; } + ASN1_TIME* notBefore = X509_get_notBefore(cert); + ASN1_TIME* notAfter = X509_get_notAfter(cert); + + time_t start = convert_asn1_time_to_time_t(notBefore); + time_t end = convert_asn1_time_to_time_t(notAfter); + + const double start_seconds = difftime(hsh_context_.system_time, start); + const double end_seconds = difftime(end, hsh_context_.system_time); + + if (start_seconds < 0) { + LOG4CXX_ERROR(logger_, + "Certificate is not yet valid. Time before validity " + << start_seconds << " seconds"); + return Handshake_Result_NotYetValid; + } else { + LOG4CXX_DEBUG(logger_, + "Time since certificate validity " << start_seconds + << "seconds"); + } + + if (end_seconds < 0) { + LOG4CXX_ERROR(logger_, + "Certificate already expired. Time after expiration " + << end_seconds << " seconds"); + return Handshake_Result_CertExpired; + } else { + LOG4CXX_DEBUG(logger_, + "Time until expiration " << end_seconds << "seconds"); + } X509_NAME* subj_name = X509_get_subject_name(cert); @@ -247,6 +280,47 @@ CryptoManagerImpl::SSLContextImpl::CheckCertContext() { return Handshake_Result_Success; } +time_t CryptoManagerImpl::SSLContextImpl::convert_asn1_time_to_time_t( + ASN1_TIME* time_to_convert) const { + struct tm cert_time; + memset(&cert_time, 0, sizeof(struct tm)); + // the minimum value for day of month is 1, otherwise exception will be thrown + cert_time.tm_mday = 1; + char* buf = reinterpret_cast(time_to_convert->data); + int index = 0; + const int year = get_number_from_char_buf(buf, &index); + if (V_ASN1_GENERALIZEDTIME == time_to_convert->type) { + cert_time.tm_year = + (year * 100 - 1900) + get_number_from_char_buf(buf, &index); + } else { + cert_time.tm_year = year < 50 ? year + 100 : year; + } + + const int mon = get_number_from_char_buf(buf, &index); + const int day = get_number_from_char_buf(buf, &index); + const int hour = get_number_from_char_buf(buf, &index); + const int mn = get_number_from_char_buf(buf, &index); + + cert_time.tm_mon = mon - 1; + cert_time.tm_mday = day; + cert_time.tm_hour = hour; + cert_time.tm_min = mn; + + if (buf[index] == 'Z') { + cert_time.tm_sec = 0; + } + if ((buf[index] == '+') || (buf[index] == '-')) { + const int mn = get_number_from_char_buf(buf, &index); + const int mn1 = get_number_from_char_buf(buf, &index); + cert_time.tm_sec = (mn * 3600) + (mn1 * 60); + } else { + const int sec = get_number_from_char_buf(buf, &index); + cert_time.tm_sec = sec; + } + + return mktime(&cert_time); +} + bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( const uint8_t** const out_data, size_t* out_data_size) { LOG4CXX_AUTO_TRACE(logger_); @@ -288,7 +362,9 @@ bool CryptoManagerImpl::SSLContextImpl::WriteHandshakeData( SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::PerformHandshake() { + LOG4CXX_AUTO_TRACE(logger_); const int handshake_result = SSL_do_handshake(connection_); + LOG4CXX_TRACE(logger_, "Handshake result: " << handshake_result); if (handshake_result == 1) { const HandshakeResult result = CheckCertContext(); if (result != Handshake_Result_Success) { @@ -307,6 +383,7 @@ CryptoManagerImpl::SSLContextImpl::PerformHandshake() { is_handshake_pending_ = false; } else if (handshake_result == 0) { + LOG4CXX_DEBUG(logger_, "SSL handshake failed"); SSL_clear(connection_); is_handshake_pending_ = false; return Handshake_Result_Fail; @@ -447,6 +524,25 @@ bool CryptoManagerImpl::SSLContextImpl::IsHandshakePending() const { return is_handshake_pending_; } +bool CryptoManagerImpl::SSLContextImpl::GetCertificateDueDate( + time_t& due_date) const { + LOG4CXX_AUTO_TRACE(logger_); + + X509* cert = SSL_get_certificate(connection_); + if (!cert) { + LOG4CXX_DEBUG(logger_, "Get certificate failed."); + return false; + } + + due_date = convert_asn1_time_to_time_t(X509_get_notAfter(cert)); + + return true; +} + +bool CryptoManagerImpl::SSLContextImpl::HasCertificate() const { + return SSL_get_certificate(connection_) != NULL; +} + CryptoManagerImpl::SSLContextImpl::~SSLContextImpl() { SSL_shutdown(connection_); SSL_free(connection_); diff --git a/src/components/security_manager/test/crypto_manager_impl_test.cc b/src/components/security_manager/test/crypto_manager_impl_test.cc index b30684e5f6..fb645b175d 100644 --- a/src/components/security_manager/test/crypto_manager_impl_test.cc +++ b/src/components/security_manager/test/crypto_manager_impl_test.cc @@ -210,7 +210,10 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated) { } TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) { + time_t system_time = 0; + time_t certificates_time = 1; size_t updates_before = 0; + SetInitialValues( security_manager::CLIENT, security_manager::TLSv1_2, kAllCiphers); ASSERT_TRUE(crypto_manager_->Init()); @@ -218,7 +221,8 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) { EXPECT_CALL(*mock_security_manager_settings_, update_before_hours()) .WillOnce(Return(updates_before)); - EXPECT_FALSE(crypto_manager_->IsCertificateUpdateRequired()); + EXPECT_FALSE(crypto_manager_->IsCertificateUpdateRequired(system_time, + certificates_time)); size_t max_updates_ = std::numeric_limits::max(); SetInitialValues( @@ -227,7 +231,8 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) { .WillOnce(Return(max_updates_)); ASSERT_TRUE(crypto_manager_->Init()); - EXPECT_TRUE(crypto_manager_->IsCertificateUpdateRequired()); + EXPECT_TRUE(crypto_manager_->IsCertificateUpdateRequired(system_time, + certificates_time)); } TEST_F(CryptoManagerTest, OnCertificateUpdated_NotInitialized) { diff --git a/src/components/security_manager/test/security_manager_test.cc b/src/components/security_manager/test/security_manager_test.cc index b334e78e19..4fe66498ea 100644 --- a/src/components/security_manager/test/security_manager_test.cc +++ b/src/components/security_manager/test/security_manager_test.cc @@ -44,6 +44,7 @@ #include "security_manager/mock_ssl_context.h" #include "security_manager/mock_crypto_manager.h" #include "security_manager/mock_security_manager_listener.h" +#include "utils/mock_system_time_handler.h" #include "utils/make_shared.h" #include "utils/test_async_waiter.h" @@ -95,8 +96,12 @@ const uint32_t kAsyncExpectationsTimeout = 10000u; class SecurityManagerTest : public ::testing::Test { protected: + SecurityManagerTest() + : mock_system_time_handler( + std::unique_ptr(new MockSystemTimeHandler())) + , security_manager_( + new SecurityManagerImpl(std::move(mock_system_time_handler))) {} void SetUp() OVERRIDE { - security_manager_.reset(new SecurityManagerImpl()); security_manager_->set_session_observer(&mock_session_observer); security_manager_->set_protocol_handler(&mock_protocol_handler); mock_sm_listener.reset(new testing::StrictMock< @@ -105,7 +110,7 @@ class SecurityManagerTest : public ::testing::Test { } void SetMockCryptoManager() { - EXPECT_CALL(mock_crypto_manager, IsCertificateUpdateRequired()) + EXPECT_CALL(mock_crypto_manager, IsCertificateUpdateRequired(_, _)) .WillRepeatedly(Return(false)); security_manager_->set_crypto_manager(&mock_crypto_manager); } @@ -152,8 +157,9 @@ class SecurityManagerTest : public ::testing::Test { EmulateMobileMessage(header, data, data_size); } } - ::utils::SharedPtr security_manager_; + // Strict mocks (same as all methods EXPECT_CALL().Times(0)) + testing::StrictMock mock_session_observer; testing::StrictMock @@ -166,6 +172,8 @@ class SecurityManagerTest : public ::testing::Test { mock_ssl_context_exists; std::unique_ptr > mock_sm_listener; + std::unique_ptr mock_system_time_handler; + std::shared_ptr security_manager_; }; // Test Bodies @@ -174,7 +182,6 @@ class SecurityManagerTest : public ::testing::Test { * and shall not call any methodes */ TEST_F(SecurityManagerTest, SetNULL_Intefaces) { - security_manager_.reset(new SecurityManagerImpl()); security_manager_->set_session_observer(NULL); security_manager_->set_protocol_handler(NULL); security_manager_->set_crypto_manager(NULL); @@ -398,7 +405,9 @@ TEST_F(SecurityManagerTest, CreateSSLContext_ServiceAlreadyProtected) { EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl)) .WillOnce(Return(&mock_ssl_context_new)); - const SSLContext* result = security_manager_->CreateSSLContext(key); + const SSLContext* result = security_manager_->CreateSSLContext( + key, + security_manager::SecurityManager::ContextCreationStrategy::kUseExisting); EXPECT_EQ(&mock_ssl_context_new, result); } /* @@ -424,7 +433,9 @@ TEST_F(SecurityManagerTest, CreateSSLContext_ErrorCreateSSL) { .WillOnce(ReturnNull()); EXPECT_CALL(mock_crypto_manager, CreateSSLContext()).WillOnce(ReturnNull()); - const SSLContext* result = security_manager_->CreateSSLContext(key); + const SSLContext* result = security_manager_->CreateSSLContext( + key, + security_manager::SecurityManager::ContextCreationStrategy::kUseExisting); EXPECT_EQ(NULL, result); } /* @@ -457,7 +468,9 @@ TEST_F(SecurityManagerTest, CreateSSLContext_SetSSLContextError) { EXPECT_CALL(mock_session_observer, SetSSLContext(key, &mock_ssl_context_new)) .WillOnce(Return(SecurityManager::ERROR_UNKNOWN_INTERNAL_ERROR)); - const SSLContext* result = security_manager_->CreateSSLContext(key); + const SSLContext* result = security_manager_->CreateSSLContext( + key, + security_manager::SecurityManager::ContextCreationStrategy::kUseExisting); EXPECT_EQ(NULL, result); } /* @@ -470,7 +483,6 @@ TEST_F(SecurityManagerTest, CreateSSLContext_Success) { // Emulate SessionObserver and CryptoManager result EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl)) - .WillOnce(ReturnNull()) . // additional check for debug code WillOnce(Return(&mock_ssl_context_exists)); @@ -479,7 +491,10 @@ TEST_F(SecurityManagerTest, CreateSSLContext_Success) { EXPECT_CALL(mock_session_observer, SetSSLContext(key, &mock_ssl_context_new)) .WillOnce(Return(SecurityManager::ERROR_SUCCESS)); - const SSLContext* result = security_manager_->CreateSSLContext(key); + const SSLContext* result = security_manager_->CreateSSLContext( + key, + security_manager::SecurityManager::ContextCreationStrategy:: + kForceRecreation); EXPECT_EQ(&mock_ssl_context_new, result); } /* @@ -521,109 +536,27 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInternalError) { uint32_t connection_id = 0; uint8_t session_id = 0; - // uint8_t protocol_version = 0; + EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _)); - EXPECT_CALL(mock_session_observer, GetHandshakeContext(key)) - .WillOnce(Return(SSLContext::HandshakeContext())); EXPECT_CALL(mock_session_observer, ProtocolVersionUsed(connection_id, session_id, _)) .WillOnce(Return(true)); - - // Expect InternalError with ERROR_ID - EXPECT_CALL( - mock_protocol_handler, - SendMessageToMobileApp( - InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final)); // Expect notifying listeners (unsuccess) EXPECT_CALL(*mock_sm_listener, OnHandshakeDone(key, SSLContext::Handshake_Result_Fail)) .WillOnce(Return(true)); - - // Emulate SessionObserver result EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl)) - .WillOnce(Return(&mock_ssl_context_exists)); - EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted()) - .WillOnce(Return(false)); - EXPECT_CALL(mock_ssl_context_exists, SetHandshakeContext(_)); - EXPECT_CALL(mock_ssl_context_exists, StartHandshake(_, _)) - .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer), - SetArgPointee<1>(handshake_data_out_size), - Return(SSLContext::Handshake_Result_Fail))); + .WillOnce(ReturnNull()); + // Expect InternalError with ERROR_ID + EXPECT_CALL( + mock_protocol_handler, + SendMessageToMobileApp( + InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final)); security_manager_->StartHandshake(key); - - // Listener was destroyed after OnHandshakeDone call mock_sm_listener.release(); } -/* - * Shall send data on call StartHandshake - */ -TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsNotComplete) { - SetMockCryptoManager(); - uint32_t connection_id = 0; - uint8_t session_id = 0; - // uint8_t protocol_version = 0; - EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _)); - EXPECT_CALL(mock_session_observer, GetHandshakeContext(key)) - .Times(3) - .WillRepeatedly(Return(SSLContext::HandshakeContext())); - EXPECT_CALL(mock_session_observer, - ProtocolVersionUsed(connection_id, session_id, _)) - .WillOnce(Return(true)); - // Expect send one message (with correct pointer and size data) - EXPECT_CALL(mock_protocol_handler, SendMessageToMobileApp(_, is_final)); - - // Return mock SSLContext - EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl)) - .Times(3) - .WillRepeatedly(Return(&mock_ssl_context_exists)); - // Expect initialization check on each call StartHandshake - EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted()) - .Times(3) - .WillRepeatedly(Return(false)); - EXPECT_CALL(mock_ssl_context_exists, SetHandshakeContext(_)).Times(3); - - // Emulate SSLContext::StartHandshake with different parameters - // Only on both correct - data and size shall be send message to mobile app - EXPECT_CALL(mock_ssl_context_exists, StartHandshake(_, _)) - .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer), - SetArgPointee<1>(0), - Return(SSLContext::Handshake_Result_Success))) - .WillOnce(DoAll(SetArgPointee<0>((uint8_t*)NULL), - SetArgPointee<1>(handshake_data_out_size), - Return(SSLContext::Handshake_Result_Success))) - .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer), - SetArgPointee<1>(handshake_data_out_size), - Return(SSLContext::Handshake_Result_Success))); - - security_manager_->StartHandshake(key); - security_manager_->StartHandshake(key); - security_manager_->StartHandshake(key); -} -/* - * Shall notify listeners on call StartHandshake after SSLContext initialization - * complete - */ -TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsComplete) { - SetMockCryptoManager(); - // Expect no message send - // Expect notifying listeners (success) - EXPECT_CALL(*mock_sm_listener, - OnHandshakeDone(key, SSLContext::Handshake_Result_Success)) - .WillOnce(Return(true)); - - // Emulate SessionObserver result - EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl)) - .WillOnce(Return(&mock_ssl_context_exists)); - EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted()) - .WillOnce(Return(true)); - - security_manager_->StartHandshake(key); - - // Listener was destroyed after OnHandshakeDone call - mock_sm_listener.release(); -} /* * Shall send InternallError on * getting SEND_HANDSHAKE_DATA with NULL data 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 dc335c8da2..f6521c253a 100644 --- a/src/components/security_manager/test/ssl_certificate_handshake_test.cc +++ b/src/components/security_manager/test/ssl_certificate_handshake_test.cc @@ -335,6 +335,9 @@ class SSLHandshakeTest : public testing::Test { std::string client_certificate_; std::string client_ciphers_list_; std::string client_ca_certificate_path_; + + std::vector forced_protected_services_; + std::vector forced_unprotected_services_; }; TEST_F(SSLHandshakeTest, NoVerification) { diff --git a/src/components/utils/CMakeLists.txt b/src/components/utils/CMakeLists.txt index 51835c125a..b256a2fadc 100644 --- a/src/components/utils/CMakeLists.txt +++ b/src/components/utils/CMakeLists.txt @@ -38,6 +38,7 @@ include_directories ( ${COMPONENTS_DIR}/config_profile/include ${COMPONENTS_DIR}/media_manager/include ${COMPONENTS_DIR}/protocol_handler/include + ${JSONCPP_INCLUDE_DIRECTORY} ${LOG4CXX_INCLUDE_DIRECTORY} ) diff --git a/src/components/utils/include/utils/system_time_handler.h b/src/components/utils/include/utils/system_time_handler.h new file mode 100644 index 0000000000..99bbfa39e5 --- /dev/null +++ b/src/components/utils/include/utils/system_time_handler.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018, 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_UTILS_INCLUDE_UTILS_SYSTEM_TIME_HANDLER_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SYSTEM_TIME_HANDLER_H_ + +#include + +namespace utils { + +/** + * @brief The SystemTimeListener interface. + * This interface allows to get notifications whenever + * system time appears or fails to appear. + */ +class SystemTimeListener { + public: + /** + * @brief OnSystemTimeArrived Notify about system time + * in utc format + * @param utc_time current system time. + */ + virtual void OnSystemTimeArrived(const time_t utc_time) = 0; +}; + +/** + * @brief SystemTimeHandler the interface which provides the necessary + * public API to work with system time. The class does not implement + * any logic it's public api forwards call to the private virtual + * methods which are suppose to be defined within specific implementation. + */ +class SystemTimeHandler { + public: + /** + * @brief SystemTimeHandler creates an instance + * for this class. + */ + SystemTimeHandler(); + + /** + * @brief QuerySystemTime provides the public interface + * to retrieve the system time. Interface uses private implementation + * hence the logic will be defined within descendant class. + */ + void QuerySystemTime(); + + /** + * @brief SubscribeOnSystemTime allows to subscribe listener + * to the certain event. This class does not provide such storage. + * It rather uses private pure virtual function. So the final behaviour + * should be defined within the descendant class + */ + void SubscribeOnSystemTime(SystemTimeListener* listener); + + /** + * @brief UnSubscribeFromSystemTime allows to unsubscribe listener + * from the certain event. This class does not manipulate with storage. + * It rather uses private pure virtual function. So the final behaviour + * should be defined within the descendant class + */ + void UnSubscribeFromSystemTime(SystemTimeListener* listener); + + /** + * @brief GetUTCTime allows to obtain cached result for the + * GetSystemTime request + * @return utc time. + */ + time_t GetUTCTime(); + + /** + * @brief Checks if system time is ready + * and can be requested by GetSystemTime request + * @return True if HMI is ready to provide UTC time + * otherwise False + */ + bool system_time_can_be_received() const; + + /** + * @brief ~SystemTimeHandler destroys the object + */ + virtual ~SystemTimeHandler(); + + private: + /** + * @brief DoSystemTimeQuery responsible for the system time querying. + * It is up to implementator how exactly system is going to receive this time. + */ + virtual void DoSystemTimeQuery() = 0; + + /** + * @brief DoSubscribe implements the logic which allows to handle + * subscription process. The handling logic should be defined within + * descendant class. + */ + virtual void DoSubscribe(SystemTimeListener* listener) = 0; + + /** + * @brief DoUnsubscribe implements the logic which allows to handle + * unsubscription process. The handling logic should be defined within + * descendant class. + */ + virtual void DoUnsubscribe(SystemTimeListener* listener) = 0; + + /** + * @brief FetchSystemTime allows to obtain the cached result + * for the GetSystemTime request. + * @return utc time. + */ + virtual time_t FetchSystemTime() = 0; + + /** + * @brief Checks if UTC time is ready to provided by HMI + * and can be requested by GetSystemTime request + * @return True if HMI is ready to provide UTC time + * otherwise False + */ + virtual bool utc_time_can_be_received() const = 0; +}; + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SYSTEM_TIME_HANDLER_H_ diff --git a/src/components/utils/src/system_time_handler.cc b/src/components/utils/src/system_time_handler.cc new file mode 100644 index 0000000000..ea04d1c0b9 --- /dev/null +++ b/src/components/utils/src/system_time_handler.cc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 "utils/system_time_handler.h" +//#include + +namespace utils { + +SystemTimeHandler::SystemTimeHandler() {} + +SystemTimeHandler::~SystemTimeHandler() {} + +void SystemTimeHandler::QuerySystemTime() { + DoSystemTimeQuery(); +} + +void SystemTimeHandler::SubscribeOnSystemTime(SystemTimeListener* listener) { + DoSubscribe(listener); +} + +void SystemTimeHandler::UnSubscribeFromSystemTime( + SystemTimeListener* listener) { + DoUnsubscribe(listener); +} + +time_t SystemTimeHandler::GetUTCTime() { + return FetchSystemTime(); +} + +bool SystemTimeHandler::system_time_can_be_received() const { + return utc_time_can_be_received(); +} + +} // namespace utils -- cgit v1.2.1