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