summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorAGaliuzov <AGaliuzov@luxoft.com>2015-10-02 17:04:44 +0300
committerAGaliuzov <AGaliuzov@luxoft.com>2015-10-02 17:04:44 +0300
commit4fa9992398ccc40f34827ef77972067bb426a35b (patch)
treedeb575aa828a7202d621a9a4ee6e0c533f607901 /src/components
parentf506bac1e06a016c3ee2057331de50683cfa6281 (diff)
parent158aa1da4f33fd17466e72a384bb22e710180cb2 (diff)
downloadsdl_core-4fa9992398ccc40f34827ef77972067bb426a35b.tar.gz
Merge pull request #225 from LuxoftSDL/security-changes
Implement getting certificate from policy table
Diffstat (limited to 'src/components')
-rw-r--r--src/components/application_manager/include/application_manager/policies/policy_handler.h9
-rw-r--r--src/components/application_manager/src/policies/policy_handler.cc7
-rw-r--r--src/components/config_profile/include/config_profile/profile.h53
-rw-r--r--src/components/config_profile/src/profile.cc87
-rw-r--r--src/components/include/security_manager/crypto_manager.h6
-rw-r--r--src/components/include/utils/macro.h3
-rw-r--r--src/components/include/utils/scope_guard.h332
-rw-r--r--src/components/policy/src/policy/include/policy/cache_manager.h99
-rw-r--r--src/components/policy/src/policy/include/policy/cache_manager_interface.h23
-rw-r--r--src/components/policy/src/policy/include/policy/policy_manager.h8
-rw-r--r--src/components/policy/src/policy/include/policy/policy_manager_impl.h12
-rw-r--r--src/components/policy/src/policy/include/policy/policy_types.h10
-rw-r--r--src/components/policy/src/policy/policy_table/table_struct/types.cc12
-rw-r--r--src/components/policy/src/policy/policy_table/table_struct/types.h1
-rw-r--r--src/components/policy/src/policy/src/cache_manager.cc118
-rw-r--r--src/components/policy/src/policy/src/policy_manager_impl.cc5
-rw-r--r--src/components/security_manager/include/security_manager/crypto_manager_impl.h29
-rw-r--r--src/components/security_manager/src/crypto_manager_impl.cc209
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