diff options
20 files changed, 498 insertions, 49 deletions
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 e14d6d4cad..759691ae38 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 @@ -66,6 +66,12 @@ #include "interfaces/v4_protocol_v1_2_no_extra.h" #include "interfaces/v4_protocol_v1_2_no_extra_schema.h" + +#ifdef ENABLE_SECURITY +#include "security_manager/security_manager_listener.h" +#include "security_manager/ssl_context.h" +#endif // ENABLE_SECURITY + #ifdef TIME_TESTER #include "time_metric_observer.h" #endif // TIME_TESTER @@ -179,12 +185,14 @@ typedef threads::MessageLoopThread<RawAudioDataQueue> AudioPassThruQueue; } typedef std::vector<std::string> RPCParams; - class ApplicationManagerImpl : public ApplicationManager, public hmi_message_handler::HMIMessageObserver, public protocol_handler::ProtocolObserver, public connection_handler::ConnectionHandlerObserver, public policy::PolicyHandlerObserver, +#ifdef ENABLE_SECURITY + public security_manager::SecurityManagerListener, +#endif // ENABLE_SECURITY public impl::FromMobileQueue::Handler, public impl::ToMobileQueue::Handler, public impl::FromHmiQueue::Handler, public impl::ToHmiQueue::Handler, public impl::AudioPassThruQueue::Handler, @@ -637,6 +645,15 @@ class ApplicationManagerImpl : public ApplicationManager, const protocol_handler::ServiceType& type, const connection_handler::CloseSessionReason& close_reason) OVERRIDE; +#ifdef ENABLE_SECURITY + //Overriden SecurityManagerListener method + bool OnHandshakeDone( + uint32_t connection_key, + security_manager::SSLContext::HandshakeResult result) OVERRIDE FINAL; + + security_manager::SSLContext::HandshakeContext + GetHandshakeContext(uint32_t key) const OVERRIDE FINAL; +#endif // ENABLE_SECURITY /** * @ Add notification to collection * diff --git a/src/components/application_manager/include/application_manager/usage_statistics.h b/src/components/application_manager/include/application_manager/usage_statistics.h index d6ff1f2c49..9be1bde7ca 100644 --- a/src/components/application_manager/include/application_manager/usage_statistics.h +++ b/src/components/application_manager/include/application_manager/usage_statistics.h @@ -54,6 +54,7 @@ class UsageStatistics { void RecordAppUserSelection(); void RecordRunAttemptsWhileRevoked(); void RecordRemovalsForBadBehavior(); + void RecordTLSError(); private: usage_statistics::AppStopwatch time_in_hmi_state_; @@ -64,6 +65,7 @@ class UsageStatistics { usage_statistics::AppCounter count_of_user_selections_; usage_statistics::AppCounter count_of_run_attempts_while_revoked_; usage_statistics::AppCounter count_of_removals_for_bad_behavior_; + usage_statistics::AppCounter count_of_tls_error_; }; } // namespace application_manager diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index c5e91acbce..a9e67a93ca 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -1176,8 +1176,43 @@ void ApplicationManagerImpl::OnServiceEndedCallback( if (Compare<ServiceType, EQ, ONE>(type, ServiceType::kMobileNav, ServiceType::kAudio)) { StopNaviService(session_key, type); + } +} + +#ifdef ENABLE_SECURITY +bool ApplicationManagerImpl::OnHandshakeDone( + uint32_t connection_key, + security_manager::SSLContext::HandshakeResult result) { + LOG4CXX_AUTO_TRACE(logger_); + + using security_manager::SSLContext; + using namespace helpers; + + ApplicationSharedPtr app = application(connection_key); + DCHECK_OR_RETURN(app, false); + if (Compare<SSLContext::HandshakeResult, EQ, ONE> ( + result, + SSLContext::Handshake_Result_CertExpired, + SSLContext::Handshake_Result_CertNotSigned, + SSLContext::Handshake_Result_AppIDMismatch, + SSLContext::Handshake_Result_AppNameMismatch, + SSLContext::Handshake_Result_NotYetValid)) { + app->usage_report().RecordTLSError(); } + return true; +} + +security_manager::SSLContext::HandshakeContext +ApplicationManagerImpl::GetHandshakeContext(uint32_t key) const { + LOG4CXX_AUTO_TRACE(logger_); + ApplicationConstSharedPtr app = application(key); + security_manager::SSLContext::HandshakeContext res; + res.expected_cn = app->mobile_app_id(); + res.expected_sn = app->name(); + + return res; } +#endif // ENABLE_SECURITY void ApplicationManagerImpl::set_hmi_message_handler( hmi_message_handler::HMIMessageHandler* handler) { diff --git a/src/components/application_manager/src/usage_statistics.cc b/src/components/application_manager/src/usage_statistics.cc index ad986d2223..c3758fa9e2 100644 --- a/src/components/application_manager/src/usage_statistics.cc +++ b/src/components/application_manager/src/usage_statistics.cc @@ -66,7 +66,8 @@ UsageStatistics::UsageStatistics(const std::string& app_id, count_of_run_attempts_while_revoked_(statistics_manager, app_id, RUN_ATTEMPTS_WHILE_REVOKED), count_of_removals_for_bad_behavior_(statistics_manager, app_id, - REMOVALS_MISBEHAVED) { + REMOVALS_MISBEHAVED), + count_of_tls_error_(statistics_manager, app_id, COUNT_OF_TLS_ERRORS) { time_in_hmi_state_.Start(SECONDS_HMI_NONE); } @@ -122,4 +123,8 @@ void UsageStatistics::RecordRemovalsForBadBehavior() { ++count_of_removals_for_bad_behavior_; } +void UsageStatistics::RecordTLSError() { + ++count_of_tls_error_; +} + } // namespace application_manager diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h index 63568a5927..b861e4f030 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h @@ -289,6 +289,9 @@ class ConnectionHandlerImpl : public ConnectionHandler, void SetProtectionFlag( const uint32_t &key, const protocol_handler::ServiceType &service_type) OVERRIDE; + + security_manager::SSLContext::HandshakeContext + GetHandshakeContext(uint32_t key) const OVERRIDE; #endif // ENABLE_SECURITY /** diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_observer.h b/src/components/connection_handler/include/connection_handler/connection_handler_observer.h index 556a2dc4e2..be7e600556 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_observer.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_observer.h @@ -38,6 +38,10 @@ #include "connection_handler/connection_handler.h" #include "protocol/service_type.h" +#ifdef ENABLE_SECURITY +#include "security_manager/ssl_context.h" +#endif // ENABLE_SECURITY + /** * \namespace connection_handler * \brief SmartDeviceLink connection_handler namespace. @@ -100,6 +104,10 @@ class ConnectionHandlerObserver { const protocol_handler::ServiceType& type, const connection_handler::CloseSessionReason& close_reason) = 0; +#ifdef ENABLE_SECURITY + virtual security_manager::SSLContext::HandshakeContext + GetHandshakeContext(uint32_t key) const = 0; +#endif // ENABLE_SECURITY protected: /** * \brief Destructor diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 1fbe26a8f7..7542f311d1 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -654,6 +654,11 @@ void ConnectionHandlerImpl::SetProtectionFlag( Connection &connection = *it->second; connection.SetProtectionFlag(session_id, service_type); } + +security_manager::SSLContext::HandshakeContext +ConnectionHandlerImpl::GetHandshakeContext(uint32_t key) const { + return connection_handler_observer_->GetHandshakeContext(key); +} #endif // ENABLE_SECURITY void ConnectionHandlerImpl::StartDevicesDiscovery() { diff --git a/src/components/include/protocol_handler/session_observer.h b/src/components/include/protocol_handler/session_observer.h index 355c62e646..ed341b3926 100644 --- a/src/components/include/protocol_handler/session_observer.h +++ b/src/components/include/protocol_handler/session_observer.h @@ -212,6 +212,9 @@ class SessionObserver { virtual void SetProtectionFlag( const uint32_t &key, const protocol_handler::ServiceType &service_type) = 0; + + virtual security_manager::SSLContext::HandshakeContext + GetHandshakeContext(uint32_t key) const = 0; #endif // ENABLE_SECURITY protected: diff --git a/src/components/include/security_manager/security_manager_listener.h b/src/components/include/security_manager/security_manager_listener.h index 14a5dc3281..1655d15e7e 100644 --- a/src/components/include/security_manager/security_manager_listener.h +++ b/src/components/include/security_manager/security_manager_listener.h @@ -42,7 +42,7 @@ class SecurityManagerListener { * \return \c true on success notification or \c false otherwise */ virtual bool OnHandshakeDone(uint32_t connection_key, - bool success) = 0; + SSLContext::HandshakeResult result) = 0; virtual ~SecurityManagerListener() {} }; } // namespace security_manager diff --git a/src/components/include/security_manager/ssl_context.h b/src/components/include/security_manager/ssl_context.h index e3f1dadc4f..cd82b67461 100644 --- a/src/components/include/security_manager/ssl_context.h +++ b/src/components/include/security_manager/ssl_context.h @@ -61,10 +61,21 @@ namespace security_manager { class SSLContext { public: enum HandshakeResult { - Handshake_Result_Success = 0x0, - Handshake_Result_Fail = 0x1, - Handshake_Result_AbnormalFail = 0x2 + Handshake_Result_Success, + Handshake_Result_Fail, + Handshake_Result_AbnormalFail, + Handshake_Result_CertExpired, + Handshake_Result_NotYetValid, + Handshake_Result_CertNotSigned, + Handshake_Result_AppIDMismatch, + Handshake_Result_AppNameMismatch, }; + + struct HandshakeContext { + std::string expected_sn; + std::string expected_cn; + }; + virtual HandshakeResult StartHandshake(const uint8_t** const out_data, size_t *out_data_size) = 0; virtual HandshakeResult DoHandshakeStep(const uint8_t *const in_data, @@ -79,7 +90,11 @@ class SSLContext { virtual bool IsHandshakePending() const = 0; virtual size_t get_max_block_size(size_t mtu) const = 0; virtual std::string LastError() const = 0; + + virtual void ResetConnection() = 0; + virtual void SetHandshakeContext(const HandshakeContext& hsh_ctx) = 0; virtual ~SSLContext() { } + }; } // namespace security_manager #endif // SRC_COMPONENTS_INCLUDE_SECURITY_MANAGER_SSL_CONTEXT_H_ diff --git a/src/components/policy/src/policy/policy_table/table_struct/types.cc b/src/components/policy/src/policy/policy_table/table_struct/types.cc index a26c1339ca..f6135921b4 100644 --- a/src/components/policy/src/policy/policy_table/table_struct/types.cc +++ b/src/components/policy/src/policy/policy_table/table_struct/types.cc @@ -933,18 +933,109 @@ void ModuleMeta::ReportErrors(rpc::ValidationReport* report__) const { AppLevel::AppLevel() : CompositeType(kUninitialized) { } + +AppLevel::AppLevel(uint16_t minutes_in_hmi_full, const std::string& app_registration_language_gui, const std::string& app_registration_language_vui, uint16_t minutes_in_hmi_limited, uint16_t minutes_in_hmi_background, uint16_t minutes_in_hmi_none, uint16_t count_of_user_selections, uint16_t count_of_rejections_sync_out_of_memory, uint16_t count_of_rejections_nickname_mismatch, uint16_t count_of_rejections_duplicate_name, uint16_t count_of_rejected_rpc_calls, uint16_t count_of_rpcs_sent_in_hmi_none, uint16_t count_of_removals_for_bad_behavior, uint16_t count_of_tls_error, uint16_t count_of_run_attempts_while_revoked) + : CompositeType(kUninitialized), + minutes_in_hmi_full(minutes_in_hmi_full), + app_registration_language_gui(app_registration_language_gui), + app_registration_language_vui(app_registration_language_vui), + minutes_in_hmi_limited(minutes_in_hmi_limited), + minutes_in_hmi_background(minutes_in_hmi_background), + minutes_in_hmi_none(minutes_in_hmi_none), + count_of_user_selections(count_of_user_selections), + count_of_rejections_sync_out_of_memory(count_of_rejections_sync_out_of_memory), + count_of_rejections_nickname_mismatch(count_of_rejections_nickname_mismatch), + count_of_rejections_duplicate_name(count_of_rejections_duplicate_name), + count_of_rejected_rpc_calls(count_of_rejected_rpc_calls), + count_of_rpcs_sent_in_hmi_none(count_of_rpcs_sent_in_hmi_none), + count_of_removals_for_bad_behavior(count_of_removals_for_bad_behavior), + count_of_tls_error(count_of_tls_error), + count_of_run_attempts_while_revoked(count_of_run_attempts_while_revoked) { +} AppLevel::~AppLevel() { } AppLevel::AppLevel(const Json::Value* value__) - : CompositeType(InitHelper(value__, &Json::Value::isObject)) { + : CompositeType(InitHelper(value__, &Json::Value::isObject)), + minutes_in_hmi_full(impl::ValueMember(value__, "minutes_in_hmi_full")), + app_registration_language_gui(impl::ValueMember(value__, "app_registration_language_gui")), + app_registration_language_vui(impl::ValueMember(value__, "app_registration_language_vui")), + minutes_in_hmi_limited(impl::ValueMember(value__, "minutes_in_hmi_limited")), + minutes_in_hmi_background(impl::ValueMember(value__, "minutes_in_hmi_background")), + minutes_in_hmi_none(impl::ValueMember(value__, "minutes_in_hmi_none")), + count_of_user_selections(impl::ValueMember(value__, "count_of_user_selections")), + count_of_rejections_sync_out_of_memory(impl::ValueMember(value__, "count_of_rejections_sync_out_of_memory")), + count_of_rejections_nickname_mismatch(impl::ValueMember(value__, "count_of_rejections_nickname_mismatch")), + count_of_rejections_duplicate_name(impl::ValueMember(value__, "count_of_rejections_duplicate_name")), + count_of_rejected_rpc_calls(impl::ValueMember(value__, "count_of_rejected_rpc_calls")), + count_of_rpcs_sent_in_hmi_none(impl::ValueMember(value__, "count_of_rpcs_sent_in_hmi_none")), + count_of_removals_for_bad_behavior(impl::ValueMember(value__, "count_of_removals_for_bad_behavior")), + count_of_tls_error(impl::ValueMember(value__, "count_of_tls_error")), + count_of_run_attempts_while_revoked(impl::ValueMember(value__, "count_of_run_attempts_while_revoked")) { } Json::Value AppLevel::ToJsonValue() const { Json::Value result__(Json::objectValue); + impl::WriteJsonField("minutes_in_hmi_full", minutes_in_hmi_full, &result__); + impl::WriteJsonField("app_registration_language_gui", app_registration_language_gui, &result__); + impl::WriteJsonField("app_registration_language_vui", app_registration_language_vui, &result__); + impl::WriteJsonField("minutes_in_hmi_limited", minutes_in_hmi_limited, &result__); + impl::WriteJsonField("minutes_in_hmi_background", minutes_in_hmi_background, &result__); + impl::WriteJsonField("minutes_in_hmi_none", minutes_in_hmi_none, &result__); + impl::WriteJsonField("count_of_user_selections", count_of_user_selections, &result__); + impl::WriteJsonField("count_of_rejections_sync_out_of_memory", count_of_rejections_sync_out_of_memory, &result__); + impl::WriteJsonField("count_of_rejections_nickname_mismatch", count_of_rejections_nickname_mismatch, &result__); + impl::WriteJsonField("count_of_rejections_duplicate_name", count_of_rejections_duplicate_name, &result__); + impl::WriteJsonField("count_of_rejected_rpc_calls", count_of_rejected_rpc_calls, &result__); + impl::WriteJsonField("count_of_rpcs_sent_in_hmi_none", count_of_rpcs_sent_in_hmi_none, &result__); + impl::WriteJsonField("count_of_removals_for_bad_behavior", count_of_removals_for_bad_behavior, &result__); + impl::WriteJsonField("count_of_tls_error", count_of_tls_error, &result__); + impl::WriteJsonField("count_of_run_attempts_while_revoked", count_of_run_attempts_while_revoked, &result__); return result__; } bool AppLevel::is_valid() const { - if (struct_empty()) { - return initialization_state__ == kInitialized && Validate(); + if (!minutes_in_hmi_full.is_valid()) { + return false; + } + if (!app_registration_language_gui.is_valid()) { + return false; + } + if (!app_registration_language_vui.is_valid()) { + return false; + } + if (!minutes_in_hmi_limited.is_valid()) { + return false; + } + if (!minutes_in_hmi_background.is_valid()) { + return false; + } + if (!minutes_in_hmi_none.is_valid()) { + return false; + } + if (!count_of_user_selections.is_valid()) { + return false; + } + if (!count_of_rejections_sync_out_of_memory.is_valid()) { + return false; + } + if (!count_of_rejections_nickname_mismatch.is_valid()) { + return false; + } + if (!count_of_rejections_duplicate_name.is_valid()) { + return false; + } + if (!count_of_rejected_rpc_calls.is_valid()) { + return false; + } + if (!count_of_rpcs_sent_in_hmi_none.is_valid()) { + return false; + } + if (!count_of_removals_for_bad_behavior.is_valid()) { + return false; + } + if (!count_of_tls_error.is_valid()) { + return false; + } + if (!count_of_run_attempts_while_revoked.is_valid()) { + return false; } return Validate(); } @@ -952,6 +1043,58 @@ bool AppLevel::is_initialized() const { return (initialization_state__ != kUninitialized) || (!struct_empty()); } bool AppLevel::struct_empty() const { + + if (minutes_in_hmi_full.is_initialized()) { + return false; + } + if (app_registration_language_gui.is_initialized()) { + return false; + } + + if (app_registration_language_vui.is_initialized()) { + return false; + } + + if (minutes_in_hmi_limited.is_initialized()) { + return false; + } + if (minutes_in_hmi_background.is_initialized()) { + return false; + } + + if (minutes_in_hmi_none.is_initialized()) { + return false; + } + if (count_of_user_selections.is_initialized()) { + return false; + } + + if (count_of_rejections_sync_out_of_memory.is_initialized()) { + return false; + } + if (count_of_rejections_nickname_mismatch.is_initialized()) { + return false; + } + + if (count_of_rejections_duplicate_name.is_initialized()) { + return false; + } + if (count_of_rejected_rpc_calls.is_initialized()) { + return false; + } + + if (count_of_rpcs_sent_in_hmi_none.is_initialized()) { + return false; + } + if (count_of_removals_for_bad_behavior.is_initialized()) { + return false; + } + if (count_of_tls_error.is_initialized()) { + return false; + } + if (count_of_run_attempts_while_revoked.is_initialized()) { + return false; + } return true; } void AppLevel::ReportErrors(rpc::ValidationReport* report__) const { diff --git a/src/components/policy/src/policy/policy_table/table_struct/types.h b/src/components/policy/src/policy/policy_table/table_struct/types.h index 4896f64a2e..d23d79e2df 100644 --- a/src/components/policy/src/policy/policy_table/table_struct/types.h +++ b/src/components/policy/src/policy/policy_table/table_struct/types.h @@ -275,8 +275,26 @@ struct ModuleMeta : CompositeType { struct AppLevel : CompositeType { public: + + Integer<uint16_t, 0, 65535> minutes_in_hmi_full; + String<1, 10> app_registration_language_gui; + String<0, 10> app_registration_language_vui; + Integer<uint16_t, 0, 65535> minutes_in_hmi_limited; + Integer<uint16_t, 0, 65535> minutes_in_hmi_background; + Integer<uint16_t, 0, 65535> minutes_in_hmi_none; + Integer<uint16_t, 0, 65535> count_of_user_selections; + Integer<uint16_t, 0, 65535> count_of_rejections_sync_out_of_memory; + Integer<uint16_t, 0, 65535> count_of_rejections_nickname_mismatch; + Integer<uint16_t, 0, 65535> count_of_rejections_duplicate_name; + Integer<uint16_t, 0, 65535> count_of_rejected_rpc_calls; + Integer<uint16_t, 0, 65535> count_of_rpcs_sent_in_hmi_none; + Integer<uint16_t, 0, 65535> count_of_removals_for_bad_behavior; + Integer<uint16_t, 0, 65535> count_of_tls_error; + Integer<uint16_t, 0, 65535> count_of_run_attempts_while_revoked; public: AppLevel(); + AppLevel(uint16_t minutes_in_hmi_full, const std::string& app_registration_language_gui, const std::string& app_registration_language_vui, uint16_t minutes_in_hmi_limited, uint16_t minutes_in_hmi_background, uint16_t minutes_in_hmi_none, uint16_t count_of_user_selections, uint16_t count_of_rejections_sync_out_of_memory, uint16_t count_of_rejections_nickname_mismatch, uint16_t count_of_rejections_duplicate_name, uint16_t count_of_rejected_rpc_calls, uint16_t count_of_rpcs_sent_in_hmi_none, uint16_t count_of_removals_for_bad_behavior, +uint16_t count_of_tls_error, uint16_t count_of_run_attempts_while_revoked); ~AppLevel(); explicit AppLevel(const Json::Value* value__); Json::Value ToJsonValue() const; diff --git a/src/components/policy/src/policy/src/cache_manager.cc b/src/components/policy/src/policy/src/cache_manager.cc index 4c8784c703..ac5729b424 100644 --- a/src/components/policy/src/policy/src/cache_manager.cc +++ b/src/components/policy/src/policy/src/cache_manager.cc @@ -898,6 +898,48 @@ void CacheManager::Increment(usage_statistics::GlobalCounterId type) { void CacheManager::Increment(const std::string &app_id, usage_statistics::AppCounterId type) { CACHE_MANAGER_CHECK_VOID(); + + switch (type) { + case usage_statistics::USER_SELECTIONS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_user_selections; + break; + case usage_statistics::REJECTIONS_SYNC_OUT_OF_MEMORY: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_rejections_sync_out_of_memory; + break; + case usage_statistics::REJECTIONS_NICKNAME_MISMATCH: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_rejections_nickname_mismatch; + break; + case usage_statistics::REJECTIONS_DUPLICATE_NAME: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_rejections_duplicate_name; + break; + case usage_statistics::REJECTED_RPC_CALLS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_rejected_rpc_calls; + break; + case usage_statistics::RPCS_IN_HMI_NONE: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_rpcs_sent_in_hmi_none; + break; + case usage_statistics::REMOVALS_MISBEHAVED: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_removals_for_bad_behavior; + break; + case usage_statistics::RUN_ATTEMPTS_WHILE_REVOKED: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_run_attempts_while_revoked; + break; + case usage_statistics::COUNT_OF_TLS_ERRORS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id]. + count_of_tls_error; + break; + default: + LOG4CXX_WARN(logger_, "Type app counter is unknown"); + return; + } Backup(); } diff --git a/src/components/policy/src/policy/src/sql_pt_queries.cc b/src/components/policy/src/policy/src/sql_pt_queries.cc index 44c54040fe..2e2fb92649 100644 --- a/src/components/policy/src/policy/src/sql_pt_queries.cc +++ b/src/components/policy/src/policy/src/sql_pt_queries.cc @@ -218,6 +218,7 @@ const std::string kCreateSchema = " `count_of_rpcs_sent_in_hmi_none` INTEGER DEFAULT 0, " " `count_of_removals_for_bad_behavior` INTEGER DEFAULT 0, " " `count_of_run_attempts_while_revoked` INTEGER DEFAULT 0, " + " `count_of_tls_errors` INTEGER DEFAULT 0, " " `app_registration_language_gui` VARCHAR(25), " " `app_registration_language_vui` VARCHAR(25), " " CONSTRAINT `fk_app_levels_application1` " diff --git a/src/components/policy/src/policy/usage_statistics/include/usage_statistics/statistics_manager.h b/src/components/policy/src/policy/usage_statistics/include/usage_statistics/statistics_manager.h index 3af8f4c195..4226cb7dca 100644 --- a/src/components/policy/src/policy/usage_statistics/include/usage_statistics/statistics_manager.h +++ b/src/components/policy/src/policy/usage_statistics/include/usage_statistics/statistics_manager.h @@ -64,7 +64,8 @@ enum AppCounterId { REJECTED_RPC_CALLS, RPCS_IN_HMI_NONE, REMOVALS_MISBEHAVED, - RUN_ATTEMPTS_WHILE_REVOKED + RUN_ATTEMPTS_WHILE_REVOKED, + COUNT_OF_TLS_ERRORS, }; class StatisticsManager { diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index a14097b61c..10b42b049f 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -959,7 +959,9 @@ class StartSessionHandler : public security_manager::SecurityManagerListener { hash_id_(hash_id), service_type_(service_type) { } - bool OnHandshakeDone(const uint32_t connection_key, const bool success) OVERRIDE { + bool OnHandshakeDone( + const uint32_t connection_key, + security_manager::SSLContext::HandshakeResult result) OVERRIDE { if (connection_key != connection_key_) { return false; } @@ -967,8 +969,7 @@ class StartSessionHandler : public security_manager::SecurityManagerListener { const bool was_service_protection_enabled = session_observer_->GetSSLContext(connection_key_, service_type_) != NULL; if (was_service_protection_enabled) { - // On Success handshake - if (success) { + if (result != security_manager::SSLContext::Handshake_Result_Success) { // const std::string error_text("Connection is already protected"); // LOG4CXX_WARN(logger_, error_text << ", key " << connection_key); // security_manager_->SendInternalError( @@ -980,11 +981,14 @@ class StartSessionHandler : public security_manager::SecurityManagerListener { NOTREACHED(); } } else { - if (success) { + if (result == security_manager::SSLContext::Handshake_Result_Success) { session_observer_->SetProtectionFlag(connection_key_, service_type_); } - protocol_handler_->SendStartSessionAck(connection_id_, session_id_, - protocol_version_, hash_id_, service_type_, success); + protocol_handler_->SendStartSessionAck( + connection_id_, session_id_, + protocol_version_, hash_id_, + service_type_, + security_manager::SSLContext::Handshake_Result_Success == result); } delete this; return true; 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 6641050d40..881aefbe81 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 @@ -56,20 +56,26 @@ class CryptoManagerImpl : public CryptoManager { virtual HandshakeResult DoHandshakeStep(const uint8_t *const in_data, size_t in_data_size, const uint8_t** const out_data, - size_t *out_data_size); - virtual bool Encrypt(const uint8_t *const in_data, size_t in_data_size, - const uint8_t ** const out_data, size_t *out_data_size); - virtual bool Decrypt(const uint8_t *const in_data, size_t in_data_size, - const uint8_t ** const out_data, size_t *out_data_size); - virtual bool IsInitCompleted() const; - virtual bool IsHandshakePending() const; - virtual size_t get_max_block_size(size_t mtu) const; - virtual std::string LastError() const; - virtual ~SSLContextImpl(); - + size_t *out_data_size) OVERRIDE; + bool Encrypt(const uint8_t *const in_data, size_t in_data_size, + const uint8_t ** const out_data, size_t *out_data_size) OVERRIDE; + bool Decrypt(const uint8_t *const in_data, size_t in_data_size, + const uint8_t ** const out_data, size_t *out_data_size) OVERRIDE; + bool IsInitCompleted() const OVERRIDE; + bool IsHandshakePending() const OVERRIDE; + size_t get_max_block_size(size_t mtu) const OVERRIDE; + std::string LastError() const OVERRIDE; + void ResetConnection() OVERRIDE; + void SetHandshakeContext(const HandshakeContext& hsh_ctx) OVERRIDE; + ~SSLContextImpl(); private: typedef size_t(*BlockSizeGetter)(size_t); void EnsureBufferSizeEnough(size_t size); + void SetHandshakeError(const int error); + HandshakeResult openssl_error_convert_to_internal(const long error); + + std::string GetTextBy(X509_NAME* name, int object) const; + SSL *connection_; BIO *bioIn_; BIO *bioOut_; @@ -79,9 +85,11 @@ class CryptoManagerImpl : public CryptoManager { uint8_t *buffer_; bool is_handshake_pending_; Mode mode_; + mutable std::string last_error_; BlockSizeGetter max_block_size_; static std::map<std::string, BlockSizeGetter> max_block_sizes; static std::map<std::string, BlockSizeGetter> create_max_block_sizes(); + HandshakeContext hsh_context_; DISALLOW_COPY_AND_ASSIGN(SSLContextImpl); }; 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 2aa03087eb..37efcf5a5f 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 @@ -148,7 +148,7 @@ class SecurityManagerImpl * \param success result of connection protection */ void NotifyListenersOnHandshakeDone(const uint32_t &connection_key, - const bool success); + SSLContext::HandshakeResult error); /** * @brief SecurityConfigSection * @return Session name in config file diff --git a/src/components/security_manager/src/security_manager_impl.cc b/src/components/security_manager/src/security_manager_impl.cc index d985870046..16b63d304c 100644 --- a/src/components/security_manager/src/security_manager_impl.cc +++ b/src/components/security_manager/src/security_manager_impl.cc @@ -182,23 +182,31 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) { "connection is not protected"); LOG4CXX_ERROR(logger_, error_text); SendInternalError(connection_key, ERROR_INTERNAL, error_text); - NotifyListenersOnHandshakeDone(connection_key, false); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); return; } if (ssl_context->IsInitCompleted()) { - NotifyListenersOnHandshakeDone(connection_key, true); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Success); return; } + + ssl_context->SetHandshakeContext( + session_observer_->GetHandshakeContext(connection_key)); + size_t data_size = 0; const uint8_t *data = NULL; + const security_manager::SSLContext::HandshakeResult result = ssl_context->StartHandshake(&data, &data_size); if (security_manager::SSLContext::Handshake_Result_Success != result) { const std::string error_text("StartHandshake failed, handshake step fail"); LOG4CXX_ERROR(logger_, error_text); SendInternalError(connection_key, ERROR_INTERNAL, error_text); - NotifyListenersOnHandshakeDone(connection_key, false); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); return; } // for client mode will be generated output data @@ -220,12 +228,13 @@ void SecurityManagerImpl::RemoveListener(SecurityManagerListener *const listener } listeners_.remove(listener); } -void SecurityManagerImpl::NotifyListenersOnHandshakeDone(const uint32_t &connection_key, - const bool success) { +void SecurityManagerImpl::NotifyListenersOnHandshakeDone( + const uint32_t &connection_key, + SSLContext::HandshakeResult error) { LOG4CXX_AUTO_TRACE(logger_); std::list<SecurityManagerListener*>::iterator it = listeners_.begin(); while (it != listeners_.end()) { - if ((*it)->OnHandshakeDone(connection_key, success)) { + if ((*it)->OnHandshakeDone(connection_key, error)) { // On get notification remove listener it = listeners_.erase(it); } else { @@ -260,7 +269,8 @@ bool SecurityManagerImpl::ProccessHandshakeData(const SecurityMessage &inMessage LOG4CXX_ERROR(logger_, error_text); SendInternalError(connection_key, ERROR_SERVICE_NOT_PROTECTED, error_text, seqNumber); - NotifyListenersOnHandshakeDone(connection_key, false); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); return false; } size_t out_data_size; @@ -274,18 +284,21 @@ bool SecurityManagerImpl::ProccessHandshakeData(const SecurityMessage &inMessage LOG4CXX_ERROR(logger_, "SendHandshakeData: Handshake failed: " << erorr_text); SendInternalError(connection_key, ERROR_SSL_INVALID_DATA, erorr_text, seqNumber); - NotifyListenersOnHandshakeDone(connection_key, false); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); // no handshake data to send return false; } if (sslContext->IsInitCompleted()) { // On handshake success LOG4CXX_DEBUG(logger_, "SSL initialization finished success."); - NotifyListenersOnHandshakeDone(connection_key, true); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Success); } else if (handshake_result == SSLContext::Handshake_Result_Fail) { // On handshake fail LOG4CXX_WARN(logger_, "SSL initialization finished with fail."); - NotifyListenersOnHandshakeDone(connection_key, false); + NotifyListenersOnHandshakeDone(connection_key, + SSLContext::Handshake_Result_Fail); } if (out_data && out_data_size) { diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc index 09c2efd196..3361711b13 100644 --- a/src/components/security_manager/src/ssl_context_impl.cc +++ b/src/components/security_manager/src/ssl_context_impl.cc @@ -37,11 +37,14 @@ #include <openssl/err.h> #include <memory.h> #include <map> +#include <algorithm> #include "utils/macro.h" namespace security_manager { +CREATE_LOGGERPTR_GLOBAL(logger_, "CryptoManagerImpl") + CryptoManagerImpl::SSLContextImpl::SSLContextImpl(SSL *conn, Mode mode) : connection_(conn), bioIn_(BIO_new(BIO_s_mem())), @@ -138,19 +141,57 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, DCHECK(out_data_size); *out_data = NULL; *out_data_size = 0; + // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake sync_primitives::AutoLock locker(bio_locker); if (SSL_is_init_finished(connection_)) { is_handshake_pending_ = false; - return SSLContext::Handshake_Result_Success; + return Handshake_Result_Success; } if (in_data && in_data_size) { const int ret = BIO_write(bioIn_, in_data, in_data_size); if (ret <= 0) { is_handshake_pending_ = false; - SSL_clear(connection_); - return SSLContext::Handshake_Result_AbnormalFail; + ResetConnection(); + return Handshake_Result_AbnormalFail; + } + } + + bool cn_found; + bool sn_found; + STACK_OF(X509 ) *peer_certs = SSL_get_peer_cert_chain(connection_); + while (sk_X509_num(peer_certs) > 0) { + X509* cert = sk_X509_pop(peer_certs); + const bool last_step = (sk_X509_num(peer_certs) == 0); + X509_NAME* subj_name = X509_get_subject_name(cert); + char *subj = X509_NAME_oneline(subj_name, NULL, 0); + if (subj) { + std::replace(subj, subj + strlen(subj), '/', ' '); + LOG4CXX_DEBUG(logger_, "Mobile cert subject:" << subj); + OPENSSL_free(subj); + } + char *issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + if (issuer) { + std::replace(issuer, issuer + strlen(issuer), '/', ' '); + LOG4CXX_DEBUG(logger_, "Mobile cert issuer:" << issuer); + OPENSSL_free(issuer); + } + + const std::string& cn = GetTextBy(subj_name, NID_commonName); + const std::string& sn = GetTextBy(subj_name, NID_serialNumber); + + cn_found = cn_found || (hsh_context_.expected_cn == cn); + sn_found = sn_found || (hsh_context_.expected_sn == sn); + + if (!cn_found && last_step) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app name"); + return Handshake_Result_AppNameMismatch; + } + + if (!sn_found && last_step) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app id"); + return Handshake_Result_AppIDMismatch; } } @@ -166,11 +207,23 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, } else if (handshake_result == 0) { SSL_clear(connection_); is_handshake_pending_ = false; - return SSLContext::Handshake_Result_Fail; - } else if (SSL_get_error(connection_, handshake_result) != SSL_ERROR_WANT_READ) { - SSL_clear(connection_); - is_handshake_pending_ = false; - return SSLContext::Handshake_Result_AbnormalFail; + return Handshake_Result_Fail; + } else { + const int error = SSL_get_error(connection_, handshake_result); + if (error != SSL_ERROR_WANT_READ) { + const long error = SSL_get_verify_result(connection_); + SetHandshakeError(error); + LOG4CXX_WARN(logger_, "Handshake failed with error " << " -> " << SSL_get_error(connection_, error) + << " \"" << LastError() << '"'); + ResetConnection(); + is_handshake_pending_ = false; + // In case error happened but ssl verification shows OK + // method will return AbnormalFail. + if (X509_V_OK == error) { + return Handshake_Result_AbnormalFail; + } + return openssl_error_convert_to_internal(error); + } } const size_t pend = BIO_ctrl_pending(bioOut_); @@ -184,12 +237,12 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, *out_data = buffer_; } else { is_handshake_pending_ = false; - SSL_clear(connection_); - return SSLContext::Handshake_Result_AbnormalFail; + ResetConnection(); + return Handshake_Result_AbnormalFail; } } - return SSLContext::Handshake_Result_Success; + return Handshake_Result_Success; } bool CryptoManagerImpl::SSLContextImpl::Encrypt( @@ -274,6 +327,48 @@ CryptoManagerImpl::SSLContextImpl::~SSLContextImpl() { delete[] buffer_; } +void CryptoManagerImpl::SSLContextImpl::SetHandshakeError(const int error) { + const char* error_str = X509_verify_cert_error_string(error); + if (error_str) { + last_error_ = error_str; + } else { + // Error will be updated with the next LastError call + last_error_.clear(); + } +} + +void CryptoManagerImpl::SSLContextImpl::ResetConnection() { + LOG4CXX_AUTO_TRACE(logger_); + const int shutdown_result = SSL_shutdown(connection_); + if (shutdown_result != 1) { + const size_t pend = BIO_ctrl_pending(bioOut_); + LOG4CXX_DEBUG(logger_, "Available " << pend << " bytes for shutdown"); + if (pend > 0) { + LOG4CXX_DEBUG(logger_, "Reading shutdown data"); + EnsureBufferSizeEnough(pend); + BIO_read(bioOut_, buffer_, pend); + } + SSL_shutdown(connection_); + } + LOG4CXX_DEBUG(logger_, "SSL connection recreation"); + SSL_CTX * ssl_context = connection_->ctx; + SSL_free(connection_); + connection_ = SSL_new(ssl_context); + if (mode_ == SERVER) { + SSL_set_accept_state(connection_); + } else { + SSL_set_connect_state(connection_); + } + bioIn_ = BIO_new(BIO_s_mem()); + bioOut_ = BIO_new(BIO_s_mem()); + SSL_set_bio(connection_, bioIn_, bioOut_); +} + +void CryptoManagerImpl::SSLContextImpl::SetHandshakeContext( + const SSLContext::HandshakeContext& hsh_ctx) { + hsh_context_ = hsh_ctx; +} + void CryptoManagerImpl::SSLContextImpl::EnsureBufferSizeEnough(size_t size) { if (buffer_size_ < size) { delete[] buffer_; @@ -281,7 +376,38 @@ void CryptoManagerImpl::SSLContextImpl::EnsureBufferSizeEnough(size_t size) { if (buffer_) { buffer_size_ = size; } + } +} + +SSLContext::HandshakeResult +CryptoManagerImpl::SSLContextImpl::openssl_error_convert_to_internal( + const long error) { + switch(error) { + case X509_V_ERR_CERT_HAS_EXPIRED: return Handshake_Result_CertExpired; + case X509_V_ERR_CERT_NOT_YET_VALID: return Handshake_Result_NotYetValid; + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + return Handshake_Result_CertNotSigned; + default: return Handshake_Result_Fail; } } +std::string CryptoManagerImpl::SSLContextImpl::GetTextBy( + X509_NAME* name, int object) const { + const int req_len = X509_NAME_get_text_by_NID(name, object, NULL, 0); + + if (-1 == req_len) { + return std::string(); + } + + std::vector<char> data; + data.resize(req_len + 1); + X509_NAME_get_text_by_NID(name, object, &data.front(), data.size()); + + return std::string(data.begin(), data.end() - 1); +} + + } // namespace security_manager |