1 // Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/signature.h"
7 #include <tzplatform_config.h>
12 #include "common/certificate_validation.h"
13 #include "common/pkgmgr_query.h"
14 #include "common/request.h"
15 #include "common/utils/glist_range.h"
16 #include "common/utils/file_util.h"
18 namespace bf = boost::filesystem;
19 namespace ci = common_installer;
21 namespace common_installer {
23 bool CheckPkgCertificateMismatch(const std::string& pkgid,
24 const std::string& certificate) {
25 bool certificate_mismatch = false;
26 uid_t uid = G_MAXUINT;
27 auto old_certificate = ci::QueryCertificateAuthorCertificate(pkgid, uid);
29 if (!old_certificate.empty()) {
30 bool is_same = ci::IsSameAuthor(old_certificate, certificate);
31 certificate_mismatch = !is_same;
33 return certificate_mismatch;
36 bool Signature::CheckSignatureMismatch(std::string& error_message) {
37 const auto& cert = cert_info_->auth_cert.get();
39 bool certificate_mismatch =
40 CheckPkgCertificateMismatch(pkgid_, cert->getBase64());
41 if (certificate_mismatch) {
43 "Package with the same id and different certificate "
44 "has been already installed";
51 bool Signature::SetPath() {
52 bf::path path = bf::path((is_readonly_package_) ?
53 tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
58 file_path_ = path / std::string(pkgid_ + ".txt");
59 backup_path_ = path / std::string(pkgid_ + "_backup.txt");
60 if (bf::exists(backup_path_))
61 bf::remove(backup_path_);
62 if (bf::exists(file_path_))
63 bf::rename(file_path_, backup_path_);
67 bool Signature::CheckSignatures(bool check_reference, PrivilegeLevel* level,
68 boost::filesystem::path sig_root_path,
69 std::string *error_message) {
70 if (!ValidateSignatures(sig_root_path, level, cert_info_,
71 check_reference, error_message))
76 bool Signature::GetPrivilegeLevel(boost::filesystem::path sig_root_path,
77 PrivilegeLevel* level,
78 std::string& error_message) {
79 bool check_reference = true;
80 if (request_type_ == ci::RequestType::Reinstall ||
81 request_type_ == ci::RequestType::ReadonlyUpdateUninstall ||
83 (skip_check_reference_ ||
84 request_type_ == ci::RequestType::ManifestDirectInstall ||
85 request_type_ == ci::RequestType::ManifestDirectUpdate ||
86 request_type_ == ci::RequestType::ManifestPartialInstall ||
87 request_type_ == ci::RequestType::ManifestPartialUpdate)))
88 check_reference = false;
89 if (!CheckSignatures(check_reference, level, sig_root_path, &error_message))
92 if (!CheckSignatureMismatch(error_message))
95 if (*level == PrivilegeLevel::UNTRUSTED)
96 if (!GetSignatureFromFile(pkgid_, is_readonly_package_, level, cert_info_))
97 LOG(INFO) << "Unable to get privilege level from file";
99 if (is_readonly_package_)
100 *level = PrivilegeLevel::PLATFORM;
105 bool Signature::CheckMetadataPrivilege(PrivilegeLevel level,
106 manifest_x* manifest,
107 std::string& error_message) {
108 if (is_readonly_package_)
110 for (application_x* app : GListRange<application_x*>(manifest->application)) {
111 if (!ValidateMetadataPrivilege(level, manifest->api_version,
112 app->metadata, &error_message))
118 bool Signature::StoreSignature(std::ofstream* ofs,
119 const ValidationCore::CertificatePtr& cert,
120 const ValidationCore::CertificatePtr& im_cert,
121 const ValidationCore::CertificatePtr& root_cert) {
125 *ofs << ((cert) ? cert->getBase64().c_str() : "") << std::endl;
126 *ofs << ((im_cert) ? im_cert->getBase64().c_str() : "") << std::endl;
127 *ofs << ((root_cert) ? root_cert->getBase64().c_str() : "") << std::endl;
131 bool Signature::Store() {
133 std::ofstream ofs(file_path_.c_str(),
134 std::ios::out | std::ios::trunc);
135 if (!StoreSignature(&ofs,
136 cert_info_->dist2_cert.get(),
137 cert_info_->dist2_im_cert.get(),
138 cert_info_->dist2_root_cert.get()) ||
139 !StoreSignature(&ofs,
140 cert_info_->dist_cert.get(),
141 cert_info_->dist_im_cert.get(),
142 cert_info_->dist_root_cert.get()))
148 bool Signature::RemoveSignature(const bf::path& path) {
149 // dist signatures cannot be removed when mount install/update
150 if (request_type_ == RequestType::MountInstall ||
151 request_type_ == RequestType::MountUpdate)
154 for (bf::directory_iterator file(path);
155 file != bf::directory_iterator();
158 bf::path file_path(file->path());
160 if (bf::is_symlink(symlink_status(file_path)) ||
161 bf::is_directory(file_path))
164 std::regex distributor_regex("^(signature)([1-9][0-9]*)(\\.xml)");
165 if (std::regex_search(file_path.filename().string(), distributor_regex)) {
166 if (!common_installer::Remove(file_path)) {
167 LOG(ERROR) << "Failed to remove signature file";
171 } catch (const bf::filesystem_error& error) {
172 LOG(ERROR) << "Failed to remove signature files: " << error.what();
181 bool Signature::SaveSignature(const bf::path& path) {
182 if (!SetPath() || !Store() || !RemoveSignature(path))
187 const bf::path& Signature::GetFilePath() const {
191 const bf::path& Signature::GetBackupPath() const {
195 } // namespace common_installer