CernVM-FS  2.12.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 "crypto/hash.h"
14 #include "crypto/signature.h"
15 #include "manifest.h"
16 #include "network/download.h"
17 #include "util/smalloc.h"
18 #include "whitelist.h"
19 
20 using namespace std; // NOLINT
21 
22 namespace manifest {
23 
30 static Failures DoVerify(unsigned char *manifest_data, size_t manifest_size,
31  const std::string &base_url,
32  const std::string &repository_name,
33  const uint64_t minimum_timestamp,
34  const shash::Any *base_catalog,
35  signature::SignatureManager *signature_manager,
36  download::DownloadManager *download_manager,
37  ManifestEnsemble *ensemble) {
38  assert(ensemble);
39  const bool probe_hosts = base_url == "";
40  Failures result = kFailUnknown;
41  bool retval_b;
42  download::Failures retval_dl;
43  whitelist::Failures retval_wl;
44  whitelist::Whitelist whitelist(repository_name, download_manager,
45  signature_manager);
46  string certificate_url = base_url + "/"; // rest is in manifest
47  shash::Any certificate_hash;
48  cvmfs::MemSink certificate_memsink;
49  download::JobInfo download_certificate(&certificate_url, true, probe_hosts,
50  &certificate_hash, &certificate_memsink);
51 
52  // Load Manifest
53  ensemble->raw_manifest_buf = manifest_data;
54  ensemble->raw_manifest_size = manifest_size;
56  ensemble->raw_manifest_buf, ensemble->raw_manifest_size);
57  if (!ensemble->manifest) return kFailIncomplete;
58 
59  // Basic manifest sanity check
60  if (ensemble->manifest->repository_name() != repository_name) {
62  "repository name does not match (found %s, expected %s)",
63  ensemble->manifest->repository_name().c_str(),
64  repository_name.c_str());
65  result = kFailNameMismatch;
66  goto cleanup;
67  }
68  if (ensemble->manifest->root_path() != shash::Md5(shash::AsciiPtr(""))) {
69  result = kFailRootMismatch;
70  goto cleanup;
71  }
72  if (ensemble->manifest->publish_timestamp() < minimum_timestamp) {
73  result = kFailOutdated;
74  goto cleanup;
75  }
76 
77  // Quick way out: hash matches base catalog
78  if (base_catalog && (ensemble->manifest->catalog_hash() == *base_catalog)) {
79  return kFailOk;
80  }
81 
82  // Load certificate
83  certificate_hash = ensemble->manifest->certificate();
84  ensemble->FetchCertificate(certificate_hash);
85  if (!ensemble->cert_buf) {
86  certificate_url += ensemble->manifest->MakeCertificatePath();
87  retval_dl = download_manager->Fetch(&download_certificate);
88  if (retval_dl != download::kFailOk) {
89  result = kFailLoad;
90  goto cleanup;
91  }
92  ensemble->cert_buf = certificate_memsink.data();
93  ensemble->cert_size = certificate_memsink.pos();
94  certificate_memsink.Release();
95  }
96  retval_b = signature_manager->LoadCertificateMem(ensemble->cert_buf,
97  ensemble->cert_size);
98  if (!retval_b) {
99  result = kFailBadCertificate;
100  goto cleanup;
101  }
102 
103  // Verify manifest
104  retval_b = signature_manager->VerifyLetter(
105  ensemble->raw_manifest_buf,
106  ensemble->raw_manifest_size,
107  false);
108  if (!retval_b) {
110  "failed to verify repository manifest");
111  result = kFailBadSignature;
112  goto cleanup;
113  }
114 
115  // Load whitelist and verify
116  retval_wl = whitelist.LoadUrl(base_url);
117  if (retval_wl != whitelist::kFailOk) {
119  "whitelist verification failed (%d): %s", retval_wl,
120  whitelist::Code2Ascii(retval_wl));
121  result = kFailBadWhitelist;
122  goto cleanup;
123  }
124 
125  retval_wl = whitelist.VerifyLoadedCertificate();
126  if (retval_wl != whitelist::kFailOk) {
128  "failed to verify repository signature against whitelist (%d): %s",
129  retval_wl, whitelist::Code2Ascii(retval_wl));
130  result = kFailInvalidCertificate;
131  goto cleanup;
132  }
133 
134  whitelist.CopyBuffers(&ensemble->whitelist_size, &ensemble->whitelist_buf,
135  &ensemble->whitelist_pkcs7_size,
136  &ensemble->whitelist_pkcs7_buf);
137 
138  return kFailOk;
139 
140 cleanup:
141  delete ensemble->manifest;
142  ensemble->manifest = NULL;
143  if (ensemble->raw_manifest_buf) free(ensemble->raw_manifest_buf);
144  if (ensemble->cert_buf) free(ensemble->cert_buf);
145  if (ensemble->whitelist_buf) free(ensemble->whitelist_buf);
146  if (ensemble->whitelist_pkcs7_buf) free(ensemble->whitelist_pkcs7_buf);
147  ensemble->raw_manifest_buf = NULL;
148  ensemble->cert_buf = NULL;
149  ensemble->whitelist_buf = NULL;
150  ensemble->whitelist_pkcs7_buf = NULL;
151  ensemble->raw_manifest_size = 0;
152  ensemble->cert_size = 0;
153  ensemble->whitelist_size = 0;
154  ensemble->whitelist_pkcs7_size = 0;
155  return result;
156 }
157 
162 static Failures DoFetch(const std::string &base_url,
163  const std::string &repository_name,
164  const uint64_t minimum_timestamp,
165  const shash::Any *base_catalog,
166  signature::SignatureManager *signature_manager,
167  download::DownloadManager *download_manager,
168  ManifestEnsemble *ensemble) {
169  assert(ensemble);
170  const bool probe_hosts = base_url == "";
171  download::Failures retval_dl;
172  const string manifest_url = base_url + string("/.cvmfspublished");
173  cvmfs::MemSink manifest_memsink;
174  download::JobInfo download_manifest(&manifest_url, false, probe_hosts, NULL,
175  &manifest_memsink);
176 
177  retval_dl = download_manager->Fetch(&download_manifest);
178  if (retval_dl != download::kFailOk) {
180  "failed to download repository manifest (%d - %s)", retval_dl,
181  download::Code2Ascii(retval_dl));
182  return kFailLoad;
183  }
184 
185  manifest_memsink.Release();
186  return DoVerify(manifest_memsink.data(), manifest_memsink.pos(), base_url,
187  repository_name, minimum_timestamp, base_catalog,
188  signature_manager, download_manager, ensemble);
189 }
190 
195 Failures Fetch(const std::string &base_url, const std::string &repository_name,
196  const uint64_t minimum_timestamp, const shash::Any *base_catalog,
197  signature::SignatureManager *signature_manager,
198  download::DownloadManager *download_manager,
199  ManifestEnsemble *ensemble) {
200  Failures result =
201  DoFetch(base_url, repository_name, minimum_timestamp, base_catalog,
202  signature_manager, download_manager, ensemble);
203  if ((result != kFailOk) &&
204  (result != kFailLoad) &&
205  (result != kFailInvalidCertificate) &&
206  (download_manager->num_hosts() > 1))
207  {
209  "failed to fetch manifest (%d - %s), trying another stratum 1",
210  result, Code2Ascii(result));
211  download_manager->SwitchHost();
212  result = DoFetch(base_url, repository_name, minimum_timestamp, base_catalog,
213  signature_manager, download_manager, ensemble);
214  }
215  return result;
216 }
217 
223 Failures Verify(unsigned char *manifest_data, size_t manifest_size,
224  const std::string &base_url, const std::string &repository_name,
225  const uint64_t minimum_timestamp,
226  const shash::Any *base_catalog,
227  signature::SignatureManager *signature_manager,
228  download::DownloadManager *download_manager,
229  ManifestEnsemble *ensemble) {
230  unsigned char *manifest_copy =
231  reinterpret_cast<unsigned char *>(smalloc(manifest_size));
232  memcpy(manifest_copy, manifest_data, manifest_size);
233  return DoVerify(manifest_copy, manifest_size, base_url, repository_name,
234  minimum_timestamp, base_catalog, signature_manager,
235  download_manager, ensemble);
236 }
237 
238 } // namespace manifest
const char * Code2Ascii(const ObjectFetcherFailures::Failures error)
const manifest::Manifest * manifest() const
Definition: repository.h:125
static Manifest * LoadMem(const unsigned char *buffer, const unsigned length)
Definition: manifest.cc:82
Failures Verify(unsigned 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)
unsigned char * raw_manifest_buf
unsigned char * data()
Definition: sink_mem.h:122
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:272
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:147
assert((mem||(size==0))&&"Out Of Memory")
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)
uint64_t publish_timestamp() const
Definition: manifest.h:136
std::string repository_name() const
Definition: manifest.h:130
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)
void Release()
Definition: sink.h:58
shash::Any certificate() const
Definition: manifest.h:134
const char * Code2Ascii(const Failures error)
Definition: whitelist.h:49
unsigned char * whitelist_pkcs7_buf
shash::Any catalog_hash() const
Definition: manifest.h:132
const whitelist::Whitelist * whitelist() const
Definition: repository.h:124
static Failures DoVerify(unsigned 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)
size_t pos()
Definition: sink_mem.h:121
Failures Fetch(JobInfo *info)
Definition: download.cc:1860
shash::Md5 root_path() const
Definition: manifest.h:131
bool VerifyLetter(const unsigned char *buffer, const unsigned buffer_size, const bool by_rsa)
Definition: signature.cc:968
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528