eb3c2ea101cca27364dfe7f984ae855b9fcb3c29
[platform/core/appfw/app-installers.git] / src / common / signature.cc
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.
4
5 #include "common/signature.h"
6
7 #include <tzplatform_config.h>
8 #include <unistd.h>
9
10 #include <string>
11 #include <regex>
12
13 #include "common/certificate_validation.h"
14 #include "common/utils/pkgmgr_query.h"
15 #include "common/utils/glist_range.h"
16 #include "common/utils/file_util.h"
17 #include "common/utils/request.h"
18
19 namespace bf = boost::filesystem;
20 namespace bi = boost::iostreams;
21 namespace ci = common_installer;
22
23 namespace common_installer {
24
25 bool Signature::SetPath() {
26   bf::path path = bf::path((is_readonly_package_) ?
27       tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
28       "signatures";
29   if (!CreateDir(path))
30     return false;
31
32   file_path_ = path / std::string(pkgid_ + ".txt");
33   backup_path_ = path / std::string(pkgid_ + "_backup.txt");
34   if (bf::exists(backup_path_))
35     bf::remove(backup_path_);
36   if (bf::exists(file_path_))
37     bf::rename(file_path_, backup_path_);
38   return true;
39 }
40
41 bool Signature::CheckSignatures(bool check_reference, PrivilegeLevel* level,
42                     boost::filesystem::path sig_root_path,
43                     std::string *error_message) {
44   if (!ValidateSignatures(sig_root_path, level, cert_info_,
45                           check_reference, error_message))
46     return false;
47   return true;
48 }
49
50 bool Signature::GetPrivilegeLevel(boost::filesystem::path sig_root_path,
51                                  PrivilegeLevel* level,
52                                  std::string* error_message) {
53   bool check_reference = true;
54   if (request_type_ == ci::RequestType::Reinstall ||
55       request_type_ == ci::RequestType::ReadonlyUpdateUninstall ||
56       (getuid() == 0 &&
57       (skip_check_reference_ ||
58       request_type_ == ci::RequestType::ManifestDirectInstall ||
59       request_type_ == ci::RequestType::ManifestDirectUpdate ||
60       request_type_ == ci::RequestType::ManifestPartialInstall ||
61       request_type_ == ci::RequestType::ManifestPartialUpdate)))
62     check_reference = false;
63   if (!CheckSignatures(check_reference, level, sig_root_path, error_message))
64     return false;
65
66   if (*level == PrivilegeLevel::UNTRUSTED)
67     if (!GetSignatureFromFile(pkgid_, is_readonly_package_, level, cert_info_))
68       LOG(INFO) << "Unable to get privilege level from file";
69
70   if (is_readonly_package_)
71     *level = PrivilegeLevel::PLATFORM;
72
73   return true;
74 }
75
76 bool Signature::CheckMetadataPrivilege(PrivilegeLevel level,
77                                       manifest_x* manifest,
78                                       std::string* error_message) {
79   if (is_readonly_package_)
80     return true;
81   for (application_x* app : GListRange<application_x*>(manifest->application)) {
82     if (!ValidateMetadataPrivilege(level, manifest->api_version,
83         app->metadata, error_message))
84       return false;
85   }
86   return true;
87 }
88
89 bool Signature::StoreSignature(bi::stream<bi::file_descriptor_sink> *ofs,
90     const ValidationCore::CertificatePtr& cert,
91     const ValidationCore::CertificatePtr& im_cert,
92     const ValidationCore::CertificatePtr& root_cert) {
93   if (!ofs)
94     return false;
95   *ofs << ((cert) ? cert->getBase64().c_str() : "") << std::endl;
96   *ofs << ((im_cert) ? im_cert->getBase64().c_str() : "") << std::endl;
97   *ofs << ((root_cert) ? root_cert->getBase64().c_str() : "") << std::endl;
98   return true;
99 }
100
101 bool Signature::Store() {
102   bool ret = true;
103   bi::stream<bi::file_descriptor_sink> ofs(file_path_);
104   if (!StoreSignature(&ofs,
105                       cert_info_->dist2_cert.get(),
106                       cert_info_->dist2_im_cert.get(),
107                       cert_info_->dist2_root_cert.get()) ||
108       !StoreSignature(&ofs,
109                       cert_info_->dist_cert.get(),
110                       cert_info_->dist_im_cert.get(),
111                       cert_info_->dist_root_cert.get()))
112     ret = false;
113   ofs.flush();
114   ::fsync(ofs->handle());
115   ofs.close();
116   return ret;
117 }
118
119 bool Signature::RemoveSignature(const bf::path& path) {
120   // dist signatures cannot be removed when mount install/update
121   if (request_type_ == RequestType::MountInstall ||
122       request_type_ == RequestType::MountUpdate)
123     return true;
124
125   for (bf::directory_iterator file(path);
126       file != bf::directory_iterator();
127       ++file) {
128     try {
129       bf::path file_path(file->path());
130
131       if (bf::is_symlink(symlink_status(file_path)) ||
132           bf::is_directory(file_path))
133         continue;
134
135       std::regex distributor_regex("^(signature)([1-9][0-9]*)(\\.xml)");
136       if (std::regex_search(file_path.filename().string(), distributor_regex)) {
137         if (!common_installer::Remove(file_path)) {
138           LOG(ERROR) << "Failed to remove signature file";
139           return false;
140         }
141       }
142     } catch (const bf::filesystem_error& error) {
143       LOG(ERROR) << "Failed to remove signature files: " << error.what();
144       return false;
145     }
146   }
147
148   sync();
149   return true;
150 }
151
152 bool Signature::SaveSignature(const bf::path& path) {
153   if (!SetPath() || !Store() || !RemoveSignature(path))
154     return false;
155   return true;
156 }
157
158 const bf::path& Signature::GetFilePath() const {
159   return file_path_;
160 }
161
162 const bf::path& Signature::GetBackupPath() const {
163   return backup_path_;
164 }
165
166 }  // namespace common_installer