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,
30 unsigned char **pkcs7_buf)
const {
31 *plain_size = plain_size_;
32 *pkcs7_size = pkcs7_size_;
35 if (plain_size_ > 0) {
36 *plain_buf =
reinterpret_cast<unsigned char *
>(smalloc(plain_size_));
37 memcpy(*plain_buf, plain_buf_, plain_size_);
39 if (pkcs7_size_ > 0) {
40 *pkcs7_buf =
reinterpret_cast<unsigned char *
>(smalloc(pkcs7_size_));
41 memcpy(*pkcs7_buf, pkcs7_buf_, pkcs7_size_);
46 std::string Whitelist::CreateString(
47 const std::string &fqrn,
51 const std::string to_sign =
58 std::string hash_str = hash.
ToString();
61 whitelist +=
"--\n" + hash_str +
"\n";
62 unsigned char *signature;
63 unsigned signature_size;
64 const bool retval = signature_manager->
SignRsa(
65 reinterpret_cast<const unsigned char *>(hash_str.data()),
66 hash_str.length(), &signature, &signature_size);
68 whitelist += std::string(reinterpret_cast<char *>(signature), signature_size);
75 std::string Whitelist::ExportString()
const {
76 if (plain_buf_ == NULL)
78 return std::string(reinterpret_cast<char *>(plain_buf_), plain_size_);
82 time_t Whitelist::expires()
const {
83 assert(status_ == kStAvailable);
88 bool Whitelist::IsExpired()
const {
89 assert(status_ == kStAvailable);
90 return time(NULL) > expires_;
94 Failures Whitelist::VerifyLoadedCertificate()
const {
95 assert(status_ == kStAvailable);
97 vector<string> blacklist = signature_manager_->GetBlacklist();
98 for (
unsigned i = 0; i < blacklist.size(); ++i) {
105 if (this_hash == signature_manager_->HashCertificate(algorithm))
109 for (
unsigned i = 0; i < fingerprints_.size(); ++i) {
111 if (signature_manager_->HashCertificate(algorithm) == fingerprints_[i]) {
112 if (verification_flags_ & kFlagVerifyCaChain) {
113 const bool retval = signature_manager_->VerifyCaChain();
132 assert(verification_flags_ != 0);
134 if (verification_flags_ & kFlagVerifyRsa) {
135 retval_b = signature_manager_->VerifyLetter(plain_buf_, plain_size_,
true);
142 if (verification_flags_ & kFlagVerifyPkcs7) {
143 unsigned char *extracted_whitelist;
144 unsigned extracted_whitelist_size;
145 vector<string> alt_uris;
146 retval_b = signature_manager_->VerifyPkcs7(
147 pkcs7_buf_, pkcs7_size_, &extracted_whitelist,
148 &extracted_whitelist_size, &alt_uris);
151 "failed to verify repository whitelist (pkcs#7): %s",
152 signature_manager_->GetCryptoError().c_str());
157 bool found_uri =
false;
158 for (
unsigned i = 0; i < alt_uris.size(); ++i) {
160 alt_uris[i].c_str());
161 if (alt_uris[i] ==
"cvmfs:" + fqrn_) {
168 "failed to find whitelist signer with SAN/URI cvmfs:%s",
170 free(extracted_whitelist);
177 string(reinterpret_cast<char *>(extracted_whitelist),
178 extracted_whitelist_size)
180 retval_wl = ParseWhitelist(extracted_whitelist, extracted_whitelist_size);
183 "failed to verify repository certificate against pkcs#7 "
189 status_ = kStAvailable;
199 plain_size_ = whitelist.length();
200 plain_buf_ =
reinterpret_cast<unsigned char *
>(smalloc(plain_size_));
201 memcpy(plain_buf_, whitelist.data(), plain_size_);
203 retval_wl = ParseWhitelist(plain_buf_, plain_size_);
207 if (verification_flags_ & kFlagVerifyPkcs7)
210 return VerifyWhitelist();
214 Failures Whitelist::LoadUrl(
const std::string &base_url) {
215 const bool probe_hosts = base_url ==
"";
221 const string whitelist_url = base_url + string(
"/.cvmfswhitelist");
225 retval_dl = download_manager_->Fetch(&download_whitelist);
228 plain_size_ = whitelist_memsink.
pos();
229 if (plain_size_ == 0)
232 plain_buf_ = whitelist_memsink.
data();
234 retval_wl = ParseWhitelist(plain_buf_, plain_size_);
238 if (verification_flags_ & kFlagVerifyPkcs7) {
240 const string whitelist_pkcs7_url = base_url
241 + string(
"cvmfswhitelist.pkcs7");
244 &whitelist_pkcs7_url,
false, probe_hosts, NULL, &pkcs7_memsink);
245 retval_dl = download_manager_->Fetch(&download_whitelist_pkcs7);
248 pkcs7_size_ = pkcs7_memsink.
pos();
249 if (pkcs7_size_ == 0)
252 pkcs7_buf_ = pkcs7_memsink.
data();
255 return VerifyWhitelist();
263 bool Whitelist::IsBefore(time_t now,
const struct tm &t_whitelist) {
265 if (gmtime_r(&now, &t_local) == NULL)
267 if (t_local.tm_year < t_whitelist.tm_year)
269 if (t_local.tm_year > t_whitelist.tm_year)
271 if (t_local.tm_mon < t_whitelist.tm_mon)
273 if (t_local.tm_mon > t_whitelist.tm_mon)
275 if (t_local.tm_mday < t_whitelist.tm_mday)
277 if (t_local.tm_mday > t_whitelist.tm_mday)
279 if (t_local.tm_hour < t_whitelist.tm_hour)
286 const unsigned whitelist_size) {
287 const time_t local_timestamp = time(NULL);
289 unsigned payload_bytes = 0;
290 bool verify_pkcs7 =
false;
291 bool verify_cachain =
false;
294 line =
GetLineMem(reinterpret_cast<const char *>(whitelist), whitelist_size);
295 if (line.length() != 14) {
302 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
303 whitelist_size - payload_bytes);
304 if (line.length() != 15) {
309 memset(&tm_wl, 0,
sizeof(
struct tm));
314 tm_wl.tm_min = tm_wl.tm_sec = 0;
315 const time_t timestamp = timegm(&tm_wl);
317 "whitelist UTC expiry timestamp in localtime: %s",
323 if (!IsBefore(local_timestamp, tm_wl)) {
325 "whitelist lifetime verification failed, expired");
337 expires_ = timestamp;
341 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
342 whitelist_size - payload_bytes);
343 if ((fqrn_ !=
"") && (
"N" + fqrn_ != line)) {
345 "repository name on the whitelist does not match "
346 "(found %s, expected %s)",
347 line.c_str(), fqrn_.c_str());
350 payload_bytes += line.length() + 1;
353 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
354 whitelist_size - payload_bytes);
355 if (line ==
"Vpkcs7") {
358 payload_bytes += line.length() + 1;
359 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
360 whitelist_size - payload_bytes);
364 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
365 whitelist_size - payload_bytes);
366 if (line ==
"Wcachain") {
368 "whitelist imposes ca chain verification of manifest signature");
369 verify_cachain =
true;
370 payload_bytes += line.length() + 1;
371 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
372 whitelist_size - payload_bytes);
381 fingerprints_.push_back(this_hash);
383 payload_bytes += line.length() + 1;
384 line =
GetLineMem(reinterpret_cast<const char *>(whitelist) + payload_bytes,
385 whitelist_size - payload_bytes);
386 }
while (payload_bytes < whitelist_size);
388 verification_flags_ = verify_pkcs7 ? kFlagVerifyPkcs7 : kFlagVerifyRsa;
390 verification_flags_ |= kFlagVerifyCaChain;
395 void Whitelist::Reset() {
397 fingerprints_.clear();
399 verification_flags_ = 0;
411 Whitelist::Whitelist(
const string &fqrn,
415 , download_manager_(download_manager)
416 , signature_manager_(signature_manager)
427 , download_manager_(other.download_manager_)
428 , signature_manager_(other.signature_manager_)
429 , status_(other.status_)
430 , fingerprints_(other.fingerprints_)
431 , expires_(other.expires_)
432 , verification_flags_(other.verification_flags_) {
439 : download_manager_(NULL)
440 , signature_manager_(NULL)
443 , 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,...)