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 images_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 meta
21  {
22  for (auto repo : {Uptane::RepositoryType::Director(), Uptane::RepositoryType::Image()}) {
23  boost::filesystem::path& meta_dir = repo == (Uptane::RepositoryType::Director()) ? director_path : images_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_images_root = findMaxVersion(images_path, Uptane::Role::Root());
38 }
39 
40 bool FSStorageRead::loadPrimaryKeys(std::string* public_key, std::string* private_key) {
41  return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
42 }
43 
44 bool FSStorageRead::loadPrimaryPublic(std::string* public_key) {
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) {
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) {
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) {
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) { return loadTlsCommon(ca, config_.tls_cacert_path); }
103 
104 bool FSStorageRead::loadTlsCert(std::string* cert) { return loadTlsCommon(cert, config_.tls_clientcert_path); }
105 
106 bool FSStorageRead::loadTlsPkey(std::string* pkey) { return loadTlsCommon(pkey, config_.tls_pkey_path); }
107 
108 bool FSStorageRead::loadRoot(std::string* data, Uptane::RepositoryType repo, Uptane::Version version) {
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) {
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) {
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() {
181  return boost::filesystem::exists(Utils::absolutePath(config_.path, "is_registered").string());
182 }
183 
184 bool FSStorageRead::loadEcuSerials(EcuSerials* serials) {
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) {
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, size_t* current_version) {
247  const boost::filesystem::path path = Utils::absolutePath(config_.path, "installed_versions");
248  return INvStorage::fsReadInstalledVersions(path, installed_versions, current_version);
249 }
250 
251 bool FSStorageRead::splitNameRoleVersion(const std::string& full_name, std::string* role_name, int* version) {
252  size_t dot_pos = full_name.find('.');
253 
254  // doesn't have a dot
255  if (dot_pos == std::string::npos) {
256  return false;
257  }
258  std::string prefix = full_name.substr(0, dot_pos);
259  if (role_name != nullptr) {
260  *role_name = full_name.substr(dot_pos + 1);
261  }
262 
263  try {
264  auto v = boost::lexical_cast<int>(prefix);
265  if (version != nullptr) {
266  *version = v;
267  }
268  } catch (const boost::bad_lexical_cast&) {
269  return false;
270  }
271  return true;
272 }
273 
274 Uptane::Version FSStorageRead::findMaxVersion(const boost::filesystem::path& meta_directory, const Uptane::Role& role) {
275  int version = -1;
276  if (!boost::filesystem::exists(meta_directory)) {
277  return {};
278  }
279 
280  boost::filesystem::directory_iterator it{meta_directory};
281  for (; it != boost::filesystem::directory_iterator(); ++it) {
282  if (!boost::filesystem::is_regular_file(it->path())) {
283  continue;
284  }
285  std::string name = it->path().filename().native();
286  int file_version;
287  std::string file_role;
288  if (splitNameRoleVersion(name, &file_role, &file_version)) {
289  if (file_role == Uptane::Version().RoleFileName(role) && file_version > version) {
290  version = file_version;
291  }
292  }
293  }
294 
295  return Uptane::Version(version);
296 }
297 
298 // clear methods, to clean the storage files after a migration
299 
300 void FSStorageRead::clearPrimaryKeys() {
301  boost::filesystem::remove(config_.uptane_public_key_path.get(config_.path));
302  boost::filesystem::remove(config_.uptane_private_key_path.get(config_.path));
303 }
304 
305 void FSStorageRead::clearTlsCreds() {
306  boost::filesystem::remove(config_.tls_cacert_path.get(config_.path));
307  boost::filesystem::remove(config_.tls_clientcert_path.get(config_.path));
308  boost::filesystem::remove(config_.tls_pkey_path.get(config_.path));
309 }
310 
311 void FSStorageRead::clearNonRootMeta(Uptane::RepositoryType repo) {
312  boost::filesystem::path meta_path;
313  switch (repo) {
314  case Uptane::RepositoryType::Image():
315  meta_path = config_.uptane_metadata_path.get(config_.path) / "repo";
316  break;
317  case Uptane::RepositoryType::Director():
318  meta_path = config_.uptane_metadata_path.get(config_.path) / "director";
319  break;
320  default:
321  return;
322  }
323 
324  boost::filesystem::directory_iterator it{meta_path};
325  for (; it != boost::filesystem::directory_iterator(); ++it) {
326  for (const auto& role : Uptane::Role::Roles()) {
327  if (role == Uptane::Role::Root()) {
328  continue;
329  }
330  std::string role_name;
331  std::string fn = it->path().filename().native();
332  if (fn == Uptane::Version().RoleFileName(role) ||
333  (splitNameRoleVersion(fn, &role_name, nullptr) && (role_name == Uptane::Version().RoleFileName(role)))) {
334  boost::filesystem::remove(it->path());
335  }
336  }
337  }
338 }
339 
340 void FSStorageRead::clearMetadata() {
341  for (const auto& meta_path : {config_.uptane_metadata_path.get(config_.path) / "repo",
342  config_.uptane_metadata_path.get(config_.path) / "director"}) {
343  if (!boost::filesystem::exists(meta_path)) {
344  return;
345  }
346 
347  boost::filesystem::directory_iterator it{meta_path};
348  for (; it != boost::filesystem::directory_iterator(); ++it) {
349  boost::filesystem::remove(it->path());
350  }
351  }
352 }
353 
354 void FSStorageRead::clearDeviceId() { boost::filesystem::remove(Utils::absolutePath(config_.path, "device_id")); }
355 
356 void FSStorageRead::clearEcuRegistered() {
357  boost::filesystem::remove(Utils::absolutePath(config_.path, "is_registered"));
358 }
359 
360 void FSStorageRead::clearEcuSerials() {
361  boost::filesystem::remove(Utils::absolutePath(config_.path, "primary_ecu_serial"));
362  boost::filesystem::remove(Utils::absolutePath(config_.path, "primary_ecu_hardware_id"));
363  boost::filesystem::remove(Utils::absolutePath(config_.path, "secondaries_list"));
364 }
365 
366 void FSStorageRead::clearMisconfiguredEcus() {
367  boost::filesystem::remove(Utils::absolutePath(config_.path, "misconfigured_ecus"));
368 }
369 
370 void FSStorageRead::clearInstalledVersions() {
371  if (boost::filesystem::exists(Utils::absolutePath(config_.path, "installed_versions"))) {
372  boost::filesystem::remove(Utils::absolutePath(config_.path, "installed_versions"));
373  }
374 }
375 
376 void FSStorageRead::clearInstallationResult() {
377  boost::filesystem::remove(Utils::absolutePath(config_.path, "installation_result"));
378 }
379 
380 void FSStorageRead::cleanUpAll() {
381  clearPrimaryKeys();
382  clearTlsCreds();
383  clearDeviceId();
384  clearEcuSerials();
385  clearEcuRegistered();
386  clearMisconfiguredEcus();
387  clearInstalledVersions();
388  clearInstallationResult();
389  clearMetadata();
390 
391  boost::filesystem::remove_all(config_.uptane_metadata_path.get(config_.path));
392  boost::filesystem::remove_all(config_.path / "targets");
393 }
394 
395 bool FSStorageRead::FSStoragePresent(const StorageConfig& config) {
396  return boost::filesystem::exists(Utils::absolutePath(config.path, "is_registered").string());
397 }
Uptane::Version
Metadata version numbers.
Definition: tuf.h:116
BasedPath
Definition: utils.h:101
StorageConfig
Definition: storage_config.h:15
MisconfiguredEcu
Definition: invstorage.h:28
data
General data structures.
Definition: types.cc:44
Uptane::HardwareIdentifier
Definition: tuf.h:143
Uptane::RepositoryType
Definition: tuf.h:20
Uptane::EcuSerial
Definition: tuf.h:174
Uptane::Role
TUF Roles.
Definition: tuf.h:57