Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / security_registration.cc
index bc265fc..1204e3d 100644 (file)
@@ -4,9 +4,6 @@
 
 #include "common/security_registration.h"
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/format.hpp>
-
 #include <unistd.h>
 #include <sys/types.h>
 #include <manifest_parser/utils/logging.h>
 #include <utility>
 #include <vector>
 #include <algorithm>
+#include <functional>
 
-#include "common/pkgmgr_query.h"
+#include "common/utils/pkgmgr_query.h"
 #include "common/privileges.h"
 #include "common/utils/file_util.h"
 #include "common/utils/glist_range.h"
 
-namespace bf = boost::filesystem;
+namespace fs = std::filesystem;
 namespace ci = common_installer;
 
 namespace {
 
+using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
+
 const std::vector<std::pair<const char*,
                             app_install_path_type>> kSecurityPolicies = {
-  {"/", SECURITY_MANAGER_PATH_PUBLIC_RO},
+  {".", SECURITY_MANAGER_PATH_PUBLIC_RO},
   {"bin", SECURITY_MANAGER_PATH_RO},
   {"data", SECURITY_MANAGER_PATH_RW},
   {"cache", SECURITY_MANAGER_PATH_RW},
   {"lib", SECURITY_MANAGER_PATH_RO},
   {"res", SECURITY_MANAGER_PATH_RO},
+  {"res/global", SECURITY_MANAGER_PATH_PUBLIC_RO},
+  {"res/allowed", SECURITY_MANAGER_PATH_PUBLIC_RO},
   {"shared", SECURITY_MANAGER_PATH_PUBLIC_RO},
   {"shared/data", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
   {"shared/cache", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
@@ -46,280 +48,401 @@ const std::vector<std::pair<const char*,
 };
 
 const std::vector<std::pair<const char*,
-                            app_install_path_type>> kSecurityRWOnlyPolicies = {
-  {"data", SECURITY_MANAGER_PATH_RW},
-  {"cache", SECURITY_MANAGER_PATH_RW},
-  {"shared", SECURITY_MANAGER_PATH_PUBLIC_RO},
-  {"shared/data", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
-  {"shared/cache", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
-  {"shared/trusted", SECURITY_MANAGER_PATH_TRUSTED_RW}
+                app_install_path_type>> kSecurityPoliciesExternalOnly = {
+  {"bin", SECURITY_MANAGER_PATH_RO},
+  {"lib", SECURITY_MANAGER_PATH_RO},
+  {"res", SECURITY_MANAGER_PATH_RO},
+  {".mmc", SECURITY_MANAGER_PATH_RO}
 };
 
 const std::vector<std::pair<const char*, app_install_type>> kPathPolicies = {
   {tzplatform_getenv(TZ_SYS_HOME), SM_APP_INSTALL_LOCAL},
   {tzplatform_getenv(TZ_SYS_RW_APP), SM_APP_INSTALL_GLOBAL},
   {tzplatform_getenv(TZ_SYS_RO_APP), SM_APP_INSTALL_PRELOADED},
-  {tzplatform_mkpath(TZ_SYS_RO_ETC, "skel"), SM_APP_INSTALL_PRELOADED},
+  {tzplatform_mkpath(TZ_SYS_ETC, "skel"), SM_APP_INSTALL_PRELOADED},
 };
 
-bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
-    const std::string& author_id, const std::string& api_version,
-    const boost::filesystem::path& path,
-    uid_t uid, const std::vector<std::string>& privileges,
-    app_inst_req* req, bool cross_app_rules, std::string* error_message) {
-  if (app_id.empty() || pkg_id.empty()) {
-    LOG(ERROR) << "Appid or pkgid is empty. Both values must be set";
-    return false;
-  }
+void SetErrorMessage(std::string* error_message, int error) {
+  std::string errnum = std::to_string(error);
+  *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
+  *error_message += ":<" + errnum + ">";
+}
 
-  int error = security_manager_app_inst_req_set_app_id(req,
-      app_id.c_str());
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+class SecurityContextRequest {
+ public:
+  SecurityContextRequest(): req_(nullptr), app_idx_(0) {
+    int error = security_manager_app_inst_req_new(&req_);
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        LOG(ERROR)
+            << "Failed while calling security_manager_app_inst_req_new "
+            << "(error code: " << error << ")";
+        SetErrorMessage(&error_message_, error);
+        req_ = NULL;
+      }
   }
-
-  error = security_manager_app_inst_req_set_pkg_id(req,
-      pkg_id.c_str());
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+  ~SecurityContextRequest() {
+    if (IsValid())
+      security_manager_app_inst_req_free(req_);
   }
-
-  error = security_manager_app_inst_req_set_uid(req, uid);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+  bool IsValid() const {
+    return req_ != NULL;
   }
+  bool PrepareBasic(const std::string& pkg_id, uid_t uid,
+      const std::string& type) {
+    if (pkg_id.empty() || type.empty()) {
+      LOG(ERROR) << "Invalid parameter";
+      return false;
+    }
+    int error = security_manager_app_inst_req_set_pkg_id(req_, pkg_id.c_str());
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    error = security_manager_app_inst_req_set_uid(req_, uid);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+
+    pkg_type pkgtype = SM_PKG_TYPE_NONE;
+    if (type == "tpk")
+      pkgtype = SM_PKG_TYPE_CORE;
+    else if (type == "wgt")
+      pkgtype = SM_PKG_TYPE_WRT;
 
-  if (cross_app_rules) {
-    error = security_manager_app_inst_req_set_hybrid(req);
+    error = security_manager_app_inst_req_set_pkg_type(req_, pkgtype);
     if (error != SECURITY_MANAGER_SUCCESS) {
-      std::string errnum = boost::str(boost::format("%d") % error);
-      *error_message =
-          security_manager_strerror(static_cast<lib_retcode>(error));
-      *error_message += ":<" + errnum + ">";
+      SetErrorMessage(&error_message_, error);
       return false;
     }
+    return true;
+  }
+
+  bool PrepareAdditional(const std::string& author_id,
+      const std::string& api_version,
+      const std::filesystem::path& path,
+      bool cross_app_rules) {
+    if (cross_app_rules) {
+      int error = security_manager_app_inst_req_set_hybrid(req_);
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    if (!api_version.empty()) {
+      int error = security_manager_app_inst_req_set_target_version(req_,
+          api_version.c_str());
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    if (!author_id.empty()) {
+      int error = security_manager_app_inst_req_set_author_id(req_,
+          author_id.c_str());
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    if (!path.empty()) {
+      app_install_type type = SM_APP_INSTALL_NONE;
+      for (auto& policy : kPathPolicies) {
+        fs::path root = fs::path(policy.first);
+        if (ci::IsSubDir(path, root)) {
+          type = policy.second;
+          break;
+        }
+      }
+      if (type == SM_APP_INSTALL_NONE) {
+        LOG(ERROR) << "Unexpected path: " << path;
+        return false;
+      }
+
+      LOG(INFO) << "install_type(" << type << ")";
+      int error = security_manager_app_inst_req_set_install_type(req_, type);
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    return true;
   }
 
-  if (!api_version.empty()) {
-    error = security_manager_app_inst_req_set_target_version(req,
-        api_version.c_str());
+  bool PreparePrivilegeLevel(ci::PrivilegeLevel priv_level) {
+    pkg_privilege_level level = (pkg_privilege_level)priv_level;
+    int error = security_manager_app_inst_req_set_pkg_privilege_level(
+        req_, level);
     if (error != SECURITY_MANAGER_SUCCESS) {
-      std::string errnum = boost::str(boost::format("%d") % error);
-      *error_message =
-          security_manager_strerror(static_cast<lib_retcode>(error));
-      *error_message += ":<" + errnum + ">";
+      SetErrorMessage(&error_message_, error);
       return false;
     }
+    return true;
   }
 
-  if (!author_id.empty()) {
-    error = security_manager_app_inst_req_set_author_id(req, author_id.c_str());
-    if (error != SECURITY_MANAGER_SUCCESS) {
-      std::string errnum = boost::str(boost::format("%d") % error);
-      *error_message =
-          security_manager_strerror(static_cast<lib_retcode>(error));
-      *error_message += ":<" + errnum + ">";
+  bool PrepareAppWithPrivileges(const std::string& app_id,
+      const std::vector<std::string>& privileges,
+      const AppDefinedPrivInfo& appdef_privileges,
+      const AppDefinedPrivInfo& provides_appdef_privileges) {
+    if (!PrepareApp(app_id))
       return false;
+    return PrepareAppPrivileges(privileges, appdef_privileges,
+        provides_appdef_privileges);
+  }
+
+  bool PrepareAppPrivileges(const std::vector<std::string>& privileges,
+      const AppDefinedPrivInfo& appdef_privileges,
+      const AppDefinedPrivInfo& provides_appdef_privileges) {
+    for (auto& priv : privileges) {
+      int error = security_manager_app_inst_req_add_privilege(req_,
+                                                              priv.c_str());
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    for (auto& priv : appdef_privileges) {
+      int error = security_manager_app_inst_req_add_client_privilege(
+          req_, priv.first.c_str(), priv.second.c_str());
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
+    }
+    // only one app can provide appdefined privileges
+    if (app_idx_ > 1)
+      return true;
+    for (auto& priv : provides_appdef_privileges) {
+      auto privilege_type = !priv.second.empty() ?
+                            SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED :
+                            SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED;
+      int error = security_manager_app_inst_req_add_app_defined_privilege(req_,
+          priv.first.c_str(), privilege_type, priv.second.c_str());
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
+      }
     }
+    return true;
   }
 
-  if (!path.empty()) {
-    app_install_type type = SM_APP_INSTALL_NONE;
-    for (auto& policy : kPathPolicies) {
-      bf::path root = bf::path(policy.first);
-      if (ci::IsSubDir(path, root)) {
-        type = policy.second;
-        break;
+  bool PrepareApp(const std::string& app_id) {
+    if (app_id.empty()) {
+      LOG(ERROR) << "Appid is empty.";
+      return false;
+    }
+    // req_->apps.emplace_back();
+    if (app_idx_ > 0) {
+      int error = security_manager_app_inst_req_next(req_);
+      if (error != SECURITY_MANAGER_SUCCESS) {
+        SetErrorMessage(&error_message_, error);
+        return false;
       }
     }
-    if (type == SM_APP_INSTALL_NONE) {
-      LOG(ERROR) << "Unexpected path: " << path;
+    // req_->apps.back().id = ...
+    int error = security_manager_app_inst_req_set_app_id(req_, app_id.c_str());
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
       return false;
     }
+    ++app_idx_;
+    return true;
+  }
 
-    LOG(INFO) << "install_type(" << type << ")";
-    error = security_manager_app_inst_req_set_install_type(req, type);
+  bool Install() {
+    int error = security_manager_app_update(req_);
     if (error != SECURITY_MANAGER_SUCCESS) {
-      std::string errnum = boost::str(boost::format("%d") % error);
-      *error_message =
-          security_manager_strerror(static_cast<lib_retcode>(error));
-      *error_message += ":<" + errnum + ">";
+      LOG(ERROR) << "Failed while calling  security_manager_app_update failed "
+                 << "(error code: " << error << ")";
+      SetErrorMessage(&error_message_, error);
       return false;
     }
+    return true;
   }
 
-  for (auto& priv : privileges) {
-    security_manager_app_inst_req_add_privilege(req, priv.c_str());
+  bool Uninstall() {
+    int error = security_manager_app_uninstall(req_);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      LOG(ERROR) << "Failed while calling  security_manager_app_uninstall "
+                 << "failed (error code: " << error << ")";
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    return true;
   }
-  return true;
-}
 
-bool PreparePathRequest(const std::string& pkg_id,
-    const boost::filesystem::path& path, uid_t uid, path_req* req,
-    bool is_readonly_pkg, bool rwpath_only, std::string* error_message) {
-  if (pkg_id.empty() || path.empty()) {
-    LOG(ERROR) << "Pkgid or path is empty. Both values must be set";
-    return false;
+  const std::string& ErrorMessage() const {
+    return error_message_;
   }
 
-  int error = security_manager_path_req_set_pkg_id(req, pkg_id.c_str());
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
-  }
+ private:
+  app_inst_req* req_;
+  uint app_idx_;
+  std::string error_message_;
+};
 
-  error = security_manager_path_req_set_uid(req, uid);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+class SecurityContextPathRequest {
+ public:
+  SecurityContextPathRequest() {
+    int error = security_manager_path_req_new(&req_);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      LOG(ERROR)
+          << "Failed while calling security_manager_path_req_new failed "
+          << "(error code: " << error << ")";
+      SetErrorMessage(&error_message_, error);
+      req_ = NULL;
+    }
   }
 
-  app_install_type type = SM_APP_INSTALL_NONE;
-  for (auto& policy : kPathPolicies) {
-    bf::path root = bf::path(policy.first);
-    if (ci::IsSubDir(path, root)) {
-      type = policy.second;
-      break;
-    }
+  ~SecurityContextPathRequest() {
+    if (IsValid())
+      security_manager_path_req_free(req_);
   }
-  if (type == SM_APP_INSTALL_NONE) {
-    LOG(ERROR) << "Unexpected path: " << path;
-    return false;
+
+  bool IsValid() {
+    return req_ != NULL;
   }
-  // When registering skel dir on global installation mode
-  if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
-    type = SM_APP_INSTALL_GLOBAL;
 
-  error = security_manager_path_req_set_install_type(req, type);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message =
-        security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+  bool Prepare(const std::string& pkg_id, uid_t uid) {
+    if (pkg_id.empty()) {
+      LOG(ERROR) << "Pkgid is empty. This value must be set";
+      return false;
+    }
+    int error = security_manager_path_req_set_pkg_id(req_, pkg_id.c_str());
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    error = security_manager_path_req_set_uid(req_, uid);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    return true;
   }
 
-  for (auto& policy : (rwpath_only? kSecurityRWOnlyPolicies :
-                                    kSecurityPolicies)) {
-    bf::path subpath = path / policy.first;
-    if (bf::exists(subpath)) {
-      if (bf::is_symlink(symlink_status(subpath))) {
-        LOG(DEBUG) << "Path " << subpath << " is a symlink."
-                   << "Path will not be registered";
-        continue;
+  bool PreparePath(const std::string& pkg_type,
+      const std::filesystem::path& path, bool is_readonly_pkg,
+      bool is_extonly) {
+    if (path.empty()) {
+      LOG(ERROR) << "Path is empty. This value must be set";
+      return false;
+    }
+    app_install_type type = SM_APP_INSTALL_NONE;
+    for (auto& policy : kPathPolicies) {
+      fs::path root = fs::path(policy.first);
+      if (ci::IsSubDir(path, root)) {
+        type = policy.second;
+        break;
+      }
+    }
+    if (type == SM_APP_INSTALL_NONE) {
+      LOG(ERROR) << "Unexpected path: " << path;
+      return false;
+    }
+    // When registering skel dir on global installation mode
+    if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
+      type = SM_APP_INSTALL_GLOBAL;
+
+    int error = security_manager_path_req_set_install_type(req_, type);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    std::vector<std::pair<const char*, app_install_path_type>> policies;
+    if (is_extonly)
+      policies = kSecurityPoliciesExternalOnly;
+    else
+      policies = kSecurityPolicies;
+    for (auto& policy : policies) {
+      fs::path subpath = path / policy.first;
+      if (is_extonly) {
+        // Now, this is for legacy migraton.
+        // do not try to access any file before changing label,
+        // this wil cause a exception from smack denial.
+        std::string subdir(policy.first);
+        if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
+          continue;
+      } else {
+        if (!fs::exists(subpath))
+          continue;
+        if (fs::is_symlink(symlink_status(subpath)) &&
+            policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO) {
+          LOG(DEBUG) << "Path " << subpath << " is a symlink."
+                     << "Path will not be registered";
+          continue;
+        }
       }
-      error = security_manager_path_req_add_path(req, subpath.c_str(),
+      error = security_manager_path_req_add_path(req_, subpath.c_str(),
           policy.second);
       if (error != SECURITY_MANAGER_SUCCESS) {
-        std::string errnum = boost::str(boost::format("%d") % error);
-        *error_message =
-                  security_manager_strerror(static_cast<lib_retcode>(error));
-        *error_message += ":<" + errnum + ">";
+        SetErrorMessage(&error_message_, error);
         return false;
       }
+
+      // this is for lib rpk installation. set public RO for contents only.
+      if (pkg_type == "rpk" && std::string(policy.first) == "lib") {
+        for (fs::directory_iterator iter(subpath);
+            iter != fs::directory_iterator(); ++iter) {
+          error = security_manager_path_req_add_path(req_,
+              iter->path().string().c_str(), SECURITY_MANAGER_PATH_PUBLIC_RO);
+          if (error!= SECURITY_MANAGER_SUCCESS) {
+            SetErrorMessage(&error_message_, error);
+            return false;
+          }
+        }
+      }
     }
+    return true;
   }
 
-  return true;
-}
-
-}  // namespace
-
-namespace common_installer {
-
-bool RegisterSecurityContext(const std::string& app_id,
-    const std::string& pkg_id, const std::string& author_id,
-    const std::string& api_version, const boost::filesystem::path& path,
-    uid_t uid, const std::vector<std::string>& privileges,
-    bool cross_app_rules, std::string* error_message) {
-  app_inst_req* req;
-
-  int error = security_manager_app_inst_req_new(&req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR)
-        << "Failed while calling security_manager_app_inst_req_new failed "
-        << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
+  bool Register() {
+    int error = security_manager_paths_register(req_);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      LOG(ERROR) << "Failed while calling  security_manager_paths_register "
+                 << "failed (error code: " << error << ")";
+      SetErrorMessage(&error_message_, error);
+      return false;
+    }
+    return true;
   }
 
-  if (!PrepareRequest(app_id, pkg_id, author_id, api_version, path, uid,
-      privileges, req, cross_app_rules, error_message)) {
-    LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
-    security_manager_app_inst_req_free(req);
-    return false;
+  const std::string& ErrorMessage() const {
+    return error_message_;
   }
 
-  error = security_manager_app_install(req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR) << "Failed while calling security_manager_app_install failed "
-               << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    security_manager_app_inst_req_free(req);
-    return false;
-  }
+ private:
+  path_req* req_;
+  std::string error_message_;
+};
 
-  security_manager_app_inst_req_free(req);
-  return true;
-}
+}  // namespace
 
-bool UnregisterSecurityContext(const std::string& app_id,
-    const std::string& pkg_id, uid_t uid, std::string* error_message) {
-  app_inst_req* req;
-
-  int error = security_manager_app_inst_req_new(&req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR) << "Failed while calling security_manager_app_inst_req_new  "
-               << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    return false;
-  }
+namespace common_installer {
 
-  if (!PrepareRequest(app_id, pkg_id, std::string(), std::string(),
-                      bf::path(), uid, {}, req, false, error_message)) {
-    LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
-    security_manager_app_inst_req_free(req);
-    return false;
-  }
+void PrepareAppDefinedPrivilegeData(GList *privileges,
+    AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
 
-  error = security_manager_app_uninstall(req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR) << "Failed while calling  security_manager_app_uninstall failed "
-               << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    security_manager_app_inst_req_free(req);
-    return false;
+  for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
+    if (strcmp(priv->type, kWebPrivilegeType) == 0)
+      wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
+          priv->license : std::string()));
+    else
+      tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
+          priv->license : std::string()));
   }
-
-  security_manager_app_inst_req_free(req);
-  return true;
 }
 
-bool RegisterSecurityContextForManifest(
-    const std::string& pkg_id, const boost::filesystem::path& path, uid_t uid,
-    common_installer::CertificateInfo* cert_info, manifest_x* manifest,
-    bool cross_app_rules, std::string* error_message) {
+bool RegisterSecurityContextForManifest(const ci::InstallerContext* context,
+    std::string* error_message) {
+  std::string pkg_id = context->pkgid.get();
+  std::string pkg_type = context->pkg_type.get();
+  fs::path path = context->GetPkgPath();
+  uid_t uid = context->uid.get();
+  const ci::CertificateInfo* cert_info = &(context->certificate_info.get());
+  manifest_x* manifest = context->manifest_data.get();
+  bool cross_app_rules = context->cross_app_rules.get();
+
   // Although application framework hold list of privilege per package, there
   // is situation where we need to filter privileges. This data model doesn't
   // cover hybrid apps well where native privileges should be granted only to
@@ -332,122 +455,163 @@ bool RegisterSecurityContextForManifest(
     else
       tpk_priv_vec.emplace_back(priv->value);
   }
+  AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
+  AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
+
+  PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
+      &tpk_appdef_vec, &wgt_appdef_vec);
+  PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
+      &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
+
+  SecurityContextRequest req;
+  if (!req.IsValid()) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+  if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+  if (!req.PrepareAdditional(cert_info->author_id.get(), manifest->api_version,
+      path, cross_app_rules)) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+
+  if (!req.PreparePrivilegeLevel(context->privilege_level.get())) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+
   for (application_x* app : GListRange<application_x*>(manifest->application)) {
     if (!app->appid) {
       return false;
     }
 
     bool is_web_priv = strcmp(app->type, "webapp") == 0;
-    if (!RegisterSecurityContext(app->appid, pkg_id, cert_info->author_id.get(),
-        manifest->api_version, path, uid,
+    if (!req.PrepareAppWithPrivileges(app->appid,
         is_web_priv ? wgt_priv_vec : tpk_priv_vec,
-        cross_app_rules, error_message)) {
+        is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
+        is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec)) {
+      *error_message = req.ErrorMessage();
+      return false;
+    }
+  }
+
+  if (!manifest->application)
+    req.PrepareApp(pkg_id);
+
+  bool result = req.Install();
+  *error_message = req.ErrorMessage();
+  return result;
+}
+
+static bool UnregisterSecurityContext(const std::string& pkg_id,
+    const std::string& pkg_type,  uid_t uid,
+    const std::vector<std::string>& appids, std::string* error_message) {
+  SecurityContextRequest req;
+  if (!req.IsValid()) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+  if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
+    *error_message = req.ErrorMessage();
+    return false;
+  }
+
+  for (const auto& appid : appids) {
+    if (!req.PrepareApp(appid)) {
       return false;
     }
   }
-  return true;
+
+  if (appids.empty())
+    req.PrepareApp(pkg_id);
+
+  bool result = req.Uninstall();
+  *error_message = req.ErrorMessage();
+  return result;
 }
 
 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
-    uid_t uid, manifest_x* manifest, std::string* error_message) {
+    const std::string& pkg_type, uid_t uid, manifest_x* manifest,
+    std::string* error_message) {
+  std::vector<std::string> appids;
   for (application_x* app : GListRange<application_x*>(manifest->application)) {
     if (!app->appid) {
       return false;
     }
-    if (!UnregisterSecurityContext(app->appid, pkg_id, uid, error_message)) {
-      return false;
-    }
+    appids.emplace_back(app->appid);
   }
-  return true;
+  return UnregisterSecurityContext(pkg_id, pkg_type, uid,
+      appids, error_message);
 }
 
 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
-    uid_t uid, std::string* error_message) {
+    const std::string& pkg_type, uid_t uid,
+    std::string* error_message, bool ignore_data_absence) {
   std::vector<std::string> appids;
-  if (!QueryAppidsForPkgId(pkg_id, &appids, uid))
-    return false;
-  for (auto& appid : appids) {
-    if (!UnregisterSecurityContext(appid, pkg_id, uid, error_message)) {
-      return false;
-    }
-  }
-  return true;
+  ci::PkgQueryInterface pkg_query(pkg_id, uid);
+  if (!pkg_query.AppidsForPkgId(&appids))
+    return ignore_data_absence;
+  return UnregisterSecurityContext(pkg_id, pkg_type, uid,
+      appids, error_message);
 }
 
 bool RegisterSecurityContextForPath(const std::string &pkg_id,
-    const boost::filesystem::path& path, uid_t uid,
-    bool is_readonly_pkg, std::string* error_message) {
-  path_req* req;
-  int error = security_manager_path_req_new(&req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR)
-        << "Failed while calling security_manager_path_req_new failed "
-        << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
+    const std::string& pkg_type, const std::filesystem::path& path,
+    uid_t uid, bool is_readonly_pkg, std::string* error_message) {
+  SecurityContextPathRequest req;
+  if (!req.IsValid()) {
+    *error_message = req.ErrorMessage();
     return false;
   }
-
-  if (!PreparePathRequest(pkg_id, path, uid, req, is_readonly_pkg,
-                          false, error_message)) {
-    LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
-    security_manager_path_req_free(req);
+  if (!req.Prepare(pkg_id, uid)) {
+    *error_message = req.ErrorMessage();
     return false;
   }
-
-  error = security_manager_paths_register(req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
-               << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    security_manager_path_req_free(req);
+  if (!req.PreparePath(pkg_type, path, is_readonly_pkg, false)) {
+    *error_message = req.ErrorMessage();
     return false;
   }
-
-  security_manager_path_req_free(req);
-
-  return true;
+  bool result = req.Register();
+  *error_message = req.ErrorMessage();
+  return result;
 }
 
-bool RegisterSecurityContextForRWOnlyPath(const std::string &pkg_id,
-    const boost::filesystem::path& path, uid_t uid,
-    bool is_readonly_pkg, std::string* error_message) {
-  path_req* req;
-  int error = security_manager_path_req_new(&req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR)
-        << "Failed while calling security_manager_path_req_new failed "
-        << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
+bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
+    const std::string &pkg_type, const std::filesystem::path& path,
+    uid_t uid, std::string* error_message) {
+  SecurityContextPathRequest req;
+  if (!req.IsValid()) {
+    *error_message = req.ErrorMessage();
     return false;
   }
-
-  if (!PreparePathRequest(pkg_id, path, uid, req, is_readonly_pkg,
-                          true, error_message)) {
-    LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
-    security_manager_path_req_free(req);
+  if (!req.Prepare(pkg_id, uid)) {
+    *error_message = req.ErrorMessage();
     return false;
   }
-
-  error = security_manager_paths_register(req);
-  if (error != SECURITY_MANAGER_SUCCESS) {
-    LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
-               << "(error code: " << error << ")";
-    std::string errnum = boost::str(boost::format("%d") % error);
-    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
-    *error_message += ":<" + errnum + ">";
-    security_manager_path_req_free(req);
+  if (!req.PreparePath(pkg_type, path, false, true)) {
+    *error_message = req.ErrorMessage();
     return false;
   }
+  bool result = req.Register();
+  *error_message = req.ErrorMessage();
+  return result;
+}
+
+bool HasOwnerRwOtherRoPaths(const std::filesystem::path& path) {
+  for (auto& policy : kSecurityPolicies) {
+    if (policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO)
+      continue;
 
-  security_manager_path_req_free(req);
+    fs::path subpath = path / policy.first;
+    LOG(ERROR) << "subpath : " << subpath;
+    if (fs::exists(subpath))
+      return true;
+  }
 
-  return true;
+  return false;
 }
 
 }  // namespace common_installer