diff options
author | AGaliuzov <AGaliuzov@luxoft.com> | 2015-10-02 17:04:44 +0300 |
---|---|---|
committer | AGaliuzov <AGaliuzov@luxoft.com> | 2015-10-02 17:04:44 +0300 |
commit | 4fa9992398ccc40f34827ef77972067bb426a35b (patch) | |
tree | deb575aa828a7202d621a9a4ee6e0c533f607901 /src/components | |
parent | f506bac1e06a016c3ee2057331de50683cfa6281 (diff) | |
parent | 158aa1da4f33fd17466e72a384bb22e710180cb2 (diff) | |
download | sdl_core-4fa9992398ccc40f34827ef77972067bb426a35b.tar.gz |
Merge pull request #225 from LuxoftSDL/security-changes
Implement getting certificate from policy table
Diffstat (limited to 'src/components')
18 files changed, 938 insertions, 85 deletions
diff --git a/src/components/application_manager/include/application_manager/policies/policy_handler.h b/src/components/application_manager/include/application_manager/policies/policy_handler.h index a4a6349a25..422d943b73 100644 --- a/src/components/application_manager/include/application_manager/policies/policy_handler.h +++ b/src/components/application_manager/include/application_manager/policies/policy_handler.h @@ -371,6 +371,15 @@ class PolicyHandler : usage_statistics::AppStopwatchId type, int32_t timespan_seconds); +#ifdef BUILD_TESTS + void SetPolicyManager(utils::SharedPtr<PolicyManager> pm) { + policy_manager_ = pm; + } +#endif // BUILD_TESTS +#ifdef ENABLE_SECURITY + std::string RetrieveCertificate() const; +#endif // ENABLE_SECURITY + protected: /** diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc index 97ee71b67d..0282c087da 100644 --- a/src/components/application_manager/src/policies/policy_handler.cc +++ b/src/components/application_manager/src/policies/policy_handler.cc @@ -511,6 +511,13 @@ void PolicyHandler::OnAppPermissionConsentInternal( } } +#ifdef ENABLE_SECURITY +std::string PolicyHandler::RetrieveCertificate() const { + POLICY_LIB_CHECK(std::string("")); + return policy_manager_->RetrieveCertificate(); +} +#endif // ENABLE_SECURITY + void PolicyHandler::OnGetUserFriendlyMessage( const std::vector<std::string>& message_codes, const std::string& language, uint32_t correlation_id) { diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h index 9825390c9c..5767e68ae4 100644 --- a/src/components/config_profile/include/config_profile/profile.h +++ b/src/components/config_profile/include/config_profile/profile.h @@ -358,6 +358,49 @@ class Profile : public utils::Singleton<Profile> { */ uint16_t tts_global_properties_timeout() const; +#ifdef ENABLE_SECURITY + /** + * @brief Returns name of Security Manager protocol + */ + const std::string& security_manager_protocol_name() const; + + /** + * @brief Returns SSL mode + */ + const std::string& ssl_mode() const; + + /** + * @brief Returns key path to pem file + */ + const std::string& key_path() const; + + /** + * @brief Returns certificate path to pem file + */ + const std::string& cert_path() const; + + /** + * @brief Returns ca certificate path to pem file + */ + const std::string& ca_cert_path() const; + + /** + * @brief Returns ciphers + */ + const std::string& ciphers_list() const; + + /** + * @brief Returns true if Mobile app certificate is verified + */ + bool verify_peer() const; + + /** + * @brief Return hours amount when PTU should be triggered + */ + uint32_t update_before_hours() const; + +#endif //ENABLE_SECURITY + /** * @brief Reads a string value from the profile * @@ -706,6 +749,16 @@ private: uint32_t application_list_update_timeout_; uint32_t max_thread_pool_size_; uint32_t default_hub_protocol_index_; +#ifdef ENABLE_SECURITY + std::string cert_path_; + std::string ca_cert_path_; + std::string ssl_mode_; + std::string key_path_; + std::string ciphers_list_; + bool verify_peer_; + uint32_t update_before_hours_; + std::string security_manager_protocol_name_; +#endif /* * first value is count of request diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc index a8f65ae349..ed9798198c 100644 --- a/src/components/config_profile/src/profile.cc +++ b/src/components/config_profile/src/profile.cc @@ -43,6 +43,11 @@ #include "utils/threads/thread.h" #include "utils/file_system.h" +#ifdef ENABLE_SECURITY +#include <openssl/ssl.h> +#endif // ENABLE_SECURITY + + namespace { #define LOG_UPDATED_VALUE(value, key, section) {\ LOG4CXX_INFO(logger_, "Setting value '" << value\ @@ -59,6 +64,9 @@ namespace { const char* kDefaultConfigFileName = "smartDeviceLink.ini"; const char* kMainSection = "MAIN"; +#ifdef ENABLE_SECURITY +const char* kSecuritySection = "Security Manager"; +#endif const char* kPolicySection = "Policy"; const char* kHmiSection = "HMI"; const char* kAppInfoSection = "AppInfo"; @@ -191,6 +199,13 @@ const char* kDefaultPoolProtocolMask = "com.smartdevicelink.prot"; const char* kDefaultIAPSystemConfig = "/fs/mp/etc/mm/ipod.cfg"; const char* kDefaultIAP2SystemConfig = "/fs/mp/etc/mm/iap2.cfg"; +#ifdef ENABLE_SECURITY +const char* kDefaultSecurityProtocol = "TLSv1.2"; +const char* kDefaultSSLMode = "CLIENT"; +const bool kDefaultVerifyPeer = false; +const uint32_t kDefaultBeforeUpdateHours = 24; +#endif // ENABLE_SECURITY + const uint32_t kDefaultHubProtocolIndex = 0; const uint32_t kDefaultHeartBeatTimeout = 0; const uint16_t kDefautTransportManagerTCPPort = 12345; @@ -239,6 +254,18 @@ const uint32_t kDefaultAppIconsFolderMaxSize = 104857600; const uint32_t kDefaultAppIconsAmountToRemove = 1; const uint16_t kDefaultAttemptsToOpenResumptionDB = 5; const uint16_t kDefaultOpenAttemptTimeoutMsResumptionDB = 500; + +#ifdef ENABLE_SECURITY +const char* kSecurityProtocolKey = "Protocol"; +const char* kSecurityCertificatePathKey = "CertificatePath"; +const char* kSecurityCACertificatePathKey = "CACertificatePath"; +const char* kSecuritySSLModeKey = "SSLMode"; +const char* kSecurityKeyPathKey = "KeyPath"; +const char* kSecurityCipherListKey = "CipherList"; +const char* kSecurityVerifyPeerKey = "VerifyPeer"; +const char* kBeforeUpdateHours = "UpdateBeforeHours"; +#endif + } // namespace namespace profile { @@ -694,6 +721,42 @@ uint16_t Profile::tts_global_properties_timeout() const { return tts_global_properties_timeout_; } +#ifdef ENABLE_SECURITY + +const std::string& Profile::cert_path() const { + return cert_path_; +} + +const std::string& Profile::ca_cert_path() const { + return ca_cert_path_; +} + +const std::string& Profile::ssl_mode() const { + return ssl_mode_; +} + +const std::string& Profile::key_path() const { + return key_path_; +} + +const std::string& Profile::ciphers_list() const { + return ciphers_list_; +} + +bool Profile::verify_peer() const { + return verify_peer_; +} + +uint32_t Profile::update_before_hours() const { + return update_before_hours_; +} + +const std::string& Profile::security_manager_protocol_name() const { + return security_manager_protocol_name_; +} + +#endif // ENABLE_SECURITY + bool Profile::logs_enabled() const { return logs_enabled_; } @@ -737,6 +800,30 @@ void Profile::UpdateValues() { LOG_UPDATED_BOOL_VALUE(link_to_web_hmi_, kLinkToWebHMI, kHmiSection); #endif // WEB_HMI +#ifdef ENABLE_SECURITY + + ReadStringValue(&security_manager_protocol_name_, kDefaultSecurityProtocol, kSecuritySection, + kSecurityProtocolKey); + + ReadStringValue(&cert_path_, "", kSecuritySection, kSecurityCertificatePathKey); + ReadStringValue(&ca_cert_path_, "", kSecuritySection, kSecurityCACertificatePathKey); + + ReadStringValue(&ssl_mode_, kDefaultSSLMode, kSecuritySection, + kSecuritySSLModeKey); + + ReadStringValue(&key_path_, "", kSecuritySection, kSecurityKeyPathKey); + + ReadStringValue(&ciphers_list_, SSL_TXT_ALL, kSecuritySection, + kSecurityCipherListKey); + + ReadBoolValue(&verify_peer_, kDefaultVerifyPeer, kSecuritySection, + kSecurityVerifyPeerKey); + + ReadUIntValue(&update_before_hours_, kDefaultBeforeUpdateHours, + kSecuritySection, kBeforeUpdateHours); + +#endif // ENABLE_SECURITY + // Logs enabled ReadBoolValue(&logs_enabled_, false, kMainSection, kLogsEnabledKey); diff --git a/src/components/include/security_manager/crypto_manager.h b/src/components/include/security_manager/crypto_manager.h index 00c3833e62..fd8e058d10 100644 --- a/src/components/include/security_manager/crypto_manager.h +++ b/src/components/include/security_manager/crypto_manager.h @@ -57,11 +57,11 @@ class CryptoManager { virtual bool Init(Mode mode, Protocol protocol, const std::string &cert_filename, - const std::string &key_filename, const std::string &ciphers_list, - bool verify_peer) = 0; - virtual void Finish() = 0; + bool verify_peer, + const std::string& ca_cert_file) = 0; virtual SSLContext *CreateSSLContext() = 0; + virtual bool OnCertificateUpdated(const std::string& data) = 0; virtual void ReleaseSSLContext(SSLContext *context) = 0; virtual std::string LastError() const = 0; virtual ~CryptoManager() { } diff --git a/src/components/include/utils/macro.h b/src/components/include/utils/macro.h index bfd13411f4..75019863b2 100644 --- a/src/components/include/utils/macro.h +++ b/src/components/include/utils/macro.h @@ -40,7 +40,8 @@ #include "logger.h" - +// A macro to set some action for variable to avoid "unused variable" warning +#define UNUSED(x) (void)x; // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ diff --git a/src/components/include/utils/scope_guard.h b/src/components/include/utils/scope_guard.h new file mode 100644 index 0000000000..c2accdba59 --- /dev/null +++ b/src/components/include/utils/scope_guard.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2015, 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_UTILS_SCOPE_GUARD_H +#define SRC_COMPONENTS_INCLUDE_UTILS_SCOPE_GUARD_H + +namespace utils { + +/** + * @brief The ScopeGuardImplBase class the class which allows to keep safety + * raw pointer within local scope. The same ScopeGuard has been provided by + * Andrej Alexandresku in the Loki library. + * + * The usage area example: + * + * Suppose user have to create some pointer in function call Init(). And in case + * of some fail condition this pointer has to be freed. So in order to avoid + * code duplicate as follows: + * + * bool SomeClass::Init() { + * memberObject_ = custom_allocate() // initialize member object with some value + * if(!some_condition) { + * custom_release(memberObject(); + * return false; + * } + * + * if(!other_condition) { + * custom_release(memberObject) + * return false; + * } + * return true; + * } + * + * The user is able to use ScopeGuard, where possible to automatically call + * custom release function. See example bellow: + * + * bool SomeClass::Init() { + * memberObject_ = custom_allocate() // initialize member object with some value + * // The guard will call custom release function when it goes out of scope. + * ScopeGaurd guard = MakeGuard(custom_release, memberObject); + * if(!some_condition) { + * return false; + * } + * + * if(!other_condition) { + * return false; + * } + * // Here to avoid object releasing the user has to call Dismiss method. + * // So no custom release function will be called after return statement. + * guard.Dismiss(); + * return true; + * } + */ +class ScopeGuardImplBase { + public: + /** + * @brief ScopeGuardImplBase the ScopeGuards constructor. + */ + ScopeGuardImplBase(): dismissed_(false) {} + + + + /** + * @brief Dismiss function which allows to dismiss releasing of stored object. + */ + void Dismiss() const { + dismissed_ = true; + } + + protected: + /** + * @brief ScopeGuardImplBase the copy constructor + * + * @param other the object that should be copied. + */ + ScopeGuardImplBase(const ScopeGuardImplBase& other) + : dismissed_(other.dismissed_) { + other.Dismiss(); + } + + /** + * Allows to safely execute release function(i.e. it will be called only + * in case of releasing wasn't dismiss.) + */ + template<typename T> + void SafeExecute(T& t) { + if (!t.dismissed_) { + t.Execute(); + } + } + + ~ScopeGuardImplBase() {} + + mutable bool dismissed_; + + private: + // Disallow copying via assign operator. + ScopeGuardImplBase& operator=(const ScopeGuardImplBase&); +}; + +/** + * The class which allows to bind some parameter with free function. + * I.E. + * void release(char* p){delete p;} + * + * ScopeGuard guard = MakeGuard(release, p); + * + * So the parameter p will be passed to the specified function. + */ +template<typename Function, typename Parameter1> +class ScopeGuardImpl1: public ScopeGuardImplBase { + public: + /** + * @brief MakeGuard allows to create ScopeGuard object. + * + * @param fun function to call, when out of scope. + * + * @param p1 parameter which will be passed to the certain function. + * + * @return ScopeGuard object. + */ + static ScopeGuardImpl1<Function, Parameter1> MakeGuard( + Function fun, const Parameter1& p1) { + return ScopeGuardImpl1<Function, Parameter1>(fun, p1); + } + + /** + Execute the SafeExecute function in destructor. + */ + ~ScopeGuardImpl1() { + SafeExecute(*this); + } + + protected: + + /** + * @brief Execute allows to execute certain function with certain parameter. + */ + void Execute() { + fun_(p1_); + } + + /** + * @brief ScopeGuardImpl1 create ScopeGuard object. + * + * @param f function object. + * + * @param p1 parameter to to pass to the function object. + */ + ScopeGuardImpl1(const Function& f, const Parameter1& p1) + : fun_(f), p1_(p1) {} + + private: + Function fun_; + const Parameter1 p1_; + + friend class ScopeGuardImplBase; +}; + +/** + * The class which allows to call some member function in case of + * ScopeGuard object out of scope. + * I.E. + * vector<int> vec; + * + * // When function returns, the pop_back method for vector will be called. + * void foo() { + * ScopeGuard guard = MakeObjGuard(vec, &vector::pop_back); + * vec.push_back(5); + * } + */ +template<typename Obj, typename MemFun> +class ObjScopeGuardImpl0: public ScopeGuardImplBase { + public: + /** + * @brief MakeObjGuard creates ScopeGuard object. + * + * @param obj object whose method will be called. + * + * @param memFun the method to call. + * + * @return ScopeGuard object. + */ + static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard( + Obj& obj, MemFun memFun) { + return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); + } + + /** + Execute the SafeExecute function in destructor. + */ + ~ObjScopeGuardImpl0() { + SafeExecute(*this); + } + + protected: + + /** + * @brief Execute allows to execute certain function with certain parameter. + */ + void Execute() { + (obj_.*memFun_)(); + } + + /** + * @brief ObjScopeGuardImpl0 Create ScopeGuard object. + * + * @param obj object whose method will be called. + * + * @param memFun the method to call. + * + * @return ScopeGuard object. + */ + ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) {} + + private: + Obj& obj_; + MemFun memFun_; + friend class ScopeGuardImplBase; +}; + +/** + * The class which allows to call some member function with certain parameter + * in case of ScopeGuard object out of scope. + + */ +template<typename Obj, typename MemFun, typename Parameter1> +class ObjScopeGuardImpl1: public ScopeGuardImplBase { + public: + /** + * @brief MakeObjGuard creates ScopeGuard object. + * + * @param obj object whose method will be called. + * + * @param memFun the method to call. + * + * @param p1 the parameter to pass to the member function. + * + * @return ScopeGuard object. + */ + static ObjScopeGuardImpl1<Obj, MemFun, Parameter1> MakeObjGuard( + Obj& obj, MemFun memFun, const Parameter1& p1) { + return ObjScopeGuardImpl1<Obj, MemFun, Parameter1>(obj, memFun, p1); + } + + /** + Execute the SafeExecute function in destructor. + */ + ~ObjScopeGuardImpl1() { + SafeExecute(*this); + } + + protected: + /** + * @brief Execute allows to execute certain function with certain parameter. + */ + void Execute() { + (obj_.*memFun_)(p1_); + } + + /** + * @brief MakeObjGuard creates ScopeGuard object. + * + * @param obj object whose method will be called. + * + * @param memFun the method to call. + * + * @param p1 the parameter to pass to the member function. + * + * @return ScopeGuard object. + */ + ObjScopeGuardImpl1(Obj& obj, MemFun memFun, const Parameter1& p1) + : obj_(obj), + memFun_(memFun), + p1_(p1) {} + + private: + Obj& obj_; + MemFun memFun_; + const Parameter1 p1_; + friend class ScopeGuardImplBase; +}; + +typedef const ScopeGuardImplBase& ScopeGuard; + +template <typename F, typename P1> +ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) { + return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); +} + +template <typename Obj, typename MemFun> +ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) { + return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun); +} + +template <typename Obj, typename MemFun, typename P1> +ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard( + Obj& obj, MemFun memFun, const P1& p1) { + return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1); +} + +} +#endif // SRC_COMPONENTS_INCLUDE_UTILS_SCOPE_GUARD_H diff --git a/src/components/policy/src/policy/include/policy/cache_manager.h b/src/components/policy/src/policy/include/policy/cache_manager.h index e40d4afe57..fb517fa358 100644 --- a/src/components/policy/src/policy/include/policy/cache_manager.h +++ b/src/components/policy/src/policy/include/policy/cache_manager.h @@ -44,6 +44,7 @@ #include "utils/lock.h" #include "utils/timer_thread.h" #include "utils/conditional_variable.h" +#include "policy/policy_types.h" namespace policy { @@ -544,7 +545,7 @@ class CacheManager : public CacheManagerInterface { * @param file_name preloaded * @return */ - bool LoadFromFile(const std::string& file_name); + bool LoadFromFile(const std::string& file_name, policy_table::Table& table); /** * @brief Backup allows to save cache onto hard drive. @@ -575,6 +576,101 @@ class CacheManager : public CacheManagerInterface { */ void GetAppRequestTypes(const std::string& policy_app_id, std::vector<std::string>& request_types) const; + + /** + * @brief GetCertificate allows to obtain certificate in order to + * make secure connection + * + * @return The certificate in PKCS#7. + */ + virtual std::string GetCertificate() const OVERRIDE; + + /** + * @brief MergePreloadPT allows to load policy table from certain JSON file, + * and then decide if merge is needed. The merge is needed in case when preload + * JSON date is different than current database. + * + * @param file_name the preloaded policy table JSON file. + */ + void MergePreloadPT(const std::string& file_name); + + /** + * @brief MergeMC allows to merge ModuleConfig section by definite rules. + * + * The rules are: + * 1. Add new fields (known to PoliciesManager) & sub-sections if such are + * present in the updated Preloaded PT + * 2. "vehicle_make", “model”, “year” – leave the fields & values as they were + * in the database + * 3. For all other fields – overwrite the values with the new ones from preloaded PT. + * + * @param new_pt the policy table loaded from updated preload JSON file. + * + * @param pt the exists database. + */ + void MergeMC(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt); + + /** + * @brief MergeFG allows to merge FunctionalGroupings sections by definite rules. + * + * The rules are: + * 1. If functional_group_name exists in both database (LocalPT) and updated + * PreloadedPT -> PoliciesManager must overwrite it (that is, replace such + * functional_group_name in the database by the one from Pre-PT). + * 2. If functional_group_name exists in updated PreloadedPT and does not + * exist in database (LocalPT), PoliciesManager must add such group to the database. + * 3. If functional_group_name does not exist in updated PreloadedPT and + * exists in the database (LocalPT), PoliciesManager must leave such group in + * the database without changes. + * + * @param new_pt the policy table loaded from updated preload JSON file. + * + * @param pt the exists database. + */ + void MergeFG(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt); + + /** + * @brief MergeAP Allows to merge ApplicationPolicies section by definite relues. + * The rules are: + * 1. Leave “<appID>” sub-sections as they were in the database (fields & their values). + * 2. Over-write "default", "device", "pre_DataConsent" subsections. + * + * @param new_pt the policy table loaded from updated preload JSON file. + * + * @param pt the exists database. + */ + void MergeAP(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt); + + /** + * @brief MergeCFM allows to merge ConsumerFriendlyMessages section by definite rules. + * + * The rules are: + * 1. If friendly_message_name exists in both database (LocalPT) and updated + * Preloaded PT -> PoliciesManager must overwrite it. + * 2. If friendly_message_name exists in updated Preloaded PT and does not + * exist in database (LocalPT), PoliciesManager must add such + * friendly_message_name to the database (LocalPT). + * 3. If friendly_message_name does not exist in updated Preloaded PT and + * exists in the database (LocalPT), PoliciesManager must leave such + * friendly_message_name in the database without changes. + * + * @param new_pt the policy table loaded from updated preload JSON file. + * + * @param pt the exists database + */ + void MergeCFM(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt); + + +#ifdef BUILD_TESTS + utils::SharedPtr<policy_table::Table> GetPT() const { + return pt_; + } +#endif + private: std::string currentDateTime(); struct AppHMITypeToString { @@ -622,7 +718,6 @@ private: utils::SharedPtr<policy_table::Table> pt_; utils::SharedPtr<policy_table::Table> snapshot_; utils::SharedPtr<PTRepresentation> backup_; - utils::SharedPtr<PTExtRepresentation> ex_backup_; bool update_required; typedef std::set<std::string> UnpairedDevices; UnpairedDevices is_unpaired_; diff --git a/src/components/policy/src/policy/include/policy/cache_manager_interface.h b/src/components/policy/src/policy/include/policy/cache_manager_interface.h index 366b49b5a7..3458d37809 100644 --- a/src/components/policy/src/policy/include/policy/cache_manager_interface.h +++ b/src/components/policy/src/policy/include/policy/cache_manager_interface.h @@ -38,7 +38,7 @@ #include "utils/shared_ptr.h" #include "usage_statistics/counter.h" - +#include "policy/policy_types.h" namespace policy_table = rpc::policy_table_interface_base; namespace policy { @@ -538,7 +538,8 @@ class CacheManagerInterface { * @param file_name preloaded * @return */ - virtual bool LoadFromFile(const std::string& file_name) = 0; + virtual bool LoadFromFile(const std::string& file_name, + policy_table::Table& table) = 0; /** * @brief Backup allows to save cache onto hard drive. @@ -591,6 +592,24 @@ class CacheManagerInterface { virtual void GetAppRequestTypes( const std::string& policy_app_id, std::vector<std::string>& request_types) const = 0; + + /** + * @brief GetCertificate allows to obtain certificate in order to + * make secure connection + * + * @return The certificate in PKCS#7. + */ + virtual std::string GetCertificate() const = 0; + +#ifdef BUILD_TESTS + /** + * @brief GetPT allows to obtain SharedPtr to PT. + * Used ONLY in Unit tests + * @return SharedPTR to PT + * + */ + virtual utils::SharedPtr<policy_table::Table> GetPT() const = 0; +#endif }; typedef utils::SharedPtr<CacheManagerInterface> CacheManagerInterfaceSPtr; diff --git a/src/components/policy/src/policy/include/policy/policy_manager.h b/src/components/policy/src/policy/include/policy/policy_manager.h index a22ee7990f..2c41b4cafe 100644 --- a/src/components/policy/src/policy/include/policy/policy_manager.h +++ b/src/components/policy/src/policy/include/policy/policy_manager.h @@ -428,6 +428,14 @@ class PolicyManager : public usage_statistics::StatisticsManager { */ virtual void OnAppRegisteredOnMobile(const std::string& application_id) = 0; + /** + * @brief RetrieveCertificate Allows to obtain certificate in order + * to start secure connection. + * + * @return The certificate in PKCS#7 format. + */ + virtual std::string RetrieveCertificate() const = 0; + protected: /** * Checks is PT exceeded IgnitionCycles diff --git a/src/components/policy/src/policy/include/policy/policy_manager_impl.h b/src/components/policy/src/policy/include/policy/policy_manager_impl.h index 2e7843fd35..a4ef179113 100644 --- a/src/components/policy/src/policy/include/policy/policy_manager_impl.h +++ b/src/components/policy/src/policy/include/policy/policy_manager_impl.h @@ -33,7 +33,8 @@ #ifndef SRC_COMPONENTS_POLICY_INCLUDE_POLICY_POLICY_MANAGER_IMPL_H_ #define SRC_COMPONENTS_POLICY_INCLUDE_POLICY_POLICY_MANAGER_IMPL_H_ -#include <list> +#include <string> + #include "utils/shared_ptr.h" #include "utils/lock.h" #include "policy/policy_manager.h" @@ -42,6 +43,7 @@ #include "policy/update_status_manager.h" #include "./functions.h" #include "usage_statistics/statistics_manager.h" +#include "policy/policy_helper.h" namespace policy_table = rpc::policy_table_interface_base; @@ -172,11 +174,13 @@ class PolicyManagerImpl : public PolicyManager { virtual void OnAppsSearchCompleted(); - void OnAppRegisteredOnMobile(const std::string& application_id); - virtual const std::vector<std::string> GetAppRequestTypes( const std::string policy_app_id) const; - + + virtual void OnAppRegisteredOnMobile(const std::string& application_id) OVERRIDE; + + virtual std::string RetrieveCertificate() const OVERRIDE; + protected: #ifdef USE_HMI_PTU_DECRYPTION virtual utils::SharedPtr<policy_table::Table> Parse( diff --git a/src/components/policy/src/policy/include/policy/policy_types.h b/src/components/policy/src/policy/include/policy/policy_types.h index 5dcbc3587f..5be12182ae 100644 --- a/src/components/policy/src/policy/include/policy/policy_types.h +++ b/src/components/policy/src/policy/include/policy/policy_types.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013, Ford Motor Company All rights reserved. @@ -306,6 +306,14 @@ typedef std::map<uint32_t, std::pair<std::string, std::string> > FunctionalGroup */ typedef std::vector<std::string> DeviceIds; +/** + * @brief Counters that calculated on receiving of succesful update + */ +enum Counters { + KILOMETERS, + DAYS_AFTER_EPOCH +}; + } // namespace policy #endif // SRC_COMPONENTS_POLICY_INCLUDE_POLICY_POLICY_TYPES_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 dcbd66dce9..a26c1339ca 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 @@ -487,7 +487,9 @@ ModuleConfig::ModuleConfig(const Json::Value* value__) notifications_per_minute_by_priority(impl::ValueMember(value__, "notifications_per_minute_by_priority")), vehicle_make(impl::ValueMember(value__, "vehicle_make")), vehicle_model(impl::ValueMember(value__, "vehicle_model")), - vehicle_year(impl::ValueMember(value__, "vehicle_year")) { + vehicle_year(impl::ValueMember(value__, "vehicle_year")), + preloaded_date(impl::ValueMember(value__, "preloaded_date")), + certificate(impl::ValueMember(value__, "certificate")){ } Json::Value ModuleConfig::ToJsonValue() const { Json::Value result__(Json::objectValue); @@ -503,6 +505,8 @@ Json::Value ModuleConfig::ToJsonValue() const { impl::WriteJsonField("vehicle_make", vehicle_make, &result__); impl::WriteJsonField("vehicle_model", vehicle_model, &result__); impl::WriteJsonField("vehicle_year", vehicle_year, &result__); + impl::WriteJsonField("certificate", certificate, &result__); + impl::WriteJsonField("preloaded_date", preloaded_date, &result__); return result__; } bool ModuleConfig::is_valid() const { @@ -542,6 +546,12 @@ bool ModuleConfig::is_valid() const { if (!vehicle_year.is_valid()) { return false; } + if (!certificate.is_valid()) { + return false; + } + if (!preloaded_date.is_valid()) { + return false; + } return Validate(); } bool ModuleConfig::is_initialized() 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 a13c4d6e0c..4896f64a2e 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 @@ -183,6 +183,7 @@ struct ModuleConfig : CompositeType { Optional< String<1, 100> > vehicle_make; Optional< String<1, 100> > vehicle_model; Optional< String<4, 4> > vehicle_year; + Optional< String<0, 10> > preloaded_date; Optional< String<0, 65535> > certificate; public: ModuleConfig(); diff --git a/src/components/policy/src/policy/src/cache_manager.cc b/src/components/policy/src/policy/src/cache_manager.cc index 55de8ccfda..4c8784c703 100644 --- a/src/components/policy/src/policy/src/cache_manager.cc +++ b/src/components/policy/src/policy/src/cache_manager.cc @@ -1057,12 +1057,10 @@ bool CacheManager::Init(const std::string& file_name) { } break; case InitResult::SUCCESS: { LOG4CXX_INFO(logger_, "Policy Table was inited successfully"); - result = LoadFromFile(file_name); + result = LoadFromFile(file_name, *pt_); backup_->UpdateDBVersion(); if (result) { Backup(); - } else { - ex_backup_->RemoveDB(); } } break; default: { @@ -1087,7 +1085,8 @@ bool CacheManager::LoadFromBackup() { return true; } -bool CacheManager::LoadFromFile(const std::string& file_name) { +bool CacheManager::LoadFromFile(const std::string& file_name, + policy_table::Table& table) { LOG4CXX_AUTO_TRACE(logger_); BinaryMessage json_string; if (!file_system::ReadBinaryFile(file_name, json_string)) { @@ -1107,24 +1106,21 @@ bool CacheManager::LoadFromFile(const std::string& file_name) { LOG4CXX_TRACE(logger_, "Start create PT"); sync_primitives::AutoLock locker(cache_lock_); - backup_->Clear(); - pt_ = new policy_table::Table(&value); - if (pt_->is_valid()) { - if (backup_->Save(*pt_)) { - backup_->WriteDb(); - return true; - } else { - LOG4CXX_FATAL(logger_, "Failed to save PT"); - return false; - } - } else { + table = policy_table::Table(&value); + + Json::StyledWriter s_writer; + LOG4CXX_DEBUG(logger_, "PT out:"); + LOG4CXX_DEBUG(logger_, s_writer.write(table.ToJsonValue())); + + if (!table.is_valid()) { rpc::ValidationReport report("policy_table"); - pt_->ReportErrors(&report); + table.ReportErrors(&report); LOG4CXX_FATAL(logger_, "Parsed table is not valid " << rpc::PrettyFormat(report)); return false; } + return true; } bool CacheManager::ResetPT(const std::string& file_name) { @@ -1180,6 +1176,96 @@ void CacheManager::GetAppRequestTypes( return; } +std::string CacheManager::GetCertificate() const { + CACHE_MANAGER_CHECK(std::string("")); + if (pt_->policy_table.module_config.certificate.is_initialized()) { + return *pt_->policy_table.module_config.certificate; + } + return std::string(""); +} + +void CacheManager::MergePreloadPT(const std::string& file_name) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::Table table; + if (!LoadFromFile(file_name, table)) { + LOG4CXX_DEBUG(logger_, "Unable to load preloaded PT."); + return; + } + + sync_primitives::AutoLock lock(cache_lock_); + policy_table::PolicyTable& current = pt_->policy_table; + policy_table::PolicyTable& new_table = table.policy_table; + const std::string date_current = *current.module_config.preloaded_date; + const std::string date_new = *new_table.module_config.preloaded_date; + if (date_current != date_new) { + MergeMC(new_table, current); + MergeFG(new_table, current); + MergeAP(new_table, current); + MergeCFM(new_table, current); + Backup(); + } +} + +void CacheManager::MergeMC(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::ModuleConfig copy(pt.module_config); + + pt.module_config = new_pt.module_config; + pt.module_config.vehicle_make = copy.vehicle_make; + pt.module_config.vehicle_year = copy.vehicle_year; + pt.module_config.vehicle_model = copy.vehicle_model; +} + +void CacheManager::MergeFG(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::FunctionalGroupings::const_iterator it = new_pt.functional_groupings.begin(); + + for (; it != new_pt.functional_groupings.end(); ++it) { + LOG4CXX_DEBUG(logger_, "Merge functional group: " << it->first); + pt.functional_groupings[it->first] = it->second; + } +} + +void CacheManager::MergeAP(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + pt.app_policies_section.device = const_cast<policy_table::PolicyTable&> + (new_pt).app_policies_section.device; + + pt.app_policies_section.apps[kDefaultId] = + const_cast<policy_table::PolicyTable&> + (new_pt).app_policies_section.apps[kDefaultId]; + + pt.app_policies_section.apps[kPreDataConsentId] = + const_cast<policy_table::PolicyTable&> + (new_pt).app_policies_section.apps[kPreDataConsentId]; +} + +void CacheManager::MergeCFM(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + if (new_pt.consumer_friendly_messages.is_initialized()) { + if (!pt.consumer_friendly_messages.is_initialized()) { + pt.consumer_friendly_messages = new_pt.consumer_friendly_messages; + } else { + policy_table::Messages::const_iterator it = new_pt.consumer_friendly_messages->messages->begin(); + + pt.consumer_friendly_messages->version = + new_pt.consumer_friendly_messages->version; + for (; it != new_pt.consumer_friendly_messages->messages->end(); ++it) { + LOG4CXX_DEBUG(logger_, "Merge CFM: " << it->first); + if (!(pt.consumer_friendly_messages->messages.is_initialized())) { + LOG4CXX_DEBUG(logger_, "CFM not initialized."); + } + (*pt.consumer_friendly_messages->messages)[it->first] = it->second; + } + + } + } +} + CacheManager::BackgroundBackuper::BackgroundBackuper(CacheManager* cache_manager) : cache_manager_(cache_manager), stop_flag_(false), diff --git a/src/components/policy/src/policy/src/policy_manager_impl.cc b/src/components/policy/src/policy/src/policy_manager_impl.cc index 018095d343..b44db6e65e 100644 --- a/src/components/policy/src/policy/src/policy_manager_impl.cc +++ b/src/components/policy/src/policy/src/policy_manager_impl.cc @@ -842,6 +842,11 @@ void PolicyManagerImpl::OnAppRegisteredOnMobile( SendNotificationOnPermissionsUpdated(application_id); } +std::string PolicyManagerImpl::RetrieveCertificate() const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetCertificate(); +} + void PolicyManagerImpl::AddApplication(const std::string& application_id) { LOG4CXX_AUTO_TRACE(logger_); const std::string device_id = GetCurrentDeviceId(application_id); 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 43bb63ef67..6641050d40 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 @@ -87,21 +87,28 @@ class CryptoManagerImpl : public CryptoManager { public: CryptoManagerImpl(); - virtual bool Init(Mode mode, - Protocol protocol, - const std::string &cert_filename, - const std::string &key_filename, - const std::string &ciphers_list, - bool verify_peer); - virtual void Finish(); - virtual SSLContext *CreateSSLContext(); - virtual void ReleaseSSLContext(SSLContext *context); - virtual std::string LastError() const; + ~CryptoManagerImpl(); + + bool 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) OVERRIDE; + bool OnCertificateUpdated(const std::string &data) OVERRIDE; + SSLContext *CreateSSLContext() OVERRIDE; + void ReleaseSSLContext(SSLContext *context) OVERRIDE; + std::string LastError() const OVERRIDE; + +private: + bool set_certificate(const std::string &cert_data); - private: SSL_CTX *context_; Mode mode_; static uint32_t instance_count_; + static sync_primitives::Lock instance_lock_; + std::string certificate_data_; + bool verify_peer_; 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 69121a7b19..6a38b76b63 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -31,12 +31,21 @@ */ #include "security_manager/crypto_manager_impl.h" + #include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/err.h> +#include <openssl/pkcs12.h> + +#include <fstream> +#include <iostream> +#include <stdio.h> #include "security_manager/security_manager.h" + #include "utils/logger.h" #include "utils/atomic.h" +#include "utils/macro.h" +#include "utils/scope_guard.h" #define TLS1_1_MINIMAL_VERSION 0x1000103fL #define CONST_SSL_METHOD_MINIMAL_VERSION 0x00909000L @@ -46,25 +55,75 @@ namespace security_manager { CREATE_LOGGERPTR_GLOBAL(logger_, "CryptoManagerImpl") uint32_t CryptoManagerImpl::instance_count_ = 0; +sync_primitives::Lock CryptoManagerImpl::instance_lock_; -CryptoManagerImpl::CryptoManagerImpl() - : context_(NULL), mode_(CLIENT) { +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); + LOG4CXX_WARN( + logger_, + "Certificate verification failed with error " << error + << " \"" << X509_verify_cert_error_string(error) << '"'); + } + return preverify_ok; + } + + void free_ctx(SSL_CTX** ctx) { + if (ctx) { + SSL_CTX_free(*ctx); + *ctx = NULL; + } + } } -bool CryptoManagerImpl::Init(Mode mode, - Protocol protocol, - const std::string &cert_filename, - const std::string &key_filename, - const std::string &ciphers_list, - bool verify_peer) { - if (atomic_post_inc(&instance_count_) == 0) { +CryptoManagerImpl::CryptoManagerImpl() + : context_(NULL), + mode_(CLIENT), + verify_peer_(false) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(instance_lock_); + instance_count_++; + if (instance_count_ == 1) { + LOG4CXX_DEBUG(logger_, "Openssl engine initialization"); SSL_load_error_strings(); ERR_load_BIO_strings(); OpenSSL_add_all_algorithms(); SSL_library_init(); } +} +CryptoManagerImpl::~CryptoManagerImpl() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(instance_lock_); + LOG4CXX_DEBUG(logger_, "Deinitilization"); + if (!context_) { + LOG4CXX_WARN(logger_, "Manager is not initialized"); + } else { + SSL_CTX_free(context_); + } + instance_count_--; + if (instance_count_ == 0) { + LOG4CXX_DEBUG(logger_, "Openssl engine deinitialization"); + EVP_cleanup(); + ERR_free_strings(); + } +} + +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) { + LOG4CXX_AUTO_TRACE(logger_); mode_ = mode; + verify_peer_ = verify_peer; + certificate_data_ = cert_data; + 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 << '"'); + const bool is_server = (mode == SERVER); #if OPENSSL_VERSION_NUMBER < CONST_SSL_METHOD_MINIMAL_VERSION SSL_METHOD *method; @@ -112,36 +171,18 @@ bool CryptoManagerImpl::Init(Mode mode, LOG4CXX_ERROR(logger_, "Unknown protocol: " << protocol); return false; } + if (context_) { + free_ctx(&context_); + } context_ = SSL_CTX_new(method); + + utils::ScopeGuard guard = utils::MakeGuard(free_ctx, &context_); + // Disable SSL2 as deprecated SSL_CTX_set_options(context_, SSL_OP_NO_SSLv2); - if (cert_filename.empty()) { - LOG4CXX_WARN(logger_, "Empty certificate path"); - } else { - LOG4CXX_INFO(logger_, "Certificate path: " << cert_filename); - if (!SSL_CTX_use_certificate_file(context_, cert_filename.c_str(), - SSL_FILETYPE_PEM)) { - LOG4CXX_ERROR(logger_, "Could not use certificate " << cert_filename); - return false; - } - } - - if (key_filename.empty()) { - LOG4CXX_WARN(logger_, "Empty key path"); - } else { - LOG4CXX_INFO(logger_, "Key path: " << key_filename); - if (!SSL_CTX_use_PrivateKey_file(context_, key_filename.c_str(), - SSL_FILETYPE_PEM)) { - LOG4CXX_ERROR(logger_, "Could not use key " << key_filename); - return false; - } - if (!SSL_CTX_check_private_key(context_)) { - LOG4CXX_ERROR(logger_, "Could not use certificate " << cert_filename); - return false; - } - } + set_certificate(cert_data); if (ciphers_list.empty()) { LOG4CXX_WARN(logger_, "Empty ciphers list"); @@ -153,21 +194,41 @@ bool CryptoManagerImpl::Init(Mode mode, } } - // TODO(EZamakhov): add loading SSL_VERIFY_FAIL_IF_NO_PEER_CERT from INI - const int verify_mode = verify_peer - ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT - : SSL_VERIFY_NONE; - SSL_CTX_set_verify(context_, verify_mode, NULL); + if (ca_certificate_file.empty()) { + LOG4CXX_WARN(logger_, "Setting up empty CA certificate location"); + } + LOG4CXX_DEBUG(logger_, "Setting up CA certificate location"); + const int result = SSL_CTX_load_verify_locations(context_, + NULL, + ca_certificate_file.c_str()); + if (!result) { + const unsigned long error = ERR_get_error(); + UNUSED(error); + LOG4CXX_WARN( + logger_, + "Wrong certificate file '" << ca_certificate_file + << "', err 0x" << std::hex << error + << " \"" << ERR_reason_error_string(error) << '"'); + } + + guard.Dismiss(); + const int verify_mode = verify_peer_ ? SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT + : SSL_VERIFY_NONE; + LOG4CXX_DEBUG(logger_, "Setting up peer verification in mode: " << verify_mode); + SSL_CTX_set_verify(context_, verify_mode, &debug_callback); return true; } -void CryptoManagerImpl::Finish() { - SSL_CTX_free(context_); - if (atomic_post_dec(&instance_count_) == 1) { - EVP_cleanup(); - ERR_free_strings(); +bool CryptoManagerImpl::OnCertificateUpdated(const std::string &data) { + LOG4CXX_AUTO_TRACE(logger_); + if (!context_) { + LOG4CXX_WARN(logger_, "Not initialized"); + return false; } + + return set_certificate(data); } SSLContext* CryptoManagerImpl::CreateSSLContext() { @@ -199,4 +260,64 @@ std::string CryptoManagerImpl::LastError() const { return std::string(reason ? reason : ""); } + +bool CryptoManagerImpl::set_certificate(const std::string &cert_data) { + if (cert_data.empty()) { + LOG4CXX_WARN(logger_, "Empty certificate"); + return false; + } + + BIO* bio = BIO_new(BIO_f_base64()); + BIO* bmem = BIO_new_mem_buf((char*)cert_data.c_str(), cert_data.length()); + bmem = BIO_push(bio, bmem); + + char* buf = new char[cert_data.length()]; + int len = BIO_read(bmem, buf, cert_data.length()); + + + BIO* bio_cert = BIO_new(BIO_s_mem()); + if (NULL == bio_cert) { + LOG4CXX_WARN(logger_, "Unable to update certificate. BIO not created"); + return false; + } + + utils::ScopeGuard bio_guard = utils::MakeGuard(BIO_free, bio_cert); + UNUSED(bio_guard) + int k = 0; + if ((k = BIO_write(bio_cert, buf, len)) <= 0) { + LOG4CXX_WARN(logger_, "Unable to write into BIO"); + return false; + } + + PKCS12* p12 = d2i_PKCS12_bio(bio_cert, NULL); + if(NULL == p12) { + LOG4CXX_ERROR(logger_, "Unable to parse certificate"); + return false; + } + + EVP_PKEY* pkey = NULL; + X509* cert = NULL; + PKCS12_parse(p12, NULL, &pkey, &cert, NULL); + + if (NULL == cert || NULL == pkey){ + LOG4CXX_WARN(logger_, "Either certificate or key not valid."); + return false; + } + + if (!SSL_CTX_use_certificate(context_, cert)) { + LOG4CXX_WARN(logger_, "Could not use certificate"); + return false; + } + + if (!SSL_CTX_use_PrivateKey(context_, pkey)) { + LOG4CXX_ERROR(logger_, "Could not use key"); + return false; + } + if (!SSL_CTX_check_private_key(context_)) { + LOG4CXX_ERROR(logger_, "Could not use certificate "); + return false; + } + return true; +} + } // namespace security_manager |