CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
manifest_fetch.cc
Go to the documentation of this file.
1 
5 #include "manifest_fetch.h"
6 
7 #include <string>
8 #include <vector>
9 
10 #include <cassert>
11 #include <cstring>
12 
13 #include "download.h"
14 #include "hash.h"
15 #include "manifest.h"
16 #include "signature.h"
17 #include "smalloc.h"
18 #include "whitelist.h"
19 
20 using namespace std; // NOLINT
21 
22 namespace manifest {
23 
29 static Failures DoVerify(char *manifest_data, size_t manifest_size,
30  const std::string &base_url,
31  const std::string &repository_name,
32  const uint64_t minimum_timestamp,
33  const shash::Any *base_catalog,
34  signature::SignatureManager *signature_manager,
35  download::DownloadManager *download_manager,
36  ManifestEnsemble *ensemble) {
37  assert(ensemble);
38  const bool probe_hosts = base_url == "";
39  Failures result = kFailUnknown;
40  bool retval_b;
41  download::Failures retval_dl;
42  whitelist::Failures retval_wl;
43  whitelist::Whitelist whitelist(repository_name, download_manager,
44  signature_manager);
45  string certificate_url = base_url + "/"; // rest is in manifest
46  shash::Any certificate_hash;
47  download::JobInfo download_certificate(&certificate_url, true, probe_hosts,
48  &certificate_hash);
49 
50  // Load Manifest
51  ensemble->raw_manifest_buf = reinterpret_cast<unsigned char *>(manifest_data);
52  ensemble->raw_manifest_size = manifest_size;
54  ensemble->raw_manifest_buf, ensemble->raw_manifest_size);
55  if (!ensemble->manifest) return kFailIncomplete;
56 
57  // Basic manifest sanity check
58  if (ensemble->manifest->repository_name() != repository_name) {
60  "repository name does not match (found %s, expected %s)",
61  ensemble->manifest->repository_name().c_str(),
62  repository_name.c_str());
63  result = kFailNameMismatch;
64  goto cleanup;
65  }
66  if (ensemble->manifest->root_path() != shash::Md5(shash::AsciiPtr(""))) {
67  result = kFailRootMismatch;
68  goto cleanup;
69  }
70  if (ensemble->manifest->publish_timestamp() < minimum_timestamp) {
71  result = kFailOutdated;
72  goto cleanup;
73  }
74 
75  // Quick way out: hash matches base catalog
76  if (base_catalog && (ensemble->manifest->catalog_hash() == *base_catalog))
77  return kFailOk;
78 
79  // Load certificate
80  certificate_hash = ensemble->manifest->certificate();
81  ensemble->FetchCertificate(certificate_hash);
82  if (!ensemble->cert_buf) {
83  certificate_url += ensemble->manifest->MakeCertificatePath();
84  retval_dl = download_manager->Fetch(&download_certificate);
85  if (retval_dl != download::kFailOk) {
86  result = kFailLoad;
87  goto cleanup;
88  }
89  ensemble->cert_buf = reinterpret_cast<unsigned char *>(
90  download_certificate.destination_mem.data);
91  ensemble->cert_size = download_certificate.destination_mem.pos;
92  }
93  retval_b = signature_manager->LoadCertificateMem(ensemble->cert_buf,
94  ensemble->cert_size);
95  if (!retval_b) {
96  result = kFailBadCertificate;
97  goto cleanup;
98  }
99 
100  // Verify manifest
101  retval_b = signature_manager->VerifyLetter(
102  ensemble->raw_manifest_buf,
103  ensemble->raw_manifest_size,
104  false);
105  if (!retval_b) {
107  "failed to verify repository manifest");
108  result = kFailBadSignature;
109  goto cleanup;
110  }
111 
112  // Load whitelist and verify
113  retval_wl = whitelist.LoadUrl(base_url);
114  if (retval_wl != whitelist::kFailOk) {
116  "whitelist verification failed (%d): %s", retval_wl,
117  whitelist::Code2Ascii(retval_wl));
118  result = kFailBadWhitelist;
119  goto cleanup;
120  }
121 
122  retval_wl = whitelist.VerifyLoadedCertificate();
123  if (retval_wl != whitelist::kFailOk) {
125  "failed to verify repository signature against whitelist (%d): %s",
126  retval_wl, whitelist::Code2Ascii(retval_wl));
127  result = kFailInvalidCertificate;
128  goto cleanup;
129  }
130 
131  whitelist.CopyBuffers(&ensemble->whitelist_size, &ensemble->whitelist_buf,
132  &ensemble->whitelist_pkcs7_size,
133  &ensemble->whitelist_pkcs7_buf);
134 
135  return kFailOk;
136 
137 cleanup:
138  delete ensemble->manifest;
139  ensemble->manifest = NULL;
140  if (ensemble->raw_manifest_buf) free(ensemble->raw_manifest_buf);
141  if (ensemble->cert_buf) free(ensemble->cert_buf);
142  if (ensemble->whitelist_buf) free(ensemble->whitelist_buf);
143  if (ensemble->whitelist_pkcs7_buf) free(ensemble->whitelist_pkcs7_buf);
144  ensemble->raw_manifest_buf = NULL;
145  ensemble->cert_buf = NULL;
146  ensemble->whitelist_buf = NULL;
147  ensemble->whitelist_pkcs7_buf = NULL;
148  ensemble->raw_manifest_size = 0;
149  ensemble->cert_size = 0;
150  ensemble->whitelist_size = 0;
151  ensemble->whitelist_pkcs7_size = 0;
152  return result;
153 }
154 
159 static Failures DoFetch(const std::string &base_url,
160  const std::string &repository_name,
161  const uint64_t minimum_timestamp,
162  const shash::Any *base_catalog,
163  signature::SignatureManager *signature_manager,
164  download::DownloadManager *download_manager,
165  ManifestEnsemble *ensemble) {
166  assert(ensemble);
167  const bool probe_hosts = base_url == "";
168  download::Failures retval_dl;
169  const string manifest_url = base_url + string("/.cvmfspublished");
170  download::JobInfo download_manifest(&manifest_url, false, probe_hosts, NULL);
171 
172  retval_dl = download_manager->Fetch(&download_manifest);
173  if (retval_dl != download::kFailOk) {
175  "failed to download repository manifest (%d - %s)", retval_dl,
176  download::Code2Ascii(retval_dl));
177  return kFailLoad;
178  }
179 
180  return DoVerify(download_manifest.destination_mem.data,
181  download_manifest.destination_mem.pos, base_url,
182  repository_name, minimum_timestamp, base_catalog,
183  signature_manager, download_manager, ensemble);
184 }
185 
190 Failures Fetch(const std::string &base_url, const std::string &repository_name,
191  const uint64_t minimum_timestamp, const shash::Any *base_catalog,
192  signature::SignatureManager *signature_manager,
193  download::DownloadManager *download_manager,
194  ManifestEnsemble *ensemble) {
195  Failures result =
196  DoFetch(base_url, repository_name, minimum_timestamp, base_catalog,
197  signature_manager, download_manager, ensemble);
198  if ((result != kFailOk) && (result != kFailLoad) &&
199  (download_manager->num_hosts() > 1)) {
201  "failed to fetch manifest (%d - %s), trying another stratum 1",
202  result, Code2Ascii(result));
203  download_manager->SwitchHost();
204  result = DoFetch(base_url, repository_name, minimum_timestamp, base_catalog,
205  signature_manager, download_manager, ensemble);
206  }
207  return result;
208 }
209 
210 Failures Verify(char *manifest_data, size_t manifest_size,
211  const std::string &base_url, const std::string &repository_name,
212  const uint64_t minimum_timestamp,
213  const shash::Any *base_catalog,
214  signature::SignatureManager *signature_manager,
215  download::DownloadManager *download_manager,
216  ManifestEnsemble *ensemble) {
217  char *manifest_copy = reinterpret_cast<char *>(smalloc(manifest_size));
218  memcpy(manifest_copy, manifest_data, manifest_size);
219  return DoVerify(manifest_copy, manifest_size, base_url, repository_name,
220  minimum_timestamp, base_catalog, signature_manager,
221  download_manager, ensemble);
222 }
223 
224 } // namespace manifest
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
const char * Code2Ascii(const ObjectFetcherFailures::Failures error)
const manifest::Manifest * manifest() const
Definition: repository.h:123
static Manifest * LoadMem(const unsigned char *buffer, const unsigned length)
Definition: manifest.cc:68
unsigned char * raw_manifest_buf
static Failures DoVerify(char *manifest_data, size_t manifest_size, const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
Failures LoadUrl(const std::string &base_url)
Definition: whitelist.cc:216
Failures VerifyLoadedCertificate() const
Definition: whitelist.cc:95
bool LoadCertificateMem(const unsigned char *buffer, const unsigned buffer_size)
Definition: signature.cc:244
void CopyBuffers(unsigned *plain_size, unsigned char **plain_buf, unsigned *pkcs7_size, unsigned char **pkcs7_buf) const
Definition: whitelist.cc:28
std::string MakeCertificatePath() const
Definition: manifest.h:139
assert((mem||(size==0))&&"Out Of Memory")
Failures Verify(char *manifest_data, size_t manifest_size, const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
static Failures DoFetch(const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
virtual void FetchCertificate(const shash::Any &hash)
unsigned char * whitelist_buf
const char * Code2Ascii(const Failures error)
Definition: download.h:87
uint64_t publish_timestamp() const
Definition: manifest.h:128
std::string repository_name() const
Definition: manifest.h:122
Failures Fetch(const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
shash::Any certificate() const
Definition: manifest.h:126
const char * Code2Ascii(const Failures error)
Definition: whitelist.h:49
unsigned char * whitelist_pkcs7_buf
shash::Any catalog_hash() const
Definition: manifest.h:124
const whitelist::Whitelist * whitelist() const
Definition: repository.h:122
Failures Fetch(JobInfo *info)
Definition: download.cc:1719
struct download::JobInfo::@3 destination_mem
shash::Md5 root_path() const
Definition: manifest.h:123
bool VerifyLetter(const unsigned char *buffer, const unsigned buffer_size, const bool by_rsa)
Definition: signature.cc:929