Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
fsstorage_read.cc
1 #include "fsstorage_read.h"
2 
3 #include <fcntl.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 
7 #include <iostream>
8 #include <utility>
9 
10 #include <boost/lexical_cast.hpp>
11 #include <boost/scoped_array.hpp>
12 #include "json/json.h"
13 
14 #include "logging/logging.h"
15 #include "utilities/utils.h"
16 
17 FSStorageRead::FSStorageRead(const StorageConfig& config) : config_(config) {
18  boost::filesystem::path image_path = config_.uptane_metadata_path.get(config_.path) / "repo";
19  boost::filesystem::path director_path = config_.uptane_metadata_path.get(config_.path) / "director";
20  // migrate from old unversioned Uptane Root metadata
21  {
22  for (auto repo : {Uptane::RepositoryType::Director(), Uptane::RepositoryType::Image()}) {
23  boost::filesystem::path& meta_dir = repo == (Uptane::RepositoryType::Director()) ? director_path : image_path;
24  boost::filesystem::path meta_path = meta_dir / Uptane::Version().RoleFileName(Uptane::Role::Root());
25  if (boost::filesystem::exists(meta_path)) {
26  std::string data = Utils::readFile(meta_path);
27  Uptane::Version version{Uptane::extractVersionUntrusted(data)};
28  boost::filesystem::remove(meta_path);
29  if (version.version() >= 0) {
30  Utils::writeFile(meta_dir / version.RoleFileName(Uptane::Role::Root()), data);
31  }
32  }
33  }
34  }
35 
36  latest_director_root = findMaxVersion(director_path, Uptane::Role::Root());
37  latest_image_root = findMaxVersion(image_path, Uptane::Role::Root());
38 }
39 
40 bool FSStorageRead::loadPrimaryKeys(std::string* public_key, std::string* private_key) const {
41  return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
42 }
43 
44 bool FSStorageRead::loadPrimaryPublic(std::string* public_key) const {
45  boost::filesystem::path public_key_path = config_.uptane_public_key_path.get(config_.path);
46  if (!boost::filesystem::exists(public_key_path)) {
47  return false;
48  }
49 
50  if (public_key != nullptr) {
51  *public_key = Utils::readFile(public_key_path.string());
52  }
53  return true;
54 }
55 
56 bool FSStorageRead::loadPrimaryPrivate(std::string* private_key) const {
57  boost::filesystem::path private_key_path = config_.uptane_private_key_path.get(config_.path);
58  if (!boost::filesystem::exists(private_key_path)) {
59  return false;
60  }
61 
62  if (private_key != nullptr) {
63  *private_key = Utils::readFile(private_key_path.string());
64  }
65  return true;
66 }
67 
68 bool FSStorageRead::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey) const {
69  boost::filesystem::path ca_path(config_.tls_cacert_path.get(config_.path));
70  boost::filesystem::path cert_path(config_.tls_clientcert_path.get(config_.path));
71  boost::filesystem::path pkey_path(config_.tls_pkey_path.get(config_.path));
72  if (!boost::filesystem::exists(ca_path) || boost::filesystem::is_directory(ca_path) ||
73  !boost::filesystem::exists(cert_path) || boost::filesystem::is_directory(cert_path) ||
74  !boost::filesystem::exists(pkey_path) || boost::filesystem::is_directory(pkey_path)) {
75  return false;
76  }
77  if (ca != nullptr) {
78  *ca = Utils::readFile(ca_path.string());
79  }
80  if (cert != nullptr) {
81  *cert = Utils::readFile(cert_path.string());
82  }
83  if (pkey != nullptr) {
84  *pkey = Utils::readFile(pkey_path.string());
85  }
86  return true;
87 }
88 
89 bool FSStorageRead::loadTlsCommon(std::string* data, const BasedPath& path_in) const {
90  boost::filesystem::path path(path_in.get(config_.path));
91  if (!boost::filesystem::exists(path)) {
92  return false;
93  }
94 
95  if (data != nullptr) {
96  *data = Utils::readFile(path.string());
97  }
98 
99  return true;
100 }
101 
102 bool FSStorageRead::loadTlsCa(std::string* ca) const { return loadTlsCommon(ca, config_.tls_cacert_path); }
103 
104 bool FSStorageRead::loadTlsCert(std::string* cert) const { return loadTlsCommon(cert, config_.tls_clientcert_path); }
105 
106 bool FSStorageRead::loadTlsPkey(std::string* pkey) const { return loadTlsCommon(pkey, config_.tls_pkey_path); }
107 
108 bool FSStorageRead::loadRoot(std::string* data, Uptane::RepositoryType repo, Uptane::Version version) const {
109  boost::filesystem::path metafile;
110  switch (repo) {
111  case (Uptane::RepositoryType::Director()):
112  if (version.version() < 0) {
113  version = latest_director_root;
114  }
115  metafile =
116  config_.uptane_metadata_path.get(config_.path) / "director" / version.RoleFileName(Uptane::Role::Root());
117  break;
118 
119  case (Uptane::RepositoryType::Image()):
120  if (version.version() < 0) {
121  version = latest_director_root;
122  }
123  metafile = config_.uptane_metadata_path.get(config_.path) / "repo" / version.RoleFileName(Uptane::Role::Root());
124  break;
125 
126  default:
127  return false;
128  }
129 
130  if (version.version() < 0) {
131  return false;
132  }
133 
134  if (!boost::filesystem::exists(metafile)) {
135  return false;
136  }
137 
138  if (data != nullptr) {
139  *data = Utils::readFile(metafile);
140  }
141  return true;
142 }
143 
144 bool FSStorageRead::loadNonRoot(std::string* data, Uptane::RepositoryType repo, const Uptane::Role& role) const {
145  boost::filesystem::path metafile;
146  switch (repo) {
147  case (Uptane::RepositoryType::Director()):
148  metafile = config_.uptane_metadata_path.get(config_.path) / "director" / Uptane::Version().RoleFileName(role);
149  break;
150 
151  case (Uptane::RepositoryType::Image()):
152  metafile = config_.uptane_metadata_path.get(config_.path) / "repo" / Uptane::Version().RoleFileName(role);
153  break;
154 
155  default:
156  return false;
157  }
158 
159  if (!boost::filesystem::exists(metafile)) {
160  return false;
161  }
162 
163  if (data != nullptr) {
164  *data = Utils::readFile(metafile);
165  }
166  return true;
167 }
168 
169 bool FSStorageRead::loadDeviceId(std::string* device_id) const {
170  if (!boost::filesystem::exists(Utils::absolutePath(config_.path, "device_id").string())) {
171  return false;
172  }
173 
174  if (device_id != nullptr) {
175  *device_id = Utils::readFile(Utils::absolutePath(config_.path, "device_id").string());
176  }
177  return true;
178 }
179 
180 bool FSStorageRead::loadEcuRegistered() const {
181  return boost::filesystem::exists(Utils::absolutePath(config_.path, "is_registered").string());
182 }
183 
184 bool FSStorageRead::loadEcuSerials(EcuSerials* serials) const {
185  std::string buf;
186  std::string serial;
187  std::string hw_id;
188 
189  const boost::filesystem::path serial_path = Utils::absolutePath(config_.path, "primary_ecu_serial");
190  if (!boost::filesystem::exists(serial_path)) {
191  return false;
192  }
193  serial = Utils::readFile(serial_path.string());
194  // use default hardware ID for backwards compatibility
195  const boost::filesystem::path hw_id_path = Utils::absolutePath(config_.path, "primary_ecu_hardware_id");
196  if (!boost::filesystem::exists(hw_id_path)) {
197  hw_id = Utils::getHostname();
198  } else {
199  hw_id = Utils::readFile(hw_id_path.string());
200  }
201 
202  if (serials != nullptr) {
203  serials->push_back({Uptane::EcuSerial(serial), Uptane::HardwareIdentifier(hw_id)});
204  }
205 
206  // return true for backwards compatibility
207  const boost::filesystem::path sec_list_path = Utils::absolutePath(config_.path, "secondaries_list");
208  if (!boost::filesystem::exists(sec_list_path)) {
209  return true;
210  }
211  std::ifstream file(sec_list_path.c_str());
212  while (std::getline(file, buf)) {
213  size_t tab = buf.find('\t');
214  serial = buf.substr(0, tab);
215  try {
216  hw_id = buf.substr(tab + 1);
217  } catch (const std::out_of_range& e) {
218  if (serials != nullptr) {
219  serials->clear();
220  }
221  file.close();
222  return false;
223  }
224  if (serials != nullptr) {
225  serials->push_back({Uptane::EcuSerial(serial), Uptane::HardwareIdentifier(hw_id)});
226  }
227  }
228  file.close();
229  return true;
230 }
231 
232 bool FSStorageRead::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus) const {
233  if (!boost::filesystem::exists(Utils::absolutePath(config_.path, "misconfigured_ecus"))) {
234  return false;
235  }
236  Json::Value content_json = Utils::parseJSONFile(Utils::absolutePath(config_.path, "misconfigured_ecus").string());
237 
238  for (auto it = content_json.begin(); it != content_json.end(); ++it) {
239  ecus->push_back(MisconfiguredEcu(Uptane::EcuSerial((*it)["serial"].asString()),
240  Uptane::HardwareIdentifier((*it)["hardware_id"].asString()),
241  static_cast<EcuState>((*it)["state"].asInt())));
242  }
243  return true;
244 }
245 
246 bool FSStorageRead::loadInstalledVersions(std::vector<Uptane::Target>* installed_versions,
247  size_t* current_version) const {
248  const boost::filesystem::path path = Utils::absolutePath(config_.path, "installed_versions");
249  return INvStorage::fsReadInstalledVersions(path, installed_versions, current_version);
250 }
251 
252 bool FSStorageRead::splitNameRoleVersion(const std::string& full_name, std::string* role_name, int* version) {
253  size_t dot_pos = full_name.find('.');
254 
255  // doesn't have a dot
256  if (dot_pos == std::string::npos) {
257  return false;
258  }
259  std::string prefix = full_name.substr(0, dot_pos);
260  if (role_name != nullptr) {
261  *role_name = full_name.substr(dot_pos + 1);
262  }
263 
264  try {
265  auto v = boost::lexical_cast<int>(prefix);
266  if (version != nullptr) {
267  *version = v;
268  }
269  } catch (const boost::bad_lexical_cast&) {
270  return false;
271  }
272  return true;
273 }
274 
275 Uptane::Version FSStorageRead::findMaxVersion(const boost::filesystem::path& meta_directory, const Uptane::Role& role) {
276  int version = -1;
277  if (!boost::filesystem::exists(meta_directory)) {
278  return {};
279  }
280 
281  boost::filesystem::directory_iterator it{meta_directory};
282  for (; it != boost::filesystem::directory_iterator(); ++it) {
283  if (!boost::filesystem::is_regular_file(it->path())) {
284  continue;
285  }
286  std::string name = it->path().filename().native();
287  int file_version;
288  std::string file_role;
289  if (splitNameRoleVersion(name, &file_role, &file_version)) {
290  if (file_role == Uptane::Version().RoleFileName(role) && file_version > version) {
291  version = file_version;
292  }
293  }
294  }
295 
296  return Uptane::Version(version);
297 }
298 
299 // clear methods, to clean the storage files after a migration
300 
301 void FSStorageRead::clearPrimaryKeys() {
302  boost::filesystem::remove(config_.uptane_public_key_path.get(config_.path));
303  boost::filesystem::remove(config_.uptane_private_key_path.get(config_.path));
304 }
305 
306 void FSStorageRead::clearTlsCreds() {
307  boost::filesystem::remove(config_.tls_cacert_path.get(config_.path));
308  boost::filesystem::remove(config_.tls_clientcert_path.get(config_.path));
309  boost::filesystem::remove(config_.tls_pkey_path.get(config_.path));
310 }
311 
312 void FSStorageRead::clearNonRootMeta(Uptane::RepositoryType repo) {
313  boost::filesystem::path meta_path;
314  switch (repo) {
315  case Uptane::RepositoryType::Image():
316  meta_path = config_.uptane_metadata_path.get(config_.path) / "repo";
317  break;
318  case Uptane::RepositoryType::Director():
319  meta_path = config_.uptane_metadata_path.get(config_.path) / "director";
320  break;
321  default:
322  return;
323  }
324 
325  boost::filesystem::directory_iterator it{meta_path};
326  for (; it != boost::filesystem::directory_iterator(); ++it) {
327  for (const auto& role : Uptane::Role::Roles()) {
328  if (role == Uptane::Role::Root()) {
329  continue;
330  }
331  std::string role_name;
332  std::string fn = it->path().filename().native();
333  if (fn == Uptane::Version().RoleFileName(role) ||
334  (splitNameRoleVersion(fn, &role_name, nullptr) && (role_name == Uptane::Version().RoleFileName(role)))) {
335  boost::filesystem::remove(it->path());
336  }
337  }
338  }
339 }
340 
341 void FSStorageRead::clearMetadata() {
342  for (const auto& meta_path : {config_.uptane_metadata_path.get(config_.path) / "repo",
343  config_.uptane_metadata_path.get(config_.path) / "director"}) {
344  if (!boost::filesystem::exists(meta_path)) {
345  return;
346  }
347 
348  boost::filesystem::directory_iterator it{meta_path};
349  for (; it != boost::filesystem::directory_iterator(); ++it) {
350  boost::filesystem::remove(it->path());
351  }
352  }
353 }
354 
355 void FSStorageRead::clearDeviceId() { boost::filesystem::remove(Utils::absolutePath(config_.path, "device_id")); }
356 
357 void FSStorageRead::clearEcuRegistered() {
358  boost::filesystem::remove(Utils::absolutePath(config_.path, "is_registered"));
359 }
360 
361 void FSStorageRead::clearEcuSerials() {
362  boost::filesystem::remove(Utils::absolutePath(config_.path, "primary_ecu_serial"));
363  boost::filesystem::remove(Utils::absolutePath(config_.path, "primary_ecu_hardware_id"));
364  boost::filesystem::remove(Utils::absolutePath(config_.path, "secondaries_list"));
365 }
366 
367 void FSStorageRead::clearMisconfiguredEcus() {
368  boost::filesystem::remove(Utils::absolutePath(config_.path, "misconfigured_ecus"));
369 }
370 
371 void FSStorageRead::clearInstalledVersions() {
372  if (boost::filesystem::exists(Utils::absolutePath(config_.path, "installed_versions"))) {
373  boost::filesystem::remove(Utils::absolutePath(config_.path, "installed_versions"));
374  }
375 }
376 
377 void FSStorageRead::clearInstallationResult() {
378  boost::filesystem::remove(Utils::absolutePath(config_.path, "installation_result"));
379 }
380 
381 void FSStorageRead::cleanUpAll() {
382  clearPrimaryKeys();
383  clearTlsCreds();
384  clearDeviceId();
385  clearEcuSerials();
386  clearEcuRegistered();
387  clearMisconfiguredEcus();
388  clearInstalledVersions();
389  clearInstallationResult();
390  clearMetadata();
391 
392  boost::filesystem::remove_all(config_.uptane_metadata_path.get(config_.path));
393  boost::filesystem::remove_all(config_.path / "targets");
394 }
395 
396 bool FSStorageRead::FSStoragePresent(const StorageConfig& config) {
397  return boost::filesystem::exists(Utils::absolutePath(config.path, "is_registered").string());
398 }
General data structures.
Definition: types.cc:55
Metadata version numbers.
Definition: tuf.h:119
TUF Roles.
Definition: tuf.h:60