Pluggable additional step added on validator 53/51353/2
authorKyungwook Tak <k.tak@samsung.com>
Mon, 9 Nov 2015 05:32:03 +0000 (14:32 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Mon, 9 Nov 2015 07:54:07 +0000 (16:54 +0900)
Change-Id: I39ea6072c147d40f3bb9fbf682ef437936b8ca8d
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
packaging/cert-svc.spec
vcore/CMakeLists.txt
vcore/vcore/PluginHandler.cpp [new file with mode: 0644]
vcore/vcore/PluginHandler.h [new file with mode: 0644]
vcore/vcore/SignatureValidator.cpp
vcore/vcore/ValidatorPluginApi.h [new file with mode: 0644]

index 4077bc6..6d9321c 100644 (file)
@@ -69,7 +69,7 @@ export FFLAGS="$FFLAGS -DTIZEN_EMULATOR_MODE"
 %endif
 
 %{!?build_type:%define build_type "Release"}
-cmake . -DPREFIX=%{_prefix} \
+%cmake . -DPREFIX=%{_prefix} \
         -DEXEC_PREFIX=%{_exec_prefix} \
         -DLIBDIR=%{_libdir} \
         -DINCLUDEDIR=%{_includedir} \
index 5de91b1..8e54031 100644 (file)
@@ -47,6 +47,7 @@ SET(VCORE_SOURCES
     ${VCORE_DIR}/vcore/Client.cpp
     ${VCORE_DIR}/vcore/Ocsp.cpp
     ${VCORE_DIR}/vcore/CryptoInit.cpp
+    ${VCORE_DIR}/vcore/PluginHandler.cpp
     )
 
 SET(VCORE_INCLUDES
@@ -75,6 +76,7 @@ SET_TARGET_PROPERTIES(${TARGET_VCORE_LIB}
 TARGET_LINK_LIBRARIES(${TARGET_VCORE_LIB}
     ${VCORE_DEPS_LIBRARIES}
     ${TARGET_CERT_SVC_LIB}
+    -ldl
     )
 
 ########## cert-server #############
@@ -129,6 +131,7 @@ INSTALL(FILES
     ${VCORE_DIR}/vcore/SignatureData.h
     ${VCORE_DIR}/vcore/CertStoreType.h
     ${VCORE_DIR}/vcore/exception.h
+    ${VCORE_DIR}/vcore/ValidatorPluginApi.h
     DESTINATION ${INCLUDEDIR}/cert-svc/vcore
     )
 
diff --git a/vcore/vcore/PluginHandler.cpp b/vcore/vcore/PluginHandler.cpp
new file mode 100644 (file)
index 0000000..04c1a95
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+/*
+ * @file        PluginHandler.cpp
+ * @author      Kyungwook Tak (k.tak@samsung.com)
+ * @version     1.0
+ * @brief       Validator plugin handler.
+ */
+
+#include <dlfcn.h>
+
+#include <dpl/log/log.h>
+
+#include <vcore/PluginHandler.h>
+
+namespace ValidationCore {
+
+PluginHandler::PluginHandler()
+       : m_dlhandle(nullptr)
+       , m_plugin(nullptr)
+       , m_destroy(nullptr)
+       , m_fail(true)
+{
+       m_dlhandle = dlopen(PLUGIN_PATH.c_str(), RTLD_NOW);
+       if (!m_dlhandle) {
+               LogInfo("Plugin library has not been found/opened : " << PLUGIN_PATH);
+               return;
+       }
+
+       CreateValidatorPlugin_t createFun =
+               reinterpret_cast<CreateValidatorPlugin_t>(dlsym(m_dlhandle, "create"));
+       if (!createFun) {
+               LogError("create symbol cannot found from " << PLUGIN_PATH
+                       << ". dlerror : " << dlerror());
+               return;
+       }
+
+       m_destroy =
+               reinterpret_cast<DestroyValidatorPlugin_t>(dlsym(m_dlhandle, "destroy"));
+       if (!m_destroy) {
+               LogError("destroy symbole cannot found from " << PLUGIN_PATH
+                       << ". dlerror : " << dlerror());
+               return;
+       }
+
+       m_plugin = createFun();
+       if (!m_plugin) {
+               LogError("cannot create plugin with create func.");
+               return;
+       }
+
+       LogDebug("create plugin with createFun success.");
+
+       m_fail = false;
+}
+
+PluginHandler::~PluginHandler()
+{
+       if (m_plugin && m_destroy)
+               m_destroy(m_plugin);
+
+       if (m_dlhandle)
+               dlclose(m_dlhandle);
+}
+
+bool PluginHandler::fail() const
+{
+       return m_fail;
+}
+
+SignatureValidator::Result PluginHandler::step(SignatureValidator::Result result, SignatureData &data)
+{
+       if (!m_plugin) {
+               LogError("Plugin is not initialized.");
+               return result;
+       }
+
+       return m_plugin->step(result, data);
+}
+
+} // namespace ValidationCore
diff --git a/vcore/vcore/PluginHandler.h b/vcore/vcore/PluginHandler.h
new file mode 100644 (file)
index 0000000..9754bf0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+/*
+ * @file        PluginHandler.h
+ * @author      Kyungwook Tak (k.tak@samsung.com)
+ * @version     1.0
+ * @brief       Validator plugin handler.
+ */
+#pragma once
+
+#include <vcore/SignatureData.h>
+#include <vcore/SignatureValidator.h>
+#include <vcore/ValidatorPluginApi.h>
+
+namespace ValidationCore {
+
+class PluginHandler {
+public:
+       PluginHandler();
+       PluginHandler(const PluginHandler &) = delete;
+       PluginHandler &operator=(const PluginHandler &) = delete;
+
+       virtual ~PluginHandler();
+
+       bool fail(void) const;
+       SignatureValidator::Result step(SignatureValidator::Result result, SignatureData &data);
+
+private:
+       void *m_dlhandle;
+       ValidatorPlugin *m_plugin;
+       DestroyValidatorPlugin_t m_destroy;
+       bool m_fail;
+};
+
+} // namespace ValidationCore
index eb769cd..0875661 100644 (file)
@@ -30,6 +30,7 @@
 #include <vcore/SignatureReader.h>
 #include <vcore/SignatureFinder.h>
 #include <vcore/Ocsp.h>
+#include <vcore/PluginHandler.h>
 
 #include <vcore/SignatureValidator.h>
 
@@ -182,12 +183,28 @@ static struct tm getMidTime(const struct tm &tb, const struct tm &ta)
 
 namespace ValidationCore {
 
+static SignatureValidator::Result additionalCheck(SignatureValidator::Result result, SignatureData &data)
+{
+       try {
+               PluginHandler handler;
+               if (handler.fail()) {
+                       LogInfo("No validator plugin found. Skip additional check.");
+                       return result;
+               }
+
+               return handler.step(result, data);
+       } catch (...) {
+               LogError("Exception in additional check by plugin.");
+               return SignatureValidator::SIGNATURE_INVALID;
+       }
+}
+
 /*
- *  Prepare to check / checklist. parse xml and save info to signature data.
+ *  Parse xml and save info to signature data.
  *
  *  [out] outData  : signature data for validating and will be finally returned to client.
  */
-int prepareToCheck(SignatureData &outData)
+static int parseSignature(SignatureData &outData)
 {
        try {
                SignatureReader xml;
@@ -212,8 +229,8 @@ static int makeDataBySignature(
 {
        data = SignatureData(fileInfo.getFileName(), fileInfo.getFileNumber());
 
-       if (prepareToCheck(data)) {
-               LogError("Failed to prepare to check.");
+       if (parseSignature(data)) {
+               LogError("Failed to parse signature.");
                return -1;
        }
 
@@ -257,7 +274,7 @@ static int makeDataBySignature(
  *  [out] context   : xml sec for validating.
  *  [out] data      : signature data for validationg and will be finally returned to client.
  */
-static SignatureValidator::Result checkInternal(
+static SignatureValidator::Result preStep(
        const SignatureFileInfo &fileInfo,
        bool &disregard,
        XmlSec::XmlSecContext &context,
@@ -319,7 +336,7 @@ static SignatureValidator::Result checkInternal(
        return SignatureValidator::SIGNATURE_VERIFIED;
 }
 
-SignatureValidator::Result SignatureValidator::check(
+SignatureValidator::Result baseCheck(
        const SignatureFileInfo &fileInfo,
        const std::string &widgetContentPath,
        bool checkOcsp,
@@ -327,47 +344,48 @@ SignatureValidator::Result SignatureValidator::check(
        SignatureData &outData)
 {
        bool disregard = false;
+       SignatureValidator::Result result = SignatureValidator::SIGNATURE_INVALID;
 
        try {
                XmlSec::XmlSecContext context;
-               Result result = checkInternal(fileInfo, disregard, context, outData);
-               if (result != SIGNATURE_VERIFIED)
+               result = preStep(fileInfo, disregard, context, outData);
+               if (result != SignatureValidator::SIGNATURE_VERIFIED)
                        return result;
 
                if (!outData.isAuthorSignature()) {
                        if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&context)) {
                                LogWarning("Installation break - invalid package!");
-                               return SIGNATURE_INVALID;
+                               return SignatureValidator::SIGNATURE_INVALID;
                        }
 
                        outData.setReference(context.referenceSet);
                        if (!checkObjectReferences(outData)) {
                                LogWarning("Failed to check Object References");
-                               return SIGNATURE_INVALID;
+                               return SignatureValidator::SIGNATURE_INVALID;
                        }
 
                        if (checkReferences) {
                                ReferenceValidator fileValidator(widgetContentPath);
                                if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(outData)) {
                                        LogWarning("Invalid package - file references broken");
-                                       return SIGNATURE_INVALID;
+                                       return SignatureValidator::SIGNATURE_INVALID;
                                }
                        }
                }
 
                if (checkOcsp && Ocsp::check(outData) == Ocsp::Result::REVOKED) {
                        LogError("Certificate is Revoked by OCSP server.");
-                       return SIGNATURE_REVOKED;
+                       return SignatureValidator::SIGNATURE_REVOKED;
                }
 
                LogDebug("Signature validation check done successfully ");
 
        } catch (const CertificateCollection::Exception::Base &e) {
                LogError("CertificateCollection exception : " << e.DumpToString());
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        } catch (const XmlSec::Exception::Base &e) {
                LogError("XmlSec exception : " << e.DumpToString());
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        } catch (const Ocsp::Exception::Base &e) {
                LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString());
                /*
@@ -377,16 +395,16 @@ SignatureValidator::Result SignatureValidator::check(
                 */
        } catch (const std::exception &e) {
                LogError("std exception occured : " << e.what());
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        } catch (...) {
                LogError("Unknown exception in SignatureValidator::check");
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        }
 
-       return disregard ? SIGNATURE_DISREGARD : SIGNATURE_VERIFIED;
+       return disregard ? SignatureValidator::SIGNATURE_DISREGARD : SignatureValidator::SIGNATURE_VERIFIED;
 }
 
-SignatureValidator::Result SignatureValidator::checkList(
+SignatureValidator::Result baseCheckList(
        const SignatureFileInfo &fileInfo,
        const std::string &widgetContentPath,
        const std::list<std::string> &uriList,
@@ -395,23 +413,24 @@ SignatureValidator::Result SignatureValidator::checkList(
        SignatureData &outData)
 {
        bool disregard = false;
+       SignatureValidator::Result result = SignatureValidator::SIGNATURE_INVALID;
 
        try {
                XmlSec::XmlSecContext context;
-               Result result = checkInternal(fileInfo, disregard, context, outData);
-               if (result != SIGNATURE_VERIFIED)
+               result = preStep(fileInfo, disregard, context, outData);
+               if (result != SignatureValidator::SIGNATURE_VERIFIED)
                        return result;
 
                if (uriList.size() == 0) {
                        if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validateNoHash(&context)) {
                                LogWarning("Installation break - invalid package! >> validateNoHash");
-                               return SIGNATURE_INVALID;
+                               return SignatureValidator::SIGNATURE_INVALID;
                        }
                } else {
                        XmlSecSingleton::Instance().setPartialHashList(uriList);
                        if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validatePartialHash(&context)) {
                                LogWarning("Installation break - invalid package! >> validatePartialHash");
-                               return SIGNATURE_INVALID;
+                               return SignatureValidator::SIGNATURE_INVALID;
                        }
                }
 
@@ -427,23 +446,23 @@ SignatureValidator::Result SignatureValidator::checkList(
                        ReferenceValidator fileValidator(widgetContentPath);
                        if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(outData)) {
                                LogWarning("Invalid package - file references broken");
-                               return SIGNATURE_INVALID;
+                               return SignatureValidator::SIGNATURE_INVALID;
                        }
                }
 
                if (checkOcsp && Ocsp::check(outData) == Ocsp::Result::REVOKED) {
                        LogError("Certificate is Revoked by OCSP server.");
-                       return SIGNATURE_REVOKED;
+                       return SignatureValidator::SIGNATURE_REVOKED;
                }
 
                LogDebug("Signature validation of check list done successfully ");
 
        } catch (const CertificateCollection::Exception::Base &e) {
                LogError("CertificateCollection exception : " << e.DumpToString());
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        } catch (const XmlSec::Exception::Base &e) {
                LogError("XmlSec exception : " << e.DumpToString());
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        } catch (const Ocsp::Exception::Base &e) {
                LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString());
                /*
@@ -453,10 +472,35 @@ SignatureValidator::Result SignatureValidator::checkList(
                 */
        } catch (...) {
                LogError("Unknown exception in SignatureValidator::checkList");
-               return SIGNATURE_INVALID;
+               return SignatureValidator::SIGNATURE_INVALID;
        }
 
-       return disregard ? SIGNATURE_DISREGARD : SIGNATURE_VERIFIED;
+       return disregard ? SignatureValidator::SIGNATURE_DISREGARD : SignatureValidator::SIGNATURE_VERIFIED;
+}
+
+SignatureValidator::Result SignatureValidator::check(
+       const SignatureFileInfo &fileInfo,
+       const std::string &widgetContentPath,
+       bool checkOcsp,
+       bool checkReferences,
+       SignatureData &outData)
+{
+       Result result = baseCheck(fileInfo, widgetContentPath, checkOcsp, checkReferences, outData);
+
+       return additionalCheck(result, outData);
+}
+
+SignatureValidator::Result SignatureValidator::checkList(
+       const SignatureFileInfo &fileInfo,
+       const std::string &widgetContentPath,
+       const std::list<std::string> &uriList,
+       bool checkOcsp,
+       bool checkReferences,
+       SignatureData &outData)
+{
+       Result result = baseCheckList(fileInfo, widgetContentPath, uriList, checkOcsp, checkReferences, outData);
+
+       return additionalCheck(result, outData);
 }
 
 SignatureValidator::Result SignatureValidator::makeChainBySignature(
diff --git a/vcore/vcore/ValidatorPluginApi.h b/vcore/vcore/ValidatorPluginApi.h
new file mode 100644 (file)
index 0000000..17402d1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+/*
+ * @file        ValidatonPluginApi.h
+ * @author      Kyungwook Tak (k.tak@samsung.com)
+ * @version     1.0
+ * @brief       Validator plugin interface.
+ */
+#pragma once
+
+#include <vcore/SignatureData.h>
+#include <vcore/SignatureValidator.h>
+
+namespace ValidationCore {
+
+const std::string PLUGIN_PATH = "/usr/lib/libcert-svc-validator-plugin.so";
+
+class ValidatorPlugin {
+public:
+       virtual SignatureValidator::Result step(SignatureValidator::Result result, SignatureData &data) = 0;
+       virtual ~ValidatorPlugin() {}
+};
+
+/*
+ *  plugin developer should implement create/destroy pair functions
+ *
+ *  1. function extern C named 'create' of CreateValidatorPlugin_t
+ *  2. function extern C named 'destroy' of DestroyValidatorPlugin_t
+ */
+typedef ValidatorPlugin *(*CreateValidatorPlugin_t)(void);
+typedef void (*DestroyValidatorPlugin_t)(ValidatorPlugin *ptr);
+
+} // namespace ValidatonCore