5 #include "cvmfs_config.h"
23 const int Whitelist::kFlagVerifyRsa = 0x01;
24 const int Whitelist::kFlagVerifyPkcs7 = 0x02;
25 const int Whitelist::kFlagVerifyCaChain = 0x04;
28 void Whitelist::CopyBuffers(
unsigned *plain_size,
unsigned char **plain_buf,
29 unsigned *pkcs7_size,
unsigned char **pkcs7_buf)
32 *plain_size = plain_size_;
33 *pkcs7_size = pkcs7_size_;
36 if (plain_size_ > 0) {
37 *plain_buf =
reinterpret_cast<unsigned char *
>(smalloc(plain_size_));
38 memcpy(*plain_buf, plain_buf_, plain_size_);
40 if (pkcs7_size_ > 0) {
41 *pkcs7_buf =
reinterpret_cast<unsigned char *
>(smalloc(pkcs7_size_));
42 memcpy(*pkcs7_buf, pkcs7_buf_, pkcs7_size_);
47 std::string Whitelist::CreateString(
48 const std::string &fqrn,
60 std::string hash_str = hash.
ToString();
63 whitelist +=
"--\n" + hash_str +
"\n";
64 unsigned char *signature;
65 unsigned signature_size;
66 bool retval = signature_manager->
SignRsa(
67 reinterpret_cast<const unsigned char *>(hash_str.data()), hash_str.length(),
68 &signature, &signature_size);
70 whitelist += std::string(reinterpret_cast<char *>(signature), signature_size);
77 std::string Whitelist::ExportString()
const {
78 if (plain_buf_ == NULL)
return "";
79 return std::string(reinterpret_cast<char *>(plain_buf_), plain_size_);
83 time_t Whitelist::expires()
const {
84 assert(status_ == kStAvailable);
89 bool Whitelist::IsExpired()
const {
90 assert(status_ == kStAvailable);
91 return time(NULL) > expires_;
95 Failures Whitelist::VerifyLoadedCertificate()
const {
96 assert(status_ == kStAvailable);
98 vector<string> blacklist = signature_manager_->GetBlacklist();
99 for (
unsigned i = 0; i < blacklist.size(); ++i) {
106 if (this_hash == signature_manager_->HashCertificate(algorithm))
110 for (
unsigned i = 0; i < fingerprints_.size(); ++i) {
112 if (signature_manager_->HashCertificate(algorithm) == fingerprints_[i]) {
113 if (verification_flags_ & kFlagVerifyCaChain) {
114 bool retval = signature_manager_->VerifyCaChain();
133 assert(verification_flags_ != 0);
135 if (verification_flags_ & kFlagVerifyRsa) {
136 retval_b = signature_manager_->VerifyLetter(plain_buf_, plain_size_,
true);
143 if (verification_flags_ & kFlagVerifyPkcs7) {
144 unsigned char *extracted_whitelist;
145 unsigned extracted_whitelist_size;
146 vector<string> alt_uris;
148 signature_manager_->VerifyPkcs7(pkcs7_buf_, pkcs7_size_,
149 &extracted_whitelist,
150 &extracted_whitelist_size,
154 "failed to verify repository whitelist (pkcs#7): %s",
155 signature_manager_->GetCryptoError().c_str());
160 bool found_uri =
false;
161 for (
unsigned i = 0; i < alt_uris.size(); ++i) {
163 alt_uris[i].c_str());
164 if (alt_uris[i] ==
"cvmfs:" + fqrn_) {
171 "failed to find whitelist signer with SAN/URI cvmfs:%s",
173 free(extracted_whitelist);
180 string(reinterpret_cast<char *>(extracted_whitelist),
181 extracted_whitelist_size).c_str());
182 retval_wl = ParseWhitelist(extracted_whitelist, extracted_whitelist_size);
185 "failed to verify repository certificate against pkcs#7 "
191 status_ = kStAvailable;
201 plain_size_ = whitelist.length();
202 plain_buf_ =
reinterpret_cast<unsigned char *
>(smalloc(plain_size_));
203 memcpy(plain_buf_, whitelist.data(), plain_size_);
205 retval_wl = ParseWhitelist(plain_buf_, plain_size_);
209 if (verification_flags_ & kFlagVerifyPkcs7)
212 return VerifyWhitelist();
216 Failures Whitelist::LoadUrl(
const std::string &base_url) {
217 const bool probe_hosts = base_url ==
"";
223 const string whitelist_url = base_url + string(
"/.cvmfswhitelist");
227 retval_dl = download_manager_->Fetch(&download_whitelist);
230 plain_size_ = whitelist_memsink.
pos();
231 if (plain_size_ == 0)
234 plain_buf_ = whitelist_memsink.
data();
236 retval_wl = ParseWhitelist(plain_buf_, plain_size_);
240 if (verification_flags_ & kFlagVerifyPkcs7) {
242 const string whitelist_pkcs7_url =
243 base_url + string(
"cvmfswhitelist.pkcs7");
246 probe_hosts, NULL, &pkcs7_memsink);
247 retval_dl = download_manager_->Fetch(&download_whitelist_pkcs7);
250 pkcs7_size_ = pkcs7_memsink.
pos();
251 if (pkcs7_size_ == 0)
254 pkcs7_buf_ = pkcs7_memsink.
data();
257 return VerifyWhitelist();
265 bool Whitelist::IsBefore(time_t now,
const struct tm &t_whitelist) {
267 if (gmtime_r(&now, &t_local) == NULL)
269 if (t_local.tm_year < t_whitelist.tm_year)
return true;
270 if (t_local.tm_year > t_whitelist.tm_year)
return false;
271 if (t_local.tm_mon < t_whitelist.tm_mon)
return true;
272 if (t_local.tm_mon > t_whitelist.tm_mon)
return false;
273 if (t_local.tm_mday < t_whitelist.tm_mday)
return true;
274 if (t_local.tm_mday > t_whitelist.tm_mday)
return false;
275 if (t_local.tm_hour < t_whitelist.tm_hour)
return true;
281 const unsigned whitelist_size)
283 time_t local_timestamp = time(NULL);
285 unsigned payload_bytes = 0;
286 bool verify_pkcs7 =
false;
287 bool verify_cachain =
false;
290 line =
GetLineMem(reinterpret_cast<const char *>(whitelist), whitelist_size);
291 if (line.length() != 14) {
298 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
299 whitelist_size-payload_bytes);
300 if (line.length() != 15) {
305 memset(&tm_wl, 0,
sizeof(
struct tm));
310 tm_wl.tm_min = tm_wl.tm_sec = 0;
311 time_t timestamp = timegm(&tm_wl);
313 "whitelist UTC expiry timestamp in localtime: %s",
319 if (!IsBefore(local_timestamp, tm_wl)) {
321 "whitelist lifetime verification failed, expired");
333 expires_ = timestamp;
337 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
338 whitelist_size-payload_bytes);
339 if ((fqrn_ !=
"") && (
"N" + fqrn_ != line)) {
341 "repository name on the whitelist does not match "
342 "(found %s, expected %s)",
343 line.c_str(), fqrn_.c_str());
346 payload_bytes += line.length() + 1;
349 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
350 whitelist_size-payload_bytes);
351 if (line ==
"Vpkcs7") {
354 payload_bytes += line.length() + 1;
355 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
356 whitelist_size-payload_bytes);
360 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
361 whitelist_size-payload_bytes);
362 if (line ==
"Wcachain") {
364 "whitelist imposes ca chain verification of manifest signature");
365 verify_cachain =
true;
366 payload_bytes += line.length() + 1;
367 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
368 whitelist_size-payload_bytes);
372 if (line ==
"--")
break;
375 fingerprints_.push_back(this_hash);
377 payload_bytes += line.length() + 1;
378 line =
GetLineMem(reinterpret_cast<const char *>(whitelist)+payload_bytes,
379 whitelist_size-payload_bytes);
380 }
while (payload_bytes < whitelist_size);
382 verification_flags_ = verify_pkcs7 ? kFlagVerifyPkcs7 : kFlagVerifyRsa;
384 verification_flags_ |= kFlagVerifyCaChain;
389 void Whitelist::Reset() {
391 fingerprints_.clear();
393 verification_flags_ = 0;
405 Whitelist::Whitelist(
const string &fqrn,
409 download_manager_(download_manager),
410 signature_manager_(signature_manager),
422 download_manager_(other.download_manager_),
423 signature_manager_(other.signature_manager_),
424 status_(other.status_),
425 fingerprints_(other.fingerprints_),
426 expires_(other.expires_),
427 verification_flags_(other.verification_flags_)
435 : download_manager_(NULL)
436 , signature_manager_(NULL)
439 , verification_flags_(0)
void HashString(const std::string &content, Any *any_digest)
bool SignRsa(const unsigned char *buffer, const unsigned buffer_size, unsigned char **signature, unsigned *signature_size)
string GetLineMem(const char *text, const int text_size)
static shash::Any MkFromFingerprint(const std::string &fingerprint)
std::string ToString(const bool with_suffix=false) const
unsigned char * pkcs7_buf_
void CopyBuffers(unsigned *plain_size, unsigned char **plain_buf, unsigned *pkcs7_size, unsigned char **pkcs7_buf) const
assert((mem||(size==0))&&"Out Of Memory")
string StringifyTime(const time_t seconds, const bool utc)
unsigned char * plain_buf_
int64_t String2Int64(const string &value)
std::string WhitelistTimestamp(time_t when)
download::DownloadManager * download_manager_
const whitelist::Whitelist * whitelist() const
Whitelist & operator=(const Whitelist &other)
std::string FingerprintCertificate(const shash::Algorithms hash_algorithm)
std::vector< shash::Any > fingerprints_
signature::SignatureManager * signature_manager_
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)