diff options
Diffstat (limited to 'src')
11 files changed, 225 insertions, 81 deletions
diff --git a/src/appMain/life_cycle.cc b/src/appMain/life_cycle.cc index f342da63f4..94776a447c 100644 --- a/src/appMain/life_cycle.cc +++ b/src/appMain/life_cycle.cc @@ -169,7 +169,9 @@ bool LifeCycle::StartComponents() { policy::PolicyHandler::instance()->RetrieveCertificate(), profile::Profile::instance()->ciphers_list(), profile::Profile::instance()->verify_peer(), - profile::Profile::instance()->ca_cert_path())) { + profile::Profile::instance()->ca_cert_path(), + profile::Profile::instance()->update_before_hours()) + ) { LOG4CXX_ERROR(logger_, "CryptoManager initialization fail."); return false; } @@ -195,13 +197,6 @@ bool LifeCycle::StartComponents() { connection_handler_->set_protocol_handler(protocol_handler_); connection_handler_->set_connection_handler_observer(app_manager_); -#ifdef ENABLE_SECURITY - security_manager_->set_session_observer(connection_handler_); - security_manager_->set_protocol_handler(protocol_handler_); - security_manager_->AddListener(app_manager_); - security_manager_->set_crypto_manager(crypto_manager_); -#endif // ENABLE_SECURITY - // it is important to initialise TimeTester before TM to listen TM Adapters #ifdef TIME_TESTER time_tester_ = new time_tester::TimeManager(); @@ -213,6 +208,14 @@ bool LifeCycle::StartComponents() { app_manager_->set_connection_handler(connection_handler_); app_manager_->set_hmi_message_handler(hmi_handler_); +#ifdef ENABLE_SECURITY + security_manager_->set_session_observer(connection_handler_); + security_manager_->set_protocol_handler(protocol_handler_); + security_manager_->AddListener(app_manager_); + security_manager_->set_crypto_manager(crypto_manager_); + app_manager_->AddPolicyObserver(crypto_manager_); +#endif // ENABLE_SECURITY + transport_manager_->Init(); // start transport manager transport_manager_->Visibility(true); diff --git a/src/components/application_manager/include/application_manager/policies/policy_handler_observer.h b/src/components/application_manager/include/application_manager/policies/policy_handler_observer.h index c9b32b7e17..485fbea45c 100644 --- a/src/components/application_manager/include/application_manager/policies/policy_handler_observer.h +++ b/src/components/application_manager/include/application_manager/policies/policy_handler_observer.h @@ -33,12 +33,16 @@ #ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POLICY_HANDLER_OBSERVER_H_ #define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POLICY_HANDLER_OBSERVER_H_ +#include <vector> +#include <string> +#include <map> + namespace policy { class PolicyHandlerObserver{ public: - virtual void OnUpdateHMIAppType(std::map<std::string, std::vector<std::string> > app_hmi_types) = 0; - virtual void OnCertificateUpdated(const std::string& certificate_data) {} + virtual void OnUpdateHMIAppType(std::map<std::string, std::vector<std::string> > app_hmi_types) {} + virtual bool OnCertificateUpdated(const std::string& certificate_data) { return false;} virtual ~PolicyHandlerObserver() {} }; } // namespace policy diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 4fed37a455..240b011a7d 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -1212,10 +1212,8 @@ 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; + DCHECK_OR_RETURN(app.valid(), res); + return res.make_context(app->mobile_app_id(), app->name()); } #endif // ENABLE_SECURITY diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc index 0282c087da..03835343dc 100644 --- a/src/components/application_manager/src/policies/policy_handler.cc +++ b/src/components/application_manager/src/policies/policy_handler.cc @@ -410,7 +410,7 @@ void PolicyHandler::OnDeviceConsentChanged(const std::string& device_id, void PolicyHandler::OnPTExchangeNeeded() { POLICY_LIB_CHECK_VOID(); - policy_manager_->ForcePTExchange(); + MessageHelper::SendOnStatusUpdate(policy_manager_->ForcePTExchange()); } void PolicyHandler::GetAvailableApps(std::queue<std::string>& apps) { diff --git a/src/components/include/security_manager/crypto_manager.h b/src/components/include/security_manager/crypto_manager.h index e4867663a4..121d6c9081 100644 --- a/src/components/include/security_manager/crypto_manager.h +++ b/src/components/include/security_manager/crypto_manager.h @@ -34,6 +34,7 @@ #define SRC_COMPONENTS_SECURITY_MANAGER_INCLUDE_SECURITY_MANAGER_CRYPTO_MANAGER_H_ #include <string> +#include "application_manager/policies/policy_handler_observer.h" /** * \class security_manager::CryptoManager @@ -52,14 +53,35 @@ class SSLContext; enum Mode { CLIENT, SERVER }; enum Protocol { SSLv3, TLSv1, TLSv1_1, TLSv1_2}; -class CryptoManager { +class CryptoManager: public policy::PolicyHandlerObserver{ public: + /** + * @brief Init allows to initialize cryptomanager with certain values. + * + * @param mode defines the cryptomanager mode: server or client. + * + * @param protocol set the appropriate number of ssl protocol to use. + * + * @param cert_data the stringified certificate data (certificate in PKCS12 format). + * + * @param ciphers_list the cipher list which will be used during secure connectin. + * + * @param verify_peer allows to distinguish if we need to verify the peers certificates + * + * @param ca_certificate_file location of CA file. + * + * @param hours_before_update when the certificate expiration date less then + * this value, the certificate update will be generated + * + * @return true in case initialization was succesfull, false otherwise. + */ virtual bool Init(Mode mode, Protocol protocol, - const std::string &cert_filename, + const std::string &cert_data, const std::string &ciphers_list, - bool verify_peer, - const std::string& ca_cert_file) = 0; + const bool verify_peer, + const std::string &ca_certificate_file, + const size_t hours_before_update) = 0; virtual SSLContext *CreateSSLContext() = 0; virtual bool OnCertificateUpdated(const std::string& data) = 0; virtual void ReleaseSSLContext(SSLContext *context) = 0; diff --git a/src/components/include/security_manager/ssl_context.h b/src/components/include/security_manager/ssl_context.h index 6e7c10939a..e361e98c3e 100644 --- a/src/components/include/security_manager/ssl_context.h +++ b/src/components/include/security_manager/ssl_context.h @@ -35,6 +35,8 @@ #include <cstddef> // for size_t typedef #include <string> +#include <ctype.h> +#include <algorithm> // TODO(EZamakhov): update brief info /** @@ -79,6 +81,12 @@ class SSLContext { const std::string& cn) { expected_sn = sn; expected_cn = cn; + + std::transform(expected_sn.begin(), expected_sn.end(), + expected_sn.begin(), ::tolower); + + std::transform(expected_cn.begin(), expected_cn.end(), + expected_cn.begin(), ::tolower); return *this; } }; diff --git a/src/components/policy/src/policy/src/sql_pt_ext_representation.cc b/src/components/policy/src/policy/src/sql_pt_ext_representation.cc index 976271b5d1..6feea4c678 100644 --- a/src/components/policy/src/policy/src/sql_pt_ext_representation.cc +++ b/src/components/policy/src/policy/src/sql_pt_ext_representation.cc @@ -905,7 +905,7 @@ bool SQLPTExtRepresentation::GatherAppLevels( level.count_of_run_attempts_while_revoked = query.GetInteger(12); level.app_registration_language_gui = query.GetString(13); level.app_registration_language_vui = query.GetString(14); - level.count_of_tls_errors = query.GetString(15); + level.count_of_tls_errors = query.GetInteger(15); (*apps)[query.GetString(0)] = level; } diff --git a/src/components/security_manager/CMakeLists.txt b/src/components/security_manager/CMakeLists.txt index 6433ff6dd8..3cc6178931 100644 --- a/src/components/security_manager/CMakeLists.txt +++ b/src/components/security_manager/CMakeLists.txt @@ -35,6 +35,7 @@ include_directories( ${COMPONENTS_DIR}/connection_handler/include ${COMPONENTS_DIR}/config_profile/include/ ${COMPONENTS_DIR}/utils/include/ + ${COMPONENTS_DIR}/application_manager/include/ ${JSONCPP_INCLUDE_DIRECTORY} ${CMAKE_SOURCE_DIR}/src/thirdPartyLibs/jsoncpp/include ${APR_INCLUDE_DIRECTORY} 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 5d7b579a86..5269259620 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 @@ -68,7 +68,15 @@ class CryptoManagerImpl : public CryptoManager { void ResetConnection() OVERRIDE; void SetHandshakeContext(const HandshakeContext& hsh_ctx) OVERRIDE; ~SSLContextImpl(); - private: + + void PrintCertData(X509* cert, const std::string& cert_owner); + private: + void PrintCertInfo(); + HandshakeResult CheckCertContext(); + bool ReadHandshakeData(const uint8_t** const out_data, + size_t* out_data_size); + bool WriteHandshakeData(const uint8_t* const in_data, size_t in_data_size); + HandshakeResult PerformHandshake(); typedef size_t(*BlockSizeGetter)(size_t); void EnsureBufferSizeEnough(size_t size); void SetHandshakeError(const int error); @@ -102,7 +110,8 @@ class CryptoManagerImpl : public CryptoManager { const std::string &cert_data, const std::string &ciphers_list, const bool verify_peer, - const std::string &ca_certificate_file) OVERRIDE; + const std::string &ca_certificate_file, + const size_t hours_before_update) OVERRIDE; bool OnCertificateUpdated(const std::string &data) OVERRIDE; SSLContext *CreateSSLContext() OVERRIDE; void ReleaseSSLContext(SSLContext *context) OVERRIDE; @@ -122,6 +131,7 @@ private: static sync_primitives::Lock instance_lock_; std::string certificate_data_; bool verify_peer_; + size_t hours_before_update_; DISALLOW_COPY_AND_ASSIGN(CryptoManagerImpl); }; } // 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 944ff52600..b09176df89 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -116,11 +116,13 @@ bool CryptoManagerImpl::Init(Mode mode, Protocol protocol, const std::string &cert_data, const std::string &ciphers_list, const bool verify_peer, - const std::string &ca_certificate_file) { + const std::string &ca_certificate_file, + const size_t hours_before_update) { LOG4CXX_AUTO_TRACE(logger_); mode_ = mode; verify_peer_ = verify_peer; certificate_data_ = cert_data; + hours_before_update_ = hours_before_update; LOG4CXX_DEBUG(logger_, (mode_ == SERVER ? "Server" : "Client") << " mode"); LOG4CXX_DEBUG(logger_, "Peer verification " << (verify_peer_? "enabled" : "disabled")); LOG4CXX_DEBUG(logger_, "CA certificate file is \"" << ca_certificate_file << '"'); @@ -262,10 +264,18 @@ std::string CryptoManagerImpl::LastError() const { } bool CryptoManagerImpl::IsCertificateUpdateRequired() const { - const double seconds = difftime(time(NULL), mktime(&expiration_time_)); + LOG4CXX_AUTO_TRACE(logger_); + + const time_t now = time(NULL); + const time_t cert_date = mktime(&expiration_time_); + + const double seconds = difftime(cert_date, now); + + LOG4CXX_DEBUG(logger_, "Certificate time: " << asctime(&expiration_time_)); + LOG4CXX_DEBUG(logger_, "Host time: " << asctime(localtime(&now))); + LOG4CXX_DEBUG(logger_, "Seconds before expiration: " << seconds); - return (seconds <= ( - profile::Profile::instance()->update_before_hours() * 60 * 60)); + return seconds <= hours_before_update_; } diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc index 3361711b13..e49d631092 100644 --- a/src/components/security_manager/src/ssl_context_impl.cc +++ b/src/components/security_manager/src/ssl_context_impl.cc @@ -134,69 +134,131 @@ std::map<std::string, CryptoManagerImpl::SSLContextImpl::BlockSizeGetter> CryptoManagerImpl::SSLContextImpl::max_block_sizes = CryptoManagerImpl::SSLContextImpl::create_max_block_sizes(); -SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: -DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, - const uint8_t** const out_data, size_t* out_data_size) { - DCHECK(out_data); - 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 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; - 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); +void CryptoManagerImpl::SSLContextImpl::PrintCertData(X509* cert, + const std::string& cert_owner) { + if (cert) { 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); + LOG4CXX_DEBUG(logger_, cert_owner <<" 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); + LOG4CXX_DEBUG(logger_, cert_owner << " 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); + LOG4CXX_DEBUG(logger_, "CN: " << cn << ". SERIALNUMBER: " << sn); + + ASN1_TIME* notBefore = X509_get_notBefore(cert); + ASN1_TIME* notAfter = X509_get_notAfter(cert); - if (!cn_found && last_step) { - LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app name"); - return Handshake_Result_AppNameMismatch; + if (notBefore) { + LOG4CXX_DEBUG(logger_, " Start date: " << (char*)notBefore->data); } + if (notAfter) { + LOG4CXX_DEBUG(logger_, " End date: " << (char*)notAfter->data); + } + } +} - if (!sn_found && last_step) { - LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app id"); - return Handshake_Result_AppIDMismatch; +void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() { + PrintCertData(SSL_get_certificate(connection_), "HU's"); + + 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); + PrintCertData(cert, "SERVERS"); + } +} + +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +CheckCertContext() { + 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; + } + + X509_NAME* subj_name = + X509_get_subject_name(cert); + + const std::string& cn = GetTextBy(subj_name, NID_commonName); + const std::string& sn = GetTextBy(subj_name, NID_serialNumber); + + if (hsh_context_.expected_cn.compare(cn) != 0) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app name: " << cn + << ". Expected app name: " << hsh_context_.expected_cn); + return Handshake_Result_AppNameMismatch; + } + + if (hsh_context_.expected_sn.compare(sn) != 0) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app id: " << sn + << ". Expected app id: " << hsh_context_.expected_sn); + return Handshake_Result_AppIDMismatch; + } + return Handshake_Result_Success; +} + +bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( + const uint8_t** const out_data, size_t* out_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + const size_t pend = BIO_ctrl_pending(bioOut_); + LOG4CXX_DEBUG(logger_, "Available " << pend << " bytes for handshake"); + + if (pend > 0) { + LOG4CXX_DEBUG(logger_, "Reading handshake data"); + EnsureBufferSizeEnough(pend); + + const int read_count = BIO_read(bioOut_, buffer_, pend); + if (read_count == static_cast<int>(pend)) { + *out_data_size = read_count; + *out_data = buffer_; + } else { + LOG4CXX_WARN(logger_, "BIO read fail"); + is_handshake_pending_ = false; + ResetConnection(); + return false; } } + return true; +} + +bool CryptoManagerImpl::SSLContextImpl:: +WriteHandshakeData(const uint8_t* const in_data, size_t in_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + if (in_data && in_data_size) { + const int ret = BIO_write(bioIn_, in_data, in_data_size); + if (ret <= 0) { + is_handshake_pending_ = false; + ResetConnection(); + return Handshake_Result_AbnormalFail; + } + } + return true; +} + + +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +PerformHandshake() { const int handshake_result = SSL_do_handshake(connection_); if (handshake_result == 1) { + const HandshakeResult result = CheckCertContext(); + if (result != Handshake_Result_Success) { + ResetConnection(); + is_handshake_pending_ = false; + return result; + } + + LOG4CXX_DEBUG(logger_, "SSL handshake successfully finished"); // Handshake is successful bioFilter_ = BIO_new(BIO_f_ssl()); BIO_set_ssl(bioFilter_, connection_, BIO_NOCLOSE); @@ -204,6 +266,7 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, const SSL_CIPHER *cipher = SSL_get_current_cipher(connection_); max_block_size_ = max_block_sizes[SSL_CIPHER_get_name(cipher)]; is_handshake_pending_ = false; + } else if (handshake_result == 0) { SSL_clear(connection_); is_handshake_pending_ = false; @@ -217,6 +280,7 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, << " \"" << LastError() << '"'); ResetConnection(); is_handshake_pending_ = false; + // In case error happened but ssl verification shows OK // method will return AbnormalFail. if (X509_V_OK == error) { @@ -225,24 +289,43 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, return openssl_error_convert_to_internal(error); } } + return Handshake_Result_Success; +} - const size_t pend = BIO_ctrl_pending(bioOut_); - if (pend) { - EnsureBufferSizeEnough(pend); +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, + const uint8_t** const out_data, size_t* out_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(out_data); + DCHECK(out_data_size); + *out_data = NULL; + *out_data_size = 0; - const int read_count = BIO_read(bioOut_, buffer_, pend); - if (read_count == static_cast<int>(pend)) { - *out_data_size = read_count; - *out_data = buffer_; - } else { - is_handshake_pending_ = false; - ResetConnection(); - return Handshake_Result_AbnormalFail; - } + // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake + sync_primitives::AutoLock locker(bio_locker); + if (SSL_is_init_finished(connection_)) { + LOG4CXX_DEBUG(logger_, "SSL initilization is finished"); + is_handshake_pending_ = false; + return Handshake_Result_Success; } - return Handshake_Result_Success; + if (!WriteHandshakeData(in_data, in_data_size)) { + return Handshake_Result_AbnormalFail; + } + + PrintCertInfo(); + + const HandshakeResult res = PerformHandshake(); + if (res != Handshake_Result_Success) { + return res; + } + + if (!ReadHandshakeData(out_data, out_data_size)) { + return Handshake_Result_AbnormalFail; + } + + return res; } bool CryptoManagerImpl::SSLContextImpl::Encrypt( @@ -399,6 +482,8 @@ std::string CryptoManagerImpl::SSLContextImpl::GetTextBy( const int req_len = X509_NAME_get_text_by_NID(name, object, NULL, 0); if (-1 == req_len) { + LOG4CXX_WARN(logger_, "Unable to obtain object: " << object + << " from certificate"); return std::string(); } @@ -406,8 +491,11 @@ std::string CryptoManagerImpl::SSLContextImpl::GetTextBy( 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); -} + std::string str (data.begin(), data.end() - 1); + std::transform(str.begin(), str.end(), + str.begin(), ::tolower); + return str; +} } // namespace security_manager |