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