| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/server_tool.cc |
| Date: | 2025-11-02 02:35:35 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 18 | 78 | 23.1% |
| Branches: | 14 | 110 | 12.7% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * This file is part of the CernVM File System. | ||
| 3 | */ | ||
| 4 | |||
| 5 | #include "server_tool.h" | ||
| 6 | |||
| 7 | #include "util/posix.h" | ||
| 8 | |||
| 9 |
2/4✓ Branch 2 taken 830 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 830 times.
✗ Branch 6 not taken.
|
830 | ServerTool::ServerTool() { } |
| 10 | |||
| 11 | 1770 | ServerTool::~ServerTool() { | |
| 12 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 829 times.
|
1658 | if (signature_manager_.IsValid()) { |
| 13 | ✗ | signature_manager_->Fini(); | |
| 14 | } | ||
| 15 | 1770 | } | |
| 16 | |||
| 17 | 830 | bool ServerTool::InitDownloadManager(const bool follow_redirects, | |
| 18 | const std::string &proxy, | ||
| 19 | const unsigned max_pool_handles) { | ||
| 20 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 830 times.
|
830 | if (download_manager_.IsValid()) { |
| 21 | ✗ | return true; | |
| 22 | } | ||
| 23 | |||
| 24 | download_manager_ = new download::DownloadManager( | ||
| 25 |
6/12✓ Branch 3 taken 830 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 830 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 830 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 830 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 830 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 830 times.
✗ Branch 20 not taken.
|
830 | max_pool_handles, perf::StatisticsTemplate("download", statistics())); |
| 26 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 830 times.
|
830 | assert(download_manager_.IsValid()); |
| 27 | |||
| 28 | 830 | download_manager_->SetTimeout(kDownloadTimeout, kDownloadTimeout); | |
| 29 | 830 | download_manager_->SetRetryParameters(kDownloadRetries, 2000, 5000); | |
| 30 | 830 | download_manager_->UseSystemCertificatePath(); | |
| 31 | |||
| 32 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 830 times.
|
830 | if (proxy != "") { |
| 33 | ✗ | download_manager_->SetProxyChain(proxy, "", | |
| 34 | download::DownloadManager::kSetProxyBoth); | ||
| 35 | } | ||
| 36 | |||
| 37 |
1/2✓ Branch 0 taken 830 times.
✗ Branch 1 not taken.
|
830 | if (follow_redirects) { |
| 38 | 830 | download_manager_->EnableRedirects(); | |
| 39 | } | ||
| 40 | |||
| 41 | 830 | return true; | |
| 42 | } | ||
| 43 | |||
| 44 | ✗ | bool ServerTool::InitSignatureManager(const std::string &pubkey_path, | |
| 45 | const std::string &certificate_path, | ||
| 46 | const std::string &private_key_path) { | ||
| 47 | ✗ | if (signature_manager_.IsValid()) { | |
| 48 | ✗ | return true; | |
| 49 | } | ||
| 50 | |||
| 51 | ✗ | signature_manager_ = new signature::SignatureManager(); | |
| 52 | ✗ | assert(signature_manager_.IsValid()); | |
| 53 | ✗ | signature_manager_->Init(); | |
| 54 | |||
| 55 | // We may not have a public key. In this case, the signature manager | ||
| 56 | // can only be used for signing, not for verification. | ||
| 57 | ✗ | if (!pubkey_path.empty()) { | |
| 58 | ✗ | if (!signature_manager_->LoadPublicRsaKeys(pubkey_path)) { | |
| 59 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, "failed to load public repo key '%s'", | |
| 60 | pubkey_path.c_str()); | ||
| 61 | ✗ | return false; | |
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | // We may not have a certificate and key. In this case, the signature manager | ||
| 66 | // can only be used for verification, not for signing. | ||
| 67 | ✗ | if (certificate_path.empty()) | |
| 68 | ✗ | return true; | |
| 69 | |||
| 70 | ✗ | if (!signature_manager_->LoadCertificatePath(certificate_path)) { | |
| 71 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, "failed to load certificate '%s'", | |
| 72 | certificate_path.c_str()); | ||
| 73 | ✗ | return false; | |
| 74 | } | ||
| 75 | |||
| 76 | // Load private key | ||
| 77 | ✗ | if (!signature_manager_->LoadPrivateKeyPath(private_key_path, "")) { | |
| 78 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, "failed to load private key '%s' (%s)", | |
| 79 | private_key_path.c_str(), | ||
| 80 | ✗ | signature_manager_->GetCryptoError().c_str()); | |
| 81 | ✗ | return false; | |
| 82 | } | ||
| 83 | |||
| 84 | ✗ | if (!signature_manager_->KeysMatch()) { | |
| 85 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, | |
| 86 | "the private key '%s' doesn't seem to match certificate '%s' (%s)", | ||
| 87 | private_key_path.c_str(), certificate_path.c_str(), | ||
| 88 | ✗ | signature_manager_->GetCryptoError().c_str()); | |
| 89 | ✗ | signature_manager_->UnloadPrivateKey(); | |
| 90 | ✗ | return false; | |
| 91 | } | ||
| 92 | |||
| 93 | ✗ | return true; | |
| 94 | } | ||
| 95 | |||
| 96 | 958 | download::DownloadManager *ServerTool::download_manager() const { | |
| 97 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 958 times.
|
958 | assert(download_manager_.IsValid()); |
| 98 | 958 | return download_manager_.weak_ref(); | |
| 99 | } | ||
| 100 | |||
| 101 | ✗ | signature::SignatureManager *ServerTool::signature_manager() const { | |
| 102 | ✗ | assert(signature_manager_.IsValid()); | |
| 103 | ✗ | return signature_manager_.weak_ref(); | |
| 104 | } | ||
| 105 | |||
| 106 | ✗ | manifest::Manifest *ServerTool::OpenLocalManifest( | |
| 107 | const std::string path) const { | ||
| 108 | ✗ | return manifest::Manifest::LoadFile(path); | |
| 109 | } | ||
| 110 | |||
| 111 | ✗ | manifest::Failures ServerTool::FetchRemoteManifestEnsemble( | |
| 112 | const std::string &repository_url, const std::string &repository_name, | ||
| 113 | manifest::ManifestEnsemble *ensemble) const { | ||
| 114 | ✗ | const uint64_t minimum_timestamp = 0; | |
| 115 | ✗ | const shash::Any *base_catalog = NULL; | |
| 116 | ✗ | return manifest::Fetch(repository_url, repository_name, minimum_timestamp, | |
| 117 | base_catalog, signature_manager(), download_manager(), | ||
| 118 | ✗ | ensemble); | |
| 119 | } | ||
| 120 | |||
| 121 | ✗ | manifest::Manifest *ServerTool::FetchRemoteManifest( | |
| 122 | const std::string &repository_url, const std::string &repository_name, | ||
| 123 | const shash::Any &base_hash) const { | ||
| 124 | ✗ | manifest::ManifestEnsemble manifest_ensemble; | |
| 125 | ✗ | UniquePtr<manifest::Manifest> manifest; | |
| 126 | |||
| 127 | // fetch (and verify) the manifest | ||
| 128 | ✗ | const manifest::Failures retval = FetchRemoteManifestEnsemble( | |
| 129 | repository_url, repository_name, &manifest_ensemble); | ||
| 130 | |||
| 131 | ✗ | if (retval != manifest::kFailOk) { | |
| 132 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, | |
| 133 | "failed to fetch repository manifest " | ||
| 134 | "(%d - %s)", | ||
| 135 | retval, manifest::Code2Ascii(retval)); | ||
| 136 | ✗ | return NULL; | |
| 137 | } else { | ||
| 138 | // copy-construct a fresh manifest object because ManifestEnsemble will | ||
| 139 | // free manifest_ensemble.manifest when it goes out of scope | ||
| 140 | ✗ | manifest = new manifest::Manifest(*manifest_ensemble.manifest); | |
| 141 | } | ||
| 142 | |||
| 143 | // check if manifest fetching was successful | ||
| 144 | ✗ | if (!manifest.IsValid()) { | |
| 145 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, "failed to load repository manifest"); | |
| 146 | ✗ | return NULL; | |
| 147 | } | ||
| 148 | |||
| 149 | // check the provided base hash of the repository if provided | ||
| 150 | ✗ | if (!base_hash.IsNull() && manifest->catalog_hash() != base_hash) { | |
| 151 | ✗ | LogCvmfs(kLogCvmfs, kLogStderr, | |
| 152 | "base hash does not match manifest " | ||
| 153 | "(found: %s expected: %s)", | ||
| 154 | ✗ | manifest->catalog_hash().ToString().c_str(), | |
| 155 | ✗ | base_hash.ToString().c_str()); | |
| 156 | ✗ | return NULL; | |
| 157 | } | ||
| 158 | |||
| 159 | // return the fetched manifest (releasing pointer ownership) | ||
| 160 | ✗ | return manifest.Release(); | |
| 161 | } | ||
| 162 | |||
| 163 | ✗ | manifest::Reflog *ServerTool::CreateEmptyReflog( | |
| 164 | const std::string &temp_directory, const std::string &repo_name) { | ||
| 165 | // create a new Reflog if there was none found yet | ||
| 166 | ✗ | const std::string tmp_path_prefix = temp_directory + "/new_reflog"; | |
| 167 | ✗ | const std::string tmp_path = CreateTempPath(tmp_path_prefix, 0600); | |
| 168 | |||
| 169 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug, "creating new reflog '%s' for %s", | |
| 170 | tmp_path.c_str(), repo_name.c_str()); | ||
| 171 | ✗ | return manifest::Reflog::Create(tmp_path, repo_name); | |
| 172 | } | ||
| 173 |