Refactor implementation of TrustAnchor 33/132433/3
authorsangwan.kwon <sangwan.kwon@samsung.com>
Fri, 2 Jun 2017 08:30:47 +0000 (17:30 +0900)
committersangwan.kwon <sangwan.kwon@samsung.com>
Wed, 7 Jun 2017 08:25:48 +0000 (17:25 +0900)
- According to class diagram v2

Change-Id: I31c920ff155f96981e6b6ba838d7ccd07dabd459
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
packaging/trust-anchor.spec
src/CMakeLists.txt
src/environment.hxx [new file with mode: 0644]
src/file-system.cpp [new file with mode: 0644]
src/file-system.hxx [new file with mode: 0644]
src/logic.cpp [new file with mode: 0644]
src/logic.hxx [new file with mode: 0644]
src/trust-anchor.cpp
tests/script/pre-test.sh.in

index cea4289398cf2f784cfb062a5837d804c8745adf..538c884c7072eeacfd5b725e41fae60430e44ff6 100644 (file)
@@ -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
index 2de205d25c0336d954dde1acc73f13efcaf371e6..a42fd7b90667019c36054e2a07f9e98957ab7b62 100644 (file)
@@ -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 (file)
index 0000000..1db8beb
--- /dev/null
@@ -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 (file)
index 0000000..5eaa2f7
--- /dev/null
@@ -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 <climits>
+#include <cerrno>
+#include <unistd.h>
+
+#include <vector>
+
+#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<char> 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 (file)
index 0000000..0e3dcfa
--- /dev/null
@@ -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 <string>
+
+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 (file)
index 0000000..d7f7d98
--- /dev/null
@@ -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 <ctime>
+#include <cerrno>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <klay/filesystem.h>
+#include <klay/audit/logger.h>
+
+#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 (file)
index 0000000..acb7e53
--- /dev/null
@@ -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 <string>
+#include <set>
+#include <vector>
+
+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<std::string> m_customCertNameSet;
+       std::vector<std::string> m_customCertsData;
+};
+
+} // namespace tanchor
index ad09c68222ce96f41b7addc345f19300474c9b76..d64c238f592a0a087a49a5ce7678743f20464171 100644 (file)
  */
 #include "tanchor/trust-anchor.hxx"
 
-#include <climits>
-#include <cerrno>
-#include <ctime>
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <set>
-#include <vector>
-
-#include <klay/filesystem.h>
 #include <klay/audit/logger.h>
 
-#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<std::string> m_customCertNameSet;
-       std::vector<std::string> 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<int>(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<int>(uid)) + "/" +
+                       packageId)
 {
-       std::vector<char> 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;
index d98fce61158684f1c01e619f600d7e2e330bedb1..9fbdc21b74e661830cc83606fbd6bbf4b0a7af93 100755 (executable)
@@ -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