From eff654b41f557c85de3853136e51c4949218de1f Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Fri, 2 Jun 2017 17:30:47 +0900 Subject: [PATCH] Refactor implementation of TrustAnchor - According to class diagram v2 Change-Id: I31c920ff155f96981e6b6ba838d7ccd07dabd459 Signed-off-by: sangwan.kwon --- packaging/trust-anchor.spec | 2 +- src/CMakeLists.txt | 2 + src/environment.hxx | 39 +++++ src/file-system.cpp | 55 ++++++ src/file-system.hxx | 35 ++++ src/logic.cpp | 244 +++++++++++++++++++++++++++ src/logic.hxx | 68 ++++++++ src/trust-anchor.cpp | 327 ++++++------------------------------ tests/script/pre-test.sh.in | 4 +- 9 files changed, 497 insertions(+), 279 deletions(-) create mode 100644 src/environment.hxx create mode 100644 src/file-system.cpp create mode 100644 src/file-system.hxx create mode 100644 src/logic.cpp create mode 100644 src/logic.hxx diff --git a/packaging/trust-anchor.spec b/packaging/trust-anchor.spec index cea4289..538c884 100644 --- a/packaging/trust-anchor.spec +++ b/packaging/trust-anchor.spec @@ -1,5 +1,5 @@ Name: trust-anchor -Version: 0.0.1 +Version: 0.0.2 Release: 0 License: Apache-2.0 Source0: file://%{name}-%{version}.tar.gz diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2de205d..a42fd7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,8 @@ SET(${TARGET_TANCHOR_LIB}_SRCS ${TANCHOR_SRC}/init-lib.cpp ${TANCHOR_SRC}/exception.cpp ${TANCHOR_SRC}/api.cpp ${TANCHOR_SRC}/certificate.cpp + ${TANCHOR_SRC}/file-system.cpp + ${TANCHOR_SRC}/logic.cpp ${TANCHOR_SRC}/trust-anchor.cpp) INCLUDE_DIRECTORIES(SYSTEM ${TANCHOR_INCLUDE} diff --git a/src/environment.hxx b/src/environment.hxx new file mode 100644 index 0000000..1db8beb --- /dev/null +++ b/src/environment.hxx @@ -0,0 +1,39 @@ +/* + * 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 environment.hxx + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief Environment variables + */ +#pragma once + +namespace tanchor { +namespace path { + +const std::string BASE_USR_PATH(TANCHOR_USR_DIR); +const std::string BASE_GLOBAL_PATH(TANCHOR_GLOBAL_DIR); +const std::string SYS_CERTS_PATH(TZ_SYS_CA_CERTS); +const std::string SYS_BUNDLE_PATH(TZ_SYS_CA_BUNDLE); + +const std::string TANCHOR_SYSCA_PATH = TANCHOR_SYSCA; +const std::string TANCHOR_BUNDLE_PATH = TANCHOR_BUNDLE; + +const std::string MOUNT_POINT_CERTS(TZ_SYS_CA_CERTS); +const std::string MOUNT_POINT_BUNDLE(TZ_SYS_CA_BUNDLE); + +} // namespace path +} // namespace tanchor diff --git a/src/file-system.cpp b/src/file-system.cpp new file mode 100644 index 0000000..5eaa2f7 --- /dev/null +++ b/src/file-system.cpp @@ -0,0 +1,55 @@ +/* + * 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 file-system.cpp + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief + */ +#include "file-system.hxx" + +#include +#include +#include + +#include + +#include "exception.hxx" + +namespace tanchor { + +void File::linkTo(const std::string &src, const std::string &dst) +{ + if (::symlink(src.c_str(), dst.c_str())) + ThrowErrno(errno, "Failed to link " + src + " -> " + dst); +} + +std::string File::readLink(const std::string &path) +{ + 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); +} + +std::string File::getName(const std::string &path) +{ + size_t pos = path.rfind('/'); + if (pos == std::string::npos) + throw std::invalid_argument("Path is wrong. > " + path); + return path.substr(pos + 1); +} + +} // namespace tanchor diff --git a/src/file-system.hxx b/src/file-system.hxx new file mode 100644 index 0000000..0e3dcfa --- /dev/null +++ b/src/file-system.hxx @@ -0,0 +1,35 @@ +/* + * 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 file-system.hxx + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief + */ +#pragma once + +#include + +namespace tanchor { + +class File { +public: + static void linkTo(const std::string &src, const std::string &dst); + static std::string readLink(const std::string &path); + static std::string getName(const std::string &path); +}; + +} // namespace tanchor diff --git a/src/logic.cpp b/src/logic.cpp new file mode 100644 index 0000000..d7f7d98 --- /dev/null +++ b/src/logic.cpp @@ -0,0 +1,244 @@ +/* + * 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 logic.cpp + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief + */ +#include "logic.hxx" + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "certificate.hxx" +#include "file-system.hxx" +#include "exception.hxx" +#include "environment.hxx" + +namespace tanchor { + +Logic::Logic(const std::string &appCertsPath, const std::string &basePath) : + m_appCertsPath(appCertsPath), + m_customBasePath(basePath), + m_customCertsPath(m_customBasePath + "/certs"), + m_customBundlePath(m_customBasePath + "/bundle"), + m_customCertNameSet(), + m_customCertsData() {} + +void Logic::init(void) const +{ + runtime::File customBaseDir(this->m_customBasePath); + if (customBaseDir.exists()) { + WARN("App custom directory is already exist. remove it!"); + customBaseDir.remove(true); + } + customBaseDir.makeDirectory(true); + + runtime::File customCertsDir(this->m_customCertsPath); + customCertsDir.makeDirectory(); + + runtime::File customBundleDir(this->m_customBundlePath); + customBundleDir.makeDirectory(); + DEBUG("Success to init[" << this->m_customBasePath << "]"); +} + +void Logic::deinit(bool isRollback) const +{ + runtime::File customBaseDir(this->m_customBasePath); + if (customBaseDir.exists()) + customBaseDir.remove(true); + else if (!isRollback) + throw std::invalid_argument("tanchor is never installed before."); + + DEBUG("Success to deinit[" << this->m_customBasePath << "]"); +} + +void Logic::makeCustomCerts(void) +{ + if (this->isSystemCertsUsed()) { + // link system certificates to the custom directory + runtime::DirectoryIterator iter(path::SYS_CERTS_PATH), end; + while (iter != end) { + auto name = iter->getName(); + File::linkTo(File::readLink(iter->getPath()), + this->m_customCertsPath + "/" + name); + this->m_customCertNameSet.emplace(File::getName(iter->getPath())); + ++iter; + } + DEBUG("Success to migrate system certificates."); + } + + // link app certificates to the custom directory as subjectNameHash + runtime::DirectoryIterator iter(this->m_appCertsPath), end; + while (iter != end) { + Certificate cert(iter->getPath()); + std::string uName = this->getUniqueCertName(cert.getSubjectNameHash()); + File::linkTo(iter->getPath(), this->m_customCertsPath + "/" + uName); + this->m_customCertNameSet.emplace(std::move(uName)); + + this->m_customCertsData.emplace_back(cert.getCertificateData()); + ++iter; + } +} + +void Logic::makeCustomBundle(void) +{ + runtime::File customBundle(this->m_customBundlePath + "/" + + File::getName(path::SYS_BUNDLE_PATH)); + if (customBundle.exists()) { + WARN("App custom bundle is already exist. remove it!"); + customBundle.remove(); + } + + DEBUG("Start to migrate previous bundle."); + if (this->isSystemCertsUsed()) { + runtime::File sysBundle(path::SYS_BUNDLE_PATH); + sysBundle.copyTo(this->m_customBundlePath); + } else { + runtime::File tanchorBundle(path::TANCHOR_BUNDLE_PATH); + tanchorBundle.copyTo(this->m_customBundlePath); + } + DEBUG("Finish migrating previous bundle."); + + if (this->m_customCertsData.empty()) { + DEBUG("System certificates is changed after TrustAnchor installation."); + runtime::DirectoryIterator iter(this->m_appCertsPath), end; + while (iter != end) { + Certificate cert(iter->getPath()); + this->m_customCertsData.emplace_back(cert.getCertificateData()); + ++iter; + } + } + + DEBUG("Start to add app's certificate to bundle."); + customBundle.open(O_RDWR | O_APPEND); + for (const auto &cert : this->m_customCertsData) { + customBundle.write(cert.c_str(), cert.length()); + std::string newLine = "\n"; + customBundle.write(newLine.c_str(), newLine.length()); + } + + INFO("Success to make app custom bundle."); +} + +bool Logic::isAppCertsValid(void) const +{ + runtime::File file(this->m_appCertsPath); + + if (!file.exists()) + ThrowExc(TRUST_ANCHOR_ERROR_NO_SUCH_FILE, + "File [" << file.getPath() << "] does not exist."); + + if (!file.canRead()) + ThrowExc(TRUST_ANCHOR_ERROR_PERMISSION_DENIED, + "No permission to read [" << file.getPath() << "]"); + + return file.isDirectory(); +} + +void Logic::setSystemCertsUsed(void) const +{ + runtime::File tanchorSysCA(path::TANCHOR_SYSCA_PATH); + tanchorSysCA.copyTo(this->m_customBasePath); + DEBUG("Success to set SYSCA flag."); +} + +bool Logic::isSystemCertsUsed(void) const +{ + runtime::File customSysCA(this->m_customBasePath + "/" + + File::getName(path::TANCHOR_SYSCA_PATH)); + + DEBUG("Wheter system certificates use or not : " << customSysCA.exists()); + return customSysCA.exists(); +} + +bool Logic::isSystemCertsModified(void) const +{ + struct stat systemAttr, customAttr; + auto customBundle = this->m_customBundlePath + "/" + + File::getName(path::SYS_BUNDLE_PATH); + + if (::stat(path::SYS_BUNDLE_PATH.c_str(), &systemAttr)) + ThrowErrno(errno, path::SYS_BUNDLE_PATH); + + if (::stat(customBundle.c_str(), &customAttr)) + ThrowErrno(errno, customBundle); + + DEBUG("System bundle mtime : " << ::ctime(&systemAttr.st_mtime) << ", " << + "Custom bundle mtime : " << ::ctime(&customAttr.st_mtime)); + + return systemAttr.st_mtime > customAttr.st_mtime; +} + +void Logic::disassociateNS(void) const +{ + if (::unshare(CLONE_NEWNS)) + ThrowErrno(errno, "Failed to unshare."); + + // convert it to a slave for preventing propagation + if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) + ThrowErrno(errno, "Failed to mount."); + + DEBUG("Success to disassociate namespace."); +} + +void Logic::mountCustomCerts(void) const +{ + if (::mount(this->m_customCertsPath.c_str(), + path::MOUNT_POINT_CERTS.c_str(), + NULL, + MS_BIND, + NULL)) + ThrowErrno(errno, "Failed to mount. src[" + + this->m_customCertsPath + "] to dst[" + + path::MOUNT_POINT_CERTS + "]"); +} + +void Logic::mountCustomBundle(void) const +{ + auto bundle = this->m_customBundlePath + "/" + + File::getName(path::SYS_BUNDLE_PATH); + if (::mount(bundle.c_str(), + path::MOUNT_POINT_BUNDLE.c_str(), + NULL, + MS_BIND, + NULL)) + ThrowErrno(errno, "Failed to mount. src[" + bundle + + "] to dst[" + path::MOUNT_POINT_BUNDLE + "]"); +} + +std::string Logic::getUniqueCertName(const std::string &name) const +{ + int sameNameCnt = 0; + std::string uName; + do { + uName = name + "." + std::to_string(sameNameCnt++); + } while (this->m_customCertNameSet.find(uName) != + this->m_customCertNameSet.end()); + + return uName; +} + +} // namespace tanchor diff --git a/src/logic.hxx b/src/logic.hxx new file mode 100644 index 0000000..acb7e53 --- /dev/null +++ b/src/logic.hxx @@ -0,0 +1,68 @@ +/* + * 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 logic.hxx + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 0.1 + * @brief + */ +#pragma once + +#include +#include +#include + +namespace tanchor { + +class Logic { +public: + explicit Logic(const std::string &appCertsPath, const std::string &basePath); + virtual ~Logic(void) = default; + + Logic(const Logic &) = delete; + Logic(Logic &&) = delete; + Logic &operator=(const Logic &) = delete; + Logic &operator=(Logic &&) = delete; + + void init(void) const; + void deinit(bool isRollback) const; + + void makeCustomCerts(void); + void makeCustomBundle(void); + + bool isAppCertsValid(void) const; + + bool isSystemCertsUsed(void) const; + bool isSystemCertsModified(void) const; + void setSystemCertsUsed(void) const; + + void disassociateNS(void) const; + void mountCustomCerts(void) const; + void mountCustomBundle(void) const; + +private: + std::string getUniqueCertName(const std::string &name) const; + + std::string m_appCertsPath; + std::string m_customBasePath; + std::string m_customCertsPath; + std::string m_customBundlePath; + + std::set m_customCertNameSet; + std::vector m_customCertsData; +}; + +} // namespace tanchor diff --git a/src/trust-anchor.cpp b/src/trust-anchor.cpp index ad09c68..d64c238 100644 --- a/src/trust-anchor.cpp +++ b/src/trust-anchor.cpp @@ -21,40 +21,14 @@ */ #include "tanchor/trust-anchor.hxx" -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include #include -#include "certificate.hxx" +#include "logic.hxx" #include "exception.hxx" +#include "environment.hxx" namespace tanchor { -namespace { - -const std::string BASE_USR_PATH(TANCHOR_USR_DIR); -const std::string BASE_GLOBAL_PATH(TANCHOR_GLOBAL_DIR); -const std::string TANCHOR_BUNDLE_PATH(TANCHOR_BUNDLE); -const std::string TANCHOR_SYSCA_PATH(TANCHOR_SYSCA); -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 NEW_LINE("\n"); - -} // namespace anonymous - class TrustAnchor::Impl { public: explicit Impl(const std::string &packageId, @@ -65,95 +39,41 @@ public: virtual ~Impl(void) = default; int install(bool withSystemCerts) noexcept; - int uninstall(bool isRollback = false) noexcept; - int launch(void); + int uninstall(void) const noexcept; + int launch(void) noexcept; + int rollback(void) const noexcept; private: - void preInstall(void) const; + void preInstall(void); void preLaunch(void); - void linkTo(const std::string &src, const std::string &dst) const; - void makeCustomCerts(bool withSystemCerts); - void makeCustomBundle(bool withSystemCerts); - std::string readLink(const std::string &path) const; - std::string getUniqueHashName(const std::string &hashName) const; - std::string getFileName(const std::string &path) const; - bool isSystemCertsModified(void) const; - void checkFileValidity(const runtime::File &file) const; - - std::string m_packageId; - std::string m_appCertsPath; - uid_t m_uid; - - std::string m_customBasePath; - std::string m_customCertsPath; - std::string m_customBundlePath; - - std::set m_customCertNameSet; - std::vector m_customCertsData; + + Logic m_logic; }; TrustAnchor::Impl::Impl(const std::string &packageId, const std::string &certsDir, uid_t uid) noexcept : - m_packageId(packageId), - m_appCertsPath(certsDir), - m_uid(uid), - m_customBasePath(BASE_USR_PATH + "/" + - std::to_string(static_cast(uid)) + "/" + - packageId), - m_customCertsPath(m_customBasePath + "/certs"), - m_customBundlePath(m_customBasePath + "/bundle"), - m_customCertNameSet(), - m_customCertsData() {} - -TrustAnchor::Impl::Impl(const std::string &packageId, - const std::string &certsDir) noexcept : - m_packageId(packageId), - m_appCertsPath(certsDir), - m_uid(-1), - m_customBasePath(BASE_GLOBAL_PATH + "/" + packageId), - m_customCertsPath(m_customBasePath + "/certs"), - m_customBundlePath(m_customBasePath + "/bundle"), - m_customCertNameSet(), - m_customCertsData() {} - -std::string TrustAnchor::Impl::readLink(const std::string &path) const + m_logic(certsDir, + path::BASE_USR_PATH + "/" + + std::to_string(static_cast(uid)) + "/" + + packageId) { - 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); + INFO("Start tanchor about usr[" << uid << "], app[" << packageId << "]"); } -void TrustAnchor::Impl::linkTo(const std::string &src, - const std::string &dst) const +TrustAnchor::Impl::Impl(const std::string &packageId, + const std::string &certsDir) noexcept : + m_logic(certsDir, path::BASE_GLOBAL_PATH + "/" + packageId) { - errno = 0; - int ret = ::symlink(src.c_str(), dst.c_str()); - if (ret != 0) - ThrowErrno(errno, "Failed to link " + src + " -> " + dst); + INFO("Start tanchor about global app[" << packageId << "]"); } -void TrustAnchor::Impl::preInstall(void) const +void TrustAnchor::Impl::preInstall(void) { - runtime::File customBaseDir(this->m_customBasePath); - if (customBaseDir.exists()) { - WARN("App custom directory is already exist. remove it!"); - customBaseDir.remove(true); - } - customBaseDir.makeDirectory(true); - - runtime::File customCertsDir(this->m_customCertsPath); - customCertsDir.makeDirectory(); - - runtime::File customBundleDir(this->m_customBundlePath); - customBundleDir.makeDirectory(); - - runtime::File appCertsDir(this->m_appCertsPath); - this->checkFileValidity(appCertsDir); - if (!appCertsDir.isDirectory()) - throw std::invalid_argument("[" + this->m_appCertsPath + - "] should be directory."); + this->m_logic.init(); + if (!this->m_logic.isAppCertsValid()) + throw std::invalid_argument("App certs dir should be directory."); DEBUG("Success to pre-install stage."); } @@ -163,219 +83,71 @@ int TrustAnchor::Impl::install(bool withSystemCerts) noexcept this->preInstall(); - this->makeCustomCerts(withSystemCerts); - this->makeCustomBundle(withSystemCerts); + if (withSystemCerts) + this->m_logic.setSystemCertsUsed(); - INFO("Success to install[" << this->m_packageId << - "] to " << this->m_customBasePath); + this->m_logic.makeCustomCerts(); + this->m_logic.makeCustomBundle(); + + INFO("Success to install."); return TRUST_ANCHOR_ERROR_NONE; EXCEPTION_GUARD_END } -int TrustAnchor::Impl::uninstall(bool isRollback) noexcept +int TrustAnchor::Impl::rollback(void) const noexcept { EXCEPTION_GUARD_START - runtime::File customBaseDir(this->m_customBasePath); - if (!customBaseDir.exists() && !isRollback) - throw std::logic_error("There is no installed anchor previous."); - - if (customBaseDir.exists()) - customBaseDir.remove(true); + this->m_logic.deinit(true); - INFO("Success to uninstall. : " << this->m_packageId); + INFO("Success to rollback."); return TRUST_ANCHOR_ERROR_NONE; EXCEPTION_GUARD_END } -void TrustAnchor::Impl::checkFileValidity(const runtime::File &file) const +int TrustAnchor::Impl::uninstall(void) const noexcept { - if (!file.exists()) - ThrowExc(TRUST_ANCHOR_ERROR_NO_SUCH_FILE, - "File [" << file.getPath() << "] does not exist."); - - if (!file.canRead()) - ThrowExc(TRUST_ANCHOR_ERROR_PERMISSION_DENIED, - "No permission to read [" << file.getPath() << "]"); -} - -bool TrustAnchor::Impl::isSystemCertsModified(void) const -{ - struct stat systemAttr, customAttr; - - errno = 0; - if (::stat(SYS_BUNDLE_PATH.c_str(), &systemAttr)) - ThrowErrno(errno, SYS_BUNDLE_PATH); + EXCEPTION_GUARD_START - auto customBundle = this->m_customBundlePath + "/" + - this->getFileName(SYS_BUNDLE_PATH); - if (::stat(customBundle.c_str(), &customAttr)) - ThrowErrno(errno, customBundle); + this->m_logic.deinit(false); - DEBUG("System bundle mtime : " << ::ctime(&systemAttr.st_mtime) << ", " << - "Custom bundle mtime : " << ::ctime(&customAttr.st_mtime)); + INFO("Success to uninstall."); + return TRUST_ANCHOR_ERROR_NONE; - return systemAttr.st_mtime > customAttr.st_mtime; + EXCEPTION_GUARD_END } void TrustAnchor::Impl::preLaunch(void) { - // check whether system certificates use or not - runtime::File customSysCA(this->m_customBasePath + "/" + - this->getFileName(TANCHOR_SYSCA_PATH)); - if (!customSysCA.exists()) { - INFO("This package only use custom certificates."); + if (!this->m_logic.isSystemCertsUsed()) return; - } - INFO("This package use system certificates."); - if (this->isSystemCertsModified()) { - WARN("System certificates be changed. Remake custom bundle."); - this->makeCustomBundle(true); + DEBUG("This package use system certificates."); + if (this->m_logic.isSystemCertsModified()) { + WARN("System certificates be changed. Do re-install for refresh."); + this->install(true); } - - DEBUG("Success to pre-install stage."); + DEBUG("Success to pre-launch stage."); } -int TrustAnchor::Impl::launch() +int TrustAnchor::Impl::launch() noexcept { EXCEPTION_GUARD_START this->preLaunch(); - errno = 0; - // disassociate from the parent namespace - if (::unshare(CLONE_NEWNS)) - ThrowErrno(errno, "Failed to unshare."); - - // convert it to a slave for preventing propagation - if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) - ThrowErrno(errno, "Failed to mount."); - - if (::mount(this->m_customCertsPath.c_str(), - MOUNT_POINT_CERTS.c_str(), - NULL, - MS_BIND, - NULL)) - ThrowErrno(errno, "Failed to mount. src[" + - this->m_customCertsPath + "] to dst[" + - MOUNT_POINT_CERTS + "]"); - - auto bundle = this->m_customBundlePath + "/" + - this->getFileName(SYS_BUNDLE_PATH); - if (::mount(bundle.c_str(), - MOUNT_POINT_BUNDLE.c_str(), - NULL, - MS_BIND, - NULL)) - ThrowErrno(errno, "Failed to mount. src[" + bundle + - "] to dst[" + MOUNT_POINT_BUNDLE + "]"); - - INFO("Success to launch. : " << this->m_packageId); + this->m_logic.disassociateNS(); + this->m_logic.mountCustomCerts(); + this->m_logic.mountCustomBundle(); + + INFO("Success to launch."); return TRUST_ANCHOR_ERROR_NONE; EXCEPTION_GUARD_END } -std::string TrustAnchor::Impl::getFileName(const std::string &path) const -{ - size_t pos = path.rfind('/'); - if (pos == std::string::npos) - throw std::logic_error("Path is wrong. > " + path); - - return path.substr(pos + 1); -} - -std::string TrustAnchor::Impl::getUniqueHashName( - const std::string &hashName) const -{ - int sameFileNameCnt = 0; - std::string uniqueName; - do { - uniqueName = hashName + "." + std::to_string(sameFileNameCnt++); - } while (this->m_customCertNameSet.find(uniqueName) != - this->m_customCertNameSet.end()); - - return uniqueName; -} - -void TrustAnchor::Impl::makeCustomCerts(bool withSystemCerts) -{ - if (withSystemCerts) { - // link system certificates to the custom directory - runtime::DirectoryIterator iter(SYS_CERTS_PATH), end; - while (iter != end) { - linkTo(this->readLink(iter->getPath()), - this->m_customCertsPath + "/" + iter->getName()); - this->m_customCertNameSet.emplace(iter->getName()); - ++iter; - } - DEBUG("Success to migrate system certificates."); - - // copy sysca(withSystemCerts flag) and check at launching time - runtime::File tanchorSysCA(TANCHOR_SYSCA_PATH); - this->checkFileValidity(tanchorSysCA); - tanchorSysCA.copyTo(this->m_customBasePath); - DEBUG("Success to set SYSCA flag."); - } - - // link app certificates to the custom directory as subjectNameHash - runtime::DirectoryIterator iter(this->m_appCertsPath), end; - while (iter != end) { - Certificate cert(iter->getPath()); - std::string hashName = this->getUniqueHashName(cert.getSubjectNameHash()); - linkTo(iter->getPath(), - this->m_customCertsPath + "/" + hashName); - this->m_customCertNameSet.emplace(std::move(hashName)); - - this->m_customCertsData.emplace_back(cert.getCertificateData()); - ++iter; - } -} - -void TrustAnchor::Impl::makeCustomBundle(bool withSystemCerts) -{ - runtime::File customBundle(this->m_customBundlePath + "/" + - this->getFileName(SYS_BUNDLE_PATH)); - if (customBundle.exists()) { - WARN("App custom bundle is already exist. remove it!"); - customBundle.remove(); - } - - DEBUG("Start to migrate previous bundle."); - if (withSystemCerts) { - runtime::File sysBundle(SYS_BUNDLE_PATH); - this->checkFileValidity(sysBundle); - sysBundle.copyTo(this->m_customBundlePath); - } else { - runtime::File tanchorBundle(TANCHOR_BUNDLE_PATH); - this->checkFileValidity(tanchorBundle); - tanchorBundle.copyTo(this->m_customBundlePath); - } - DEBUG("Finish migrating previous bundle."); - - if (this->m_customCertsData.empty()) { - DEBUG("System certificates is changed after TrustAnchor installation."); - runtime::DirectoryIterator iter(this->m_appCertsPath), end; - while (iter != end) { - Certificate cert(iter->getPath()); - this->m_customCertsData.emplace_back(cert.getCertificateData()); - ++iter; - } - } - - DEBUG("Start to add app's certificate to bundle."); - customBundle.open(O_RDWR | O_APPEND); - for (const auto &cert : this->m_customCertsData) { - customBundle.write(cert.c_str(), cert.length()); - customBundle.write(NEW_LINE.c_str(), NEW_LINE.length()); - } - - INFO("Success to make app custom bundle."); -} - TrustAnchor::TrustAnchor(const std::string &packageId, const std::string &certsDir, uid_t uid) noexcept : @@ -396,7 +168,8 @@ int TrustAnchor::install(bool withSystemCerts) noexcept if (ret != TRUST_ANCHOR_ERROR_NONE) { ERROR("Failed to intall ACTA. Remove custom directory for rollback."); - this->m_pImpl->uninstall(true); + if (this->m_pImpl->rollback() != TRUST_ANCHOR_ERROR_NONE) + ERROR("Failed to rollback ACTA."); } return ret; diff --git a/tests/script/pre-test.sh.in b/tests/script/pre-test.sh.in index d98fce6..9fbdc21 100755 --- a/tests/script/pre-test.sh.in +++ b/tests/script/pre-test.sh.in @@ -24,10 +24,11 @@ INSTALLER=@BIN_INSTALL_DIR@/@TEST_INSTALLER@ LAUNCHER=@BIN_INSTALL_DIR@/@TEST_LAUNCHER@ CLAUNCHER=@BIN_INSTALL_DIR@/@TEST_CLAUNCHER@ INTERNAL=@BIN_INSTALL_DIR@/@TEST_INTERNAL@ +SSL=@BIN_INSTALL_DIR@/@TEST_SSL@ CURL=@BIN_INSTALL_DIR@/curl -declare -a TESTS=("$INSTALLER $LAUNCHER $CLAUNCHER $INTERNAL") +declare -a TESTS=("$INSTALLER $LAUNCHER $CLAUNCHER $INTERNAL $SSL") for t in "${TESTS[@]}" do @@ -44,3 +45,4 @@ chsmack -e "@SMACK_LABEL@" $CURL # launch() needs CAP_SYS_ADMIN setcap cap_sys_admin+ep $LAUNCHER setcap cap_sys_admin+ep $CLAUNCHER +setcap cap_sys_admin+ep $SSL -- 2.34.1