Save author certificate to pkgmgr database 49/41949/3
authorTomasz Iwanek <t.iwanek@samsung.com>
Fri, 12 Jun 2015 09:01:12 +0000 (11:01 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Mon, 29 Jun 2015 12:48:07 +0000 (14:48 +0200)
Registration and unregistation of package was moved to
pkgmgr_registration.cc.

Change-Id: I80c838983b16302b7bea1d2acfe4d271e8732901

src/common/CMakeLists.txt
src/common/context_installer.h
src/common/pkgmgr_registration.cc [new file with mode: 0644]
src/common/pkgmgr_registration.h [new file with mode: 0644]
src/common/step/step_check_signature.cc
src/common/step/step_check_signature.h
src/common/step/step_register_app.cc
src/common/step/step_register_app.h
src/common/step/step_unregister_app.cc
src/common/step/step_update_app.cc
src/unit_tests/signature_unittest.cc

index a9ce29d..cbbf1dd 100644 (file)
@@ -3,6 +3,7 @@ SET(SRCS
   app_installer.cc
   context_installer.cc
   pkgmgr_interface.cc
+  pkgmgr_registration.cc
   pkgmgr_signal.cc
   security_registration.cc
   step/step_backup_icons.cc
index 55e597a..cd18579 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <unistd.h>
 #include <sys/types.h>
+#include <vcore/Certificate.h>
 
 #include <memory>
 #include <string>
@@ -32,6 +33,11 @@ class BackendData {
   virtual ~BackendData() { }
 };
 
+class CertificateInfo {
+ public:
+  Property<ValidationCore::CertificatePtr> author_certificate;
+};
+
 enum class PrivilegeLevel : int {
   UNTRUSTED  = 0,
   PUBLIC     = 1,
@@ -95,6 +101,9 @@ class ContextInstaller {
 
   // request privilege level of package
   Property<PrivilegeLevel> privilege_level;
+
+  // certificate information
+  Property<CertificateInfo> certificate_info;
 };
 
 boost::filesystem::path GetBackupPathForPackagePath(
diff --git a/src/common/pkgmgr_registration.cc b/src/common/pkgmgr_registration.cc
new file mode 100644 (file)
index 0000000..aedebd2
--- /dev/null
@@ -0,0 +1,161 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/pkgmgr_registration.h"
+
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer.h>
+#include <tzplatform_config.h>
+
+#include "common/utils/logging.h"
+
+namespace bf = boost::filesystem;
+
+namespace {
+
+// TODO(sdi2): Check if data->removable is correctly setting
+// during parsing step.
+// Same check should be done for preload field.
+
+// Having a specific step to implement a installer commandline tool
+// for image build could be usefull also.
+const char* const kAppinstTags[] = {"removable=true", nullptr, };
+
+bool RegisterAuthorCertificate(
+    const common_installer::CertificateInfo& cert_info,
+    const std::string& pkgid, uid_t uid) {
+  pkgmgr_instcertinfo_h handle;
+  if (pkgmgr_installer_create_certinfo_set_handle(&handle) < 0) {
+    LOG(ERROR) << "Cannot create pkgmgr_instcertinfo_h";
+    return false;
+  }
+
+  const auto& cert = cert_info.author_certificate.get();
+  pkgmgr_instcert_type inst_cert_type = PM_SET_AUTHOR_ROOT_CERT;
+  if (cert->isRootCert()) {
+    inst_cert_type = PM_SET_AUTHOR_ROOT_CERT;
+  } else if (cert->isCA()) {
+    inst_cert_type = PM_SET_AUTHOR_INTERMEDIATE_CERT;
+  } else {
+    inst_cert_type = PM_SET_AUTHOR_SIGNER_CERT;
+  }
+
+  if (pkgmgr_installer_set_cert_value(handle, inst_cert_type,
+      const_cast<char*>(cert->getBase64().c_str())) < 0) {
+    pkgmgr_installer_destroy_certinfo_set_handle(handle);
+    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
+    return false;
+  }
+
+  if (pkgmgr_installer_save_certinfo(pkgid.c_str(), handle, uid) < 0) {
+    pkgmgr_installer_destroy_certinfo_set_handle(handle);
+    LOG(ERROR) << "Failed to save certificate information";
+    return false;
+  }
+
+  pkgmgr_installer_destroy_certinfo_set_handle(handle);
+  return true;
+}
+
+}  // anonymous namespace
+
+namespace common_installer {
+
+bool RegisterAppInPkgmgr(const bf::path& xml_path,
+                         const std::string& pkgid,
+                         const CertificateInfo& cert_info, uid_t uid) {
+  int ret = uid != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
+      pkgmgr_parser_parse_usr_manifest_for_installation(
+          xml_path.c_str(), uid, const_cast<char* const*>(kAppinstTags)) :
+      pkgmgr_parser_parse_manifest_for_installation(
+          xml_path.c_str(), const_cast<char* const*>(kAppinstTags));
+  if (ret) {
+    LOG(ERROR) << "Failed to unregister package: " << xml_path;
+    return false;
+  }
+
+  if (!!cert_info.author_certificate.get()) {
+    if (!RegisterAuthorCertificate(cert_info, pkgid, uid)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool UpgradeAppInPkgmgr(const bf::path& xml_path, const std::string& pkgid,
+                        const CertificateInfo& cert_info, uid_t uid) {
+  int ret = uid != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
+       pkgmgr_parser_parse_usr_manifest_for_upgrade(
+           xml_path.string().c_str(), uid,
+           const_cast<char* const*>(kAppinstTags)) :
+       pkgmgr_parser_parse_manifest_for_upgrade(
+           xml_path.string().c_str(),
+           const_cast<char* const*>(kAppinstTags));
+
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to upgrade package: " << xml_path;
+    return false;
+  }
+
+  (void) pkgmgr_installer_delete_certinfo(pkgid.c_str());
+  if (!!cert_info.author_certificate.get()) {
+    if (!RegisterAuthorCertificate(cert_info, pkgid, uid)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool UnregisterAppInPkgmgr(const bf::path& xml_path,
+                           const std::string& pkgid, uid_t uid) {
+  int ret = uid != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
+      pkgmgr_parser_parse_usr_manifest_for_uninstallation(
+          xml_path.string().c_str(), uid,
+          const_cast<char* const*>(kAppinstTags)) :
+      pkgmgr_parser_parse_manifest_for_uninstallation(
+          xml_path.string().c_str(), const_cast<char* const*>(kAppinstTags));
+  if (ret) {
+    LOG(ERROR) << "Failed to unregister package: " << xml_path;
+    return false;
+  }
+
+  // Certificate info may be not present
+  (void) pkgmgr_installer_delete_certinfo(pkgid.c_str());
+
+  return true;
+}
+
+std::string QueryCertificateAuthorCertificate(const std::string& pkgid) {
+  pkgmgrinfo_certinfo_h handle;
+  int ret = pkgmgrinfo_pkginfo_create_certinfo(&handle);
+  if (ret != PMINFO_R_OK) {
+    LOG(ERROR) << "pkgmgrinfo_pkginfo_create_certinfo failed with error: "
+               << ret;
+    return {};
+  }
+  ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid.c_str(), handle, getuid());
+  if (ret != PMINFO_R_OK) {
+    LOG(ERROR) << "pkgmgrinfo_pkginfo_load_certinfo failed with error: " << ret;
+    pkgmgrinfo_pkginfo_destroy_certinfo(handle);
+    return {};
+  }
+  const char* author_cert = nullptr;
+  ret = pkgmgrinfo_pkginfo_get_cert_value(handle, PMINFO_AUTHOR_SIGNER_CERT,
+                                          &author_cert);
+  if (ret != PMINFO_R_OK) {
+    LOG(ERROR) << "pkgmgrinfo_pkginfo_get_cert_value failed with error: "
+               << ret;
+    pkgmgrinfo_pkginfo_destroy_certinfo(handle);
+    return {};
+  }
+  std::string old_author_certificate;
+  if (author_cert)
+    old_author_certificate = author_cert;
+  pkgmgrinfo_pkginfo_destroy_certinfo(handle);
+  return old_author_certificate;
+}
+
+}  // namespace common_installer
diff --git a/src/common/pkgmgr_registration.h b/src/common/pkgmgr_registration.h
new file mode 100644 (file)
index 0000000..cfa50c9
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_PKGMGR_REGISTRATION_H_
+#define COMMON_PKGMGR_REGISTRATION_H_
+
+#include <boost/filesystem.hpp>
+#include <unistd.h>
+
+#include <string>
+
+#include "common/context_installer.h"
+
+namespace common_installer {
+
+bool RegisterAppInPkgmgr(const boost::filesystem::path& xml_path,
+                         const std::string& pkgid,
+                         const CertificateInfo& cert_info, uid_t uid);
+bool UpgradeAppInPkgmgr(const boost::filesystem::path& xml_path,
+                        const std::string& pkgid,
+                        const CertificateInfo& cert_info, uid_t uid);
+bool UnregisterAppInPkgmgr(const boost::filesystem::path& xml_path,
+                           const std::string& pkgid, uid_t uid);
+std::string QueryCertificateAuthorCertificate(const std::string& pkgid);
+
+}  // namespace common_installer
+
+#endif  // COMMON_PKGMGR_REGISTRATION_H_
index 503bcb2..36f8841 100644 (file)
@@ -60,7 +60,8 @@ privilege_manager_visibility_e PrivilegeLevelToVisibility(
 common_installer::Step::Status ValidateSignatureFile(
     const bf::path& base_path,
     const ValidationCore::SignatureFileInfo& file_info,
-    common_installer::PrivilegeLevel* level) {
+    common_installer::PrivilegeLevel* level,
+    common_installer::CertificateInfo* cert_info) {
   bf::path path = base_path / file_info.getFileName();
   LOG(INFO) << "Processing signature: " << path;
   ValidationCore::SignatureData data(path.string(), file_info.getFileNumber());
@@ -101,6 +102,9 @@ common_installer::Step::Status ValidateSignatureFile(
               *level == common_installer::PrivilegeLevel::UNTRUSTED) {
             *level = CertStoreIdToPrivilegeLevel(data.getVisibilityLevel());
           }
+        } else {
+          // set author certificate to be saved in pkgmgr
+          cert_info->author_certificate.set(data.getEndEntityCertificatePtr());
         }
         break;
       };
@@ -162,7 +166,7 @@ namespace common_installer {
 namespace signature {
 
 Step::Status ValidateSignatures(const bf::path& base_path,
-                                PrivilegeLevel* level) {
+    PrivilegeLevel* level, common_installer::CertificateInfo* cert_info) {
   ValidationCore::VCoreInit();
   // Find signature files
   ValidationCore::SignatureFileInfoSet signature_files;
@@ -177,7 +181,8 @@ Step::Status ValidateSignatures(const bf::path& base_path,
 
   // Read xml schema for signatures
   for (auto& file_info : signature_files) {
-    Step::Status status = ValidateSignatureFile(base_path, file_info, level);
+    Step::Status status = ValidateSignatureFile(base_path, file_info, level,
+                                                cert_info);
     if (status != Step::Status::OK) {
       ValidationCore::VCoreDeinit();
       return status;
@@ -205,7 +210,8 @@ Step::Status StepCheckSignature::precheck() {
 Step::Status StepCheckSignature::process() {
   PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
   Status status =
-      ValidateSignatures(context_->unpacked_dir_path.get(), &level);
+      ValidateSignatures(context_->unpacked_dir_path.get(), &level,
+                         &context_->certificate_info.get());
   if (status != Status::OK) {
     return status;
   }
index 3743304..8396a49 100644 (file)
@@ -26,7 +26,7 @@ class StepCheckSignature : public Step {
 
 // Exposed for tests
 Step::Status ValidateSignatures(const boost::filesystem::path& base_path,
-                                PrivilegeLevel* level);
+    PrivilegeLevel* level, common_installer::CertificateInfo* cert_info);
 
 }  // namespace signature
 }  // namespace common_installer
index 1859ea8..2a47c31 100644 (file)
@@ -2,22 +2,15 @@
 
 #include "common/step/step_register_app.h"
 
-#include <pkgmgr-info.h>
 #include <unistd.h>
-#include <boost/filesystem.hpp>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
 #include <string>
 
+#include "common/pkgmgr_registration.h"
 #include "common/utils/file_util.h"
 
-namespace {
-
-const char* const kAppinstTags[] = {"removable=true", nullptr, };
-
-}  // anonymous namespace
-
 namespace common_installer {
 namespace register_app {
 
@@ -40,26 +33,13 @@ Step::Status StepRegisterApplication::precheck() {
 }
 
 Step::Status StepRegisterApplication::process() {
-  // TODO(sdi2): Check if data->removable is correctly setting
-  // during parsing step.
-  // Same check should be done for preload field.
-
-  // Having a specific step to implement a installer commandline tool
-  // for image build could be usefull also.
-
-  int ret = context_->uid.get() != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
-      pkgmgr_parser_parse_usr_manifest_for_installation(
-          context_->xml_path.get().c_str(), context_->uid.get(),
-          const_cast<char* const*>(kAppinstTags)) :
-      pkgmgr_parser_parse_manifest_for_installation(
-          context_->xml_path.get().c_str(),
-          const_cast<char* const*>(kAppinstTags));
-
-  if (ret) {
+  if (!RegisterAppInPkgmgr(context_->xml_path.get(),
+                           context_->pkgid.get().c_str(),
+                           context_->certificate_info.get(),
+                           context_->uid.get())) {
     LOG(ERROR) << "Failed to register the app";
     return Step::Status::ERROR;
   }
-  in_registry_ = true;
 
   LOG(INFO) << "Successfully registered the app";
   return Status::OK;
@@ -70,21 +50,9 @@ Step::Status StepRegisterApplication::clean() {
 }
 
 Step::Status StepRegisterApplication::undo() {
-  if (in_registry_) {
-    int ret = context_->uid.get() != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
-        pkgmgr_parser_parse_usr_manifest_for_uninstallation(
-            context_->xml_path.get().c_str(), context_->uid.get(),
-            const_cast<char* const*>(kAppinstTags)) :
-        pkgmgr_parser_parse_manifest_for_uninstallation(
-            context_->xml_path.get().c_str(),
-            const_cast<char* const*>(kAppinstTags));
-
-    if (ret) {
-      LOG(ERROR) << "Failed to restore old content pkgmgr database";
-      return Step::Status::ERROR;
-    }
-    LOG(INFO) << "Successfuly clean database";
-  }
+  UnregisterAppInPkgmgr(context_->xml_path.get(), context_->pkgid.get(),
+                        context_->uid.get());
+  LOG(INFO) << "Successfuly clean database";
   return Status::OK;
 }
 
index 01100cc..13a655c 100644 (file)
@@ -12,18 +12,13 @@ namespace register_app {
 
 class StepRegisterApplication : public Step {
  public:
-  explicit StepRegisterApplication(ContextInstaller* context)
-      : Step(context),
-        in_registry_(false) { }
+  using Step::Step;
 
   Status process() override;
   Status clean() override;
   Status undo() override;
   Status precheck() override;
 
- private:
-  bool in_registry_;
-
   SCOPE_LOG_TAG(RegisterApp)
 };
 
index 03f00ea..769e4c9 100755 (executable)
@@ -5,9 +5,11 @@
 #include <unistd.h>
 
 #include <boost/filesystem.hpp>
+#include <pkgmgr_installer.h>
 #include <cassert>
 #include <cstring>
 
+#include "common/pkgmgr_registration.h"
 #include "common/step/step_unregister_app.h"
 #include "common/utils/file_util.h"
 
@@ -38,20 +40,12 @@ Step::Status StepUnregisterApplication::precheck() {
 }
 
 Step::Status StepUnregisterApplication::process() {
-  const char* const appinst_tags[] = {"removable=true", nullptr, };
-
-  int ret = context_->uid.get() != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
-      pkgmgr_parser_parse_usr_manifest_for_uninstallation(
-          context_->xml_path.get().c_str(), context_->uid.get(),
-          const_cast<char* const*>(appinst_tags)) :
-      pkgmgr_parser_parse_manifest_for_uninstallation(
-          context_->xml_path.get().c_str(),
-          const_cast<char* const*>(appinst_tags));
-
-  if (ret != 0) {
+  if (!UnregisterAppInPkgmgr(context_->xml_path.get(), context_->pkgid.get(),
+                             context_->uid.get())) {
     LOG(ERROR) << "Failed to unregister package into database";
     return Status::ERROR;
   }
+
   LOG(DEBUG) << "Successfully unregister the application";
 
   return Status::OK;
index d9d767f..57708d0 100644 (file)
@@ -9,32 +9,19 @@
 #include <unistd.h>
 
 #include <boost/filesystem.hpp>
+#include <vcore/Base64.h>
+#include <vcore/Certificate.h>
+
 #include <cassert>
 #include <cstdio>
 #include <cstring>
 #include <string>
 
+#include "common/pkgmgr_registration.h"
 #include "common/utils/file_util.h"
 
 namespace bf = boost::filesystem;
 
-namespace {
-
-const char* const kAppinstTags[] = {"removable=true", nullptr, };
-
-bool UpgradeManifestInformation(uid_t uid, const bf::path& xml_path) {
-  int ret = uid != tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) ?
-       pkgmgr_parser_parse_usr_manifest_for_upgrade(
-           xml_path.string().c_str(), uid,
-           const_cast<char* const*>(kAppinstTags)) :
-       pkgmgr_parser_parse_manifest_for_upgrade(
-           xml_path.string().c_str(),
-           const_cast<char* const*>(kAppinstTags));
-  return !ret;
-}
-
-}  // anonymous namespace
-
 namespace common_installer {
 namespace update_app {
 
@@ -47,8 +34,9 @@ Step::Status StepUpdateApplication::precheck() {
 }
 
 Step::Status StepUpdateApplication::process() {
-  if (!UpgradeManifestInformation(context_->uid.get(),
-      context_->xml_path.get())) {
+  if (!UpgradeAppInPkgmgr(context_->xml_path.get(),
+      context_->pkgid.get(), context_->certificate_info.get(),
+      context_->uid.get())) {
     LOG(ERROR) << "Cannot upgrade manifest for application";
     return Status::ERROR;
   }
@@ -62,8 +50,17 @@ Step::Status StepUpdateApplication::clean() {
 }
 
 Step::Status StepUpdateApplication::undo() {
-  if (!UpgradeManifestInformation(context_->uid.get(),
-      context_->backup_xml_path.get())) {
+  // Prepare certification info for revert
+  ValidationCore::Base64Decoder decoder;
+  decoder.append(QueryCertificateAuthorCertificate(context_->pkgid.get()));
+  decoder.finalize();
+  CertificateInfo certificate_info;
+  certificate_info.author_certificate.set(ValidationCore::CertificatePtr(
+      new ValidationCore::Certificate(decoder.get())));
+
+  if (!UpgradeAppInPkgmgr(context_->backup_xml_path.get(),
+      context_->pkgid.get(), certificate_info,
+      context_->uid.get())) {
     LOG(ERROR) << "Cannot revert manifest for application";
     return Status::ERROR;
   }
index a7e3e33..1e0a032 100644 (file)
@@ -24,7 +24,8 @@ TEST_F(SignatureValidatorTest, HandlesInitializedSignatureDir) {
   signature_file.reset(new bf::path(
       "/usr/share/app-installers-ut/test_samples/good_signatures"));
   PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
-  EXPECT_EQ(ValidateSignatures(*signature_file, &level),
+  common_installer::CertificateInfo cert_info;
+  EXPECT_EQ(ValidateSignatures(*signature_file, &level, &cert_info),
             Step::Status::OK);
 }
 
@@ -33,7 +34,8 @@ TEST_F(SignatureValidatorTest, HandlesBadSignatureDir) {
   signature_file.reset(new bf::path(
       "/usr/share/app-installers-ut/test_samples/bad_signatures"));
   PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
-  EXPECT_EQ(ValidateSignatures(*signature_file, &level),
+  common_installer::CertificateInfo cert_info;
+  EXPECT_EQ(ValidateSignatures(*signature_file, &level, &cert_info),
             Step::Status::ERROR);
 }