From 19c91c9fde869f9adc8a8172d1ffce097270db0b Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Mon, 9 Nov 2015 14:32:03 +0900 Subject: [PATCH] Pluggable additional step added on validator Change-Id: I39ea6072c147d40f3bb9fbf682ef437936b8ca8d Signed-off-by: Kyungwook Tak --- packaging/cert-svc.spec | 2 +- vcore/CMakeLists.txt | 3 ++ vcore/vcore/PluginHandler.cpp | 95 +++++++++++++++++++++++++++++++++++ vcore/vcore/PluginHandler.h | 49 ++++++++++++++++++ vcore/vcore/SignatureValidator.cpp | 100 ++++++++++++++++++++++++++----------- vcore/vcore/ValidatorPluginApi.h | 47 +++++++++++++++++ 6 files changed, 267 insertions(+), 29 deletions(-) create mode 100644 vcore/vcore/PluginHandler.cpp create mode 100644 vcore/vcore/PluginHandler.h create mode 100644 vcore/vcore/ValidatorPluginApi.h diff --git a/packaging/cert-svc.spec b/packaging/cert-svc.spec index 4077bc6..6d9321c 100644 --- a/packaging/cert-svc.spec +++ b/packaging/cert-svc.spec @@ -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} \ diff --git a/vcore/CMakeLists.txt b/vcore/CMakeLists.txt index 5de91b1..8e54031 100644 --- a/vcore/CMakeLists.txt +++ b/vcore/CMakeLists.txt @@ -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 index 0000000..04c1a95 --- /dev/null +++ b/vcore/vcore/PluginHandler.cpp @@ -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 + +#include + +#include + +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(dlsym(m_dlhandle, "create")); + if (!createFun) { + LogError("create symbol cannot found from " << PLUGIN_PATH + << ". dlerror : " << dlerror()); + return; + } + + m_destroy = + reinterpret_cast(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 index 0000000..9754bf0 --- /dev/null +++ b/vcore/vcore/PluginHandler.h @@ -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 +#include +#include + +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 diff --git a/vcore/vcore/SignatureValidator.cpp b/vcore/vcore/SignatureValidator.cpp index eb769cd..0875661 100644 --- a/vcore/vcore/SignatureValidator.cpp +++ b/vcore/vcore/SignatureValidator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -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 &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 &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 index 0000000..17402d1 --- /dev/null +++ b/vcore/vcore/ValidatorPluginApi.h @@ -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 +#include + +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 -- 2.7.4