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