From 5ff8fb7653922931794b62d2d255b0e64d4db17e Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Tue, 21 Feb 2017 15:22:33 +0900 Subject: [PATCH] Implement launch operation on ACTA * TODO: Add logic to check system certs's change. Change-Id: I596ba360ebbd602ccde3544a621af31f97464ba4 Signed-off-by: sangwan.kwon --- CMakeLists.txt | 2 + packaging/cert-svc.spec | 2 + src/transec/AppCustomTrustAnchor.cpp | 52 +++++++++- tests/transec/CMakeLists.txt | 3 +- ...om-trust-anchor.cpp => test-acta-installer.cpp} | 67 ++----------- tests/transec/test-acta-launcher.cpp | 110 +++++++++++++++++++++ 6 files changed, 171 insertions(+), 65 deletions(-) rename tests/transec/{test-app-custom-trust-anchor.cpp => test-acta-installer.cpp} (66%) create mode 100644 tests/transec/test-acta-launcher.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f9de2ad..1b06c31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,8 @@ ADD_DEFINITIONS("-DCERTSVC_TRANSEC_DIR=\"${CERT_SVC_TRANSEC}\"") ADD_DEFINITIONS("-DTZ_SYS_CA_CERTS=\"${TZ_SYS_CA_CERTS}\"") ADD_DEFINITIONS("-DTZ_SYS_CA_CERTS_ORIG=\"${TZ_SYS_CA_CERTS_ORIG}\"") ADD_DEFINITIONS("-DTZ_SYS_CA_BUNDLE=\"${TZ_SYS_CA_BUNDLE}\"") +ADD_DEFINITIONS("-DTZ_SYS_RO_CA_CERTS=\"${TZ_SYS_RO_CA_CERTS}\"") +ADD_DEFINITIONS("-DTZ_SYS_RO_CA_BUNDLE=\"${TZ_SYS_RO_CA_BUNDLE}\"") SET(CA_CERTS_PATH ${RO_DATA_DIR}/ca-certificates) ADD_DEFINITIONS("-DTZ_SYS_CA_CERTS_TIZEN=\"${CA_CERTS_PATH}/tizen\"") diff --git a/packaging/cert-svc.spec b/packaging/cert-svc.spec index 83fee99..0a24a32 100644 --- a/packaging/cert-svc.spec +++ b/packaging/cert-svc.spec @@ -108,6 +108,8 @@ export FFLAGS="$FFLAGS -DTIZEN_EMULATOR_MODE" -DTZ_SYS_CA_CERTS=%TZ_SYS_CA_CERTS \ -DTZ_SYS_CA_CERTS_ORIG=%TZ_SYS_CA_CERTS_ORIG \ -DTZ_SYS_CA_BUNDLE=%TZ_SYS_CA_BUNDLE \ + -DTZ_SYS_RO_CA_CERTS=%TZ_SYS_RO_CA_CERTS \ + -DTZ_SYS_RO_CA_BUNDLE=%TZ_SYS_RO_CA_BUNDLE \ -DCERT_SVC_CA_BUNDLE=%cert_svc_ca_bundle \ -DFINGERPRINT_LIST_RW_PATH=%TZ_SYS_REVOKED_CERTS_FINGERPRINTS_RUNTIME \ -DCERT_SVC_PATH=%cert_svc_path \ diff --git a/src/transec/AppCustomTrustAnchor.cpp b/src/transec/AppCustomTrustAnchor.cpp index d71a945..bee5070 100644 --- a/src/transec/AppCustomTrustAnchor.cpp +++ b/src/transec/AppCustomTrustAnchor.cpp @@ -21,9 +21,11 @@ */ #include "AppCustomTrustAnchor.h" +#include #include #include #include +#include #include #include @@ -43,6 +45,8 @@ const std::string BASE_CERTS_PATH(BASE_PATH + "/certs"); const std::string BASE_BUNDLE_PATH(BASE_PATH + "/bundle"); const std::string SYS_CERTS_PATH(TZ_SYS_CA_CERTS); const std::string SYS_BUNDLE_PATH(TZ_SYS_CA_BUNDLE); +const std::string MOUNT_POINT_CERTS(TZ_SYS_CA_CERTS); +const std::string MOUNT_POINT_BUNDLE(TZ_SYS_CA_BUNDLE); const std::string BUNDLE_NAME("ca-bundle.pem"); const std::string NEW_LINE("\n"); @@ -65,6 +69,7 @@ private: void preInstall(void) const; void linkTo(const std::string &src, const std::string &dst) const; void makeCustomBundle(const std::vector &certs) const; + std::string readLink(const std::string &path) const; std::string getUniqueHashName(const std::string &hashName) const; std::string m_packageId; @@ -100,6 +105,13 @@ AppCustomTrustAnchor::Impl::Impl(const std::string &packageId, m_customBundlePath(BASE_BUNDLE_PATH + "/global/" + packageId), m_customCertNameSet() {} +std::string AppCustomTrustAnchor::Impl::readLink(const std::string &path) const +{ + std::vector buf(PATH_MAX); + ssize_t count = readlink(path.c_str(), buf.data(), buf.size()); + return std::string(buf.data(), (count > 0) ? count : 0); +} + void AppCustomTrustAnchor::Impl::linkTo(const std::string &src, const std::string &dst) const { @@ -144,7 +156,7 @@ int AppCustomTrustAnchor::Impl::install(bool withSystemCerts) noexcept // link system certificates to the custom directory runtime::DirectoryIterator iter(SYS_CERTS_PATH), end; while (iter != end) { - linkTo(iter->getPath(), + linkTo(readLink(iter->getPath()), this->m_customCertsPath + "/" + iter->getName()); this->m_customCertNameSet.emplace(iter->getName()); ++iter; @@ -208,10 +220,40 @@ int AppCustomTrustAnchor::Impl::uninstall(bool isRollback) noexcept int AppCustomTrustAnchor::Impl::launch(bool withSystemCerts) { - if (withSystemCerts) - return 0; - else - return -1; + EXCEPTION_GUARD_START + + // TODO(sangwan.kwon) add logic to check system certificates's change + (void) withSystemCerts; + + errno = 0; + // disassociate from the parent namespace + if (::unshare(CLONE_NEWNS)) + throw std::logic_error("Failed to unshare namespace > " + + std::to_string(errno)); + + // convert it to a slave for preventing propagation + if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) + throw std::logic_error("Failed to disconnect root fs."); + + if (::mount(this->m_customCertsPath.c_str(), + MOUNT_POINT_CERTS.c_str(), + NULL, + MS_BIND, + NULL)) + throw std::logic_error("Failed to mount certs."); + + auto bundle = this->m_customBundlePath + "/" + BUNDLE_NAME; + if (::mount(bundle.c_str(), + MOUNT_POINT_BUNDLE.c_str(), + NULL, + MS_BIND, + NULL)) + throw std::logic_error("Failed to mount bundle."); + + INFO("Success to launch. : " << this->m_packageId); + return 0; + + EXCEPTION_GUARD_END } std::string AppCustomTrustAnchor::Impl::getUniqueHashName( diff --git a/tests/transec/CMakeLists.txt b/tests/transec/CMakeLists.txt index 3d203c5..6a6d98b 100644 --- a/tests/transec/CMakeLists.txt +++ b/tests/transec/CMakeLists.txt @@ -18,7 +18,8 @@ # SET(TEST_SRCS main.cpp - test-app-custom-trust-anchor.cpp + test-acta-installer.cpp + test-acta-launcher.cpp test-certificate.cpp ) diff --git a/tests/transec/test-app-custom-trust-anchor.cpp b/tests/transec/test-acta-installer.cpp similarity index 66% rename from tests/transec/test-app-custom-trust-anchor.cpp rename to tests/transec/test-acta-installer.cpp index f21eb7a..580b98a 100644 --- a/tests/transec/test-app-custom-trust-anchor.cpp +++ b/tests/transec/test-acta-installer.cpp @@ -14,19 +14,24 @@ * limitations under the License. */ /* - * @file test-app-custom-trust-anchor.cpp + * @file test-acta-installer.cpp * @author Sangwan Kwon (sangwan.kwon@samsung.com) * @version 0.1 - * @brief Unit test program of AppCustomTrustAnchor + * @brief Unit test program of ACTA for installer */ #include #include +#include +#include + +#include + #include "test-resource.h" -RUNNER_TEST_GROUP_INIT(T0400_API_ACTA) +RUNNER_TEST_GROUP_INIT(T0400_API_ACTA_INSTALLER) using namespace transec; @@ -119,59 +124,3 @@ RUNNER_TEST(T0424_ACTA_UNINSTALL_USER_APP_NEGATIVE) int ret = acta.uninstall(); RUNNER_ASSERT_MSG(ret != 0, "ACTA uninstall should be fail."); } - -RUNNER_TEST(T0441_ACTA_LAUNCH_GLOBAL_APP_POSITIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR); - int ret = acta.launch(false); - RUNNER_ASSERT_MSG(ret == 0, "ACTA launch should be success."); -} - -RUNNER_TEST(T0442_ACTA_LAUNCH_GLOBAL_APP_WITH_SYS_POSITIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR); - int ret = acta.launch(true); - RUNNER_ASSERT_MSG(ret == 0, "ACTA launch should be success."); -} - -RUNNER_TEST(T0443_ACTA_LAUNCH_USER_APP_POSITIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR, DUMMY_UID); - int ret = acta.launch(false); - RUNNER_ASSERT_MSG(ret == 0, "ACTA launch should be success."); -} - -RUNNER_TEST(T0444_ACTA_INSTALL_USER_APP_WITH_SYS_POSITIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR, DUMMY_UID); - int ret = acta.launch(true); - RUNNER_ASSERT_MSG(ret == 0, "ACTA launch should be success."); -} - -RUNNER_TEST(T0445_ACTA_LAUNCH_GLOBAL_APP_NEGATIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR); - int ret = acta.launch(false); - RUNNER_ASSERT_MSG(ret != 0, "ACTA launch should be fail."); -} - -RUNNER_TEST(T0446_ACTA_LAUNCH_GLOBAL_APP_WITH_SYS_NEGATIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR); - int ret = acta.launch(true); - RUNNER_ASSERT_MSG(ret != 0, "ACTA launch should be fail."); -} - -RUNNER_TEST(T0447_ACTA_LAUNCH_USER_APP_NEGATIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR, DUMMY_UID); - int ret = acta.launch(false); - RUNNER_ASSERT_MSG(ret != 0, "ACTA launch should be fail."); -} - -RUNNER_TEST(T0448_ACTA_LAUNCH_USER_APP_WITH_SYS_NEGATIVE) -{ - AppCustomTrustAnchor acta(DUMMY_PKG_ID, DUMMY_CERTS_DIR, DUMMY_UID); - int ret = acta.launch(true); - RUNNER_ASSERT_MSG(ret != 0, "ACTA launch should be fail."); -} diff --git a/tests/transec/test-acta-launcher.cpp b/tests/transec/test-acta-launcher.cpp new file mode 100644 index 0000000..32b5d39 --- /dev/null +++ b/tests/transec/test-acta-launcher.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017 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 test-actc-launcher.cpp + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief Unit test program of ACTA for launcher + */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include "test-resource.h" + +RUNNER_TEST_GROUP_INIT(T0600_API_ACTA_LAUNCER) + +using namespace transec; + +namespace { + +std::string ls(const char *path) +{ + using FilePtr = std::unique_ptr; + std::string cmd("/bin/ls "); + cmd.append(path); + + FilePtr ls(::popen(cmd.c_str(), "r"), ::pclose); + if (ls == nullptr) + return std::string(); + + std::vector buf(1024); + std::string ret; + while (::fgets(buf.data(), buf.size(), ls.get())) + ret.append(buf.data()); + + return ret; +} + +std::string cat(const char *path) +{ + using FilePtr = std::unique_ptr; + std::string cmd("/bin/cat "); + cmd.append(path); + + FilePtr ls(::popen(cmd.c_str(), "r"), ::pclose); + if (ls == nullptr) + return std::string(); + + std::vector buf(1024); + std::string ret; + while (::fgets(buf.data(), buf.size(), ls.get())) + ret.append(buf.data()); + + return ret; +} + +} // namesapce anonymous + +// Launch needs CAP_SYS_ADMIN +RUNNER_TEST(T0601_ACTA_LAUNCH) +{ + auto beforeLs = ::ls(TZ_SYS_RO_CA_CERTS); + auto beforeCat = ::cat(TZ_SYS_RO_CA_BUNDLE); + + AppCustomTrustAnchor acta(DUMMY_PKG_ID, APP_CERTS_DIR); + int ret = acta.install(false); + + // pre-condition + int pid = fork(); + + if (pid == 0) { + ret = acta.launch(false); + RUNNER_ASSERT_MSG(ret == 0, "ACTA launch should be success."); + + auto afterLsChild = ::ls(TZ_SYS_RO_CA_CERTS); + RUNNER_ASSERT_MSG(beforeLs != afterLsChild, "Failed to launch."); + + auto afterCatChild = ::cat(TZ_SYS_RO_CA_BUNDLE); + RUNNER_ASSERT_MSG(beforeCat != afterCatChild, "Failed to launch."); + + } else { + auto afterLsParent = ::ls(TZ_SYS_RO_CA_CERTS); + RUNNER_ASSERT_MSG(beforeLs == afterLsParent, "Failed to launch."); + + auto afterCatParent = ::cat(TZ_SYS_RO_CA_BUNDLE); + RUNNER_ASSERT_MSG(beforeCat == afterCatParent, "Failed to launch."); + } +} -- 2.7.4