mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-22 11:46:13 +00:00
Give a redirect client the CAs its client trusts
With set_ca_cert_store() after load_ca_cert_store(), the redirect client trusted the earlier PEM too, though the store had replaced it, and of several load_ca_cert_store() calls it kept only the last. Take the CAs from the context when a store was set, and from every PEM loaded otherwise.
This commit is contained in:
1 parent
9724ea6b2e
commit
489fe8e504
2 files changed
+49
-6
No files matched your search
@@ -16168,17 +16168,19 @@ inline bool ClientImpl::create_redirect_client(
|
|||||||
redirect_client.system_ca_mode_ = system_ca_mode_;
|
redirect_client.system_ca_mode_ = system_ca_mode_;
|
||||||
|
|
||||||
// Transfer CA certificate to redirect client
|
// Transfer CA certificate to redirect client
|
||||||
redirect_client.load_ca_cert_store(ca_cert_pem_.c_str(),
|
|
||||||
ca_cert_pem_.size());
|
|
||||||
redirect_client.set_ca_cert_path(ca_cert_file_path_, ca_cert_dir_path_);
|
redirect_client.set_ca_cert_path(ca_cert_file_path_, ca_cert_dir_path_);
|
||||||
|
|
||||||
if (is_ssl()) {
|
if (is_ssl()) {
|
||||||
auto &self = static_cast<SSLClient &>(*this);
|
auto &self = static_cast<SSLClient &>(*this);
|
||||||
// A store given to set_ca_cert_store() lives only in this client's
|
// A store given to set_ca_cert_store() lives only in this client's
|
||||||
// context, so pass on the CA certificates the context holds.
|
// context, which then holds all that is trusted.
|
||||||
if (self.ca_cert_store_set_) {
|
if (self.ca_cert_store_set_) {
|
||||||
auto pem = detail::ca_certs_to_pem(self.ctx_);
|
auto pem = detail::ca_certs_to_pem(self.ctx_);
|
||||||
redirect_client.load_ca_cert_store(pem.data(), pem.size());
|
redirect_client.load_ca_cert_store(pem.data(), pem.size());
|
||||||
|
redirect_client.ca_cert_store_set_ = true;
|
||||||
|
} else {
|
||||||
|
redirect_client.load_ca_cert_store(ca_cert_pem_.c_str(),
|
||||||
|
ca_cert_pem_.size());
|
||||||
}
|
}
|
||||||
redirect_client.set_session_verifier(self.session_verifier_);
|
redirect_client.set_session_verifier(self.session_verifier_);
|
||||||
if (self.server_certificate_verifier_) {
|
if (self.server_certificate_verifier_) {
|
||||||
@@ -19051,7 +19053,11 @@ inline void SSLClient::enable_windows_certificate_verification(bool enabled) {
|
|||||||
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
||||||
std::size_t size) {
|
std::size_t size) {
|
||||||
if (ctx_ && ca_cert && size > 0) {
|
if (ctx_ && ca_cert && size > 0) {
|
||||||
ca_cert_pem_.assign(ca_cert, size); // Store for redirect transfer
|
// Every PEM loaded, for redirect transfer
|
||||||
|
if (!ca_cert_pem_.empty() && ca_cert_pem_.back() != '\n') {
|
||||||
|
ca_cert_pem_ += '\n';
|
||||||
|
}
|
||||||
|
ca_cert_pem_.append(ca_cert, size);
|
||||||
tls::load_ca_pem(ctx_, ca_cert, size);
|
tls::load_ca_pem(ctx_, ca_cert, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-2
@@ -17226,7 +17226,8 @@ TEST(SSLClientRedirectTest, CertFile) {
|
|||||||
// another port, so the client follows it with a new client.
|
// another port, so the client follows it with a new client.
|
||||||
static Result GetThroughTlsRedirectToDifferentPort(
|
static Result GetThroughTlsRedirectToDifferentPort(
|
||||||
const std::function<void(SSLClient &)> &setup,
|
const std::function<void(SSLClient &)> &setup,
|
||||||
const char *target_cert = SERVER_CERT2_FILE) {
|
const char *target_cert = SERVER_CERT2_FILE,
|
||||||
|
const char *target_key = SERVER_PRIVATE_KEY_FILE) {
|
||||||
auto ssl_port = PORT + 1;
|
auto ssl_port = PORT + 1;
|
||||||
|
|
||||||
SSLServer ssl_svr1(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
|
SSLServer ssl_svr1(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||||
@@ -17235,7 +17236,7 @@ static Result GetThroughTlsRedirectToDifferentPort(
|
|||||||
"/index");
|
"/index");
|
||||||
});
|
});
|
||||||
|
|
||||||
SSLServer ssl_svr2(target_cert, SERVER_PRIVATE_KEY_FILE);
|
SSLServer ssl_svr2(target_cert, target_key);
|
||||||
ssl_svr2.Get("/index", [&](const Request &, Response &res) {
|
ssl_svr2.Get("/index", [&](const Request &, Response &res) {
|
||||||
res.set_content("test", "text/plain");
|
res.set_content("test", "text/plain");
|
||||||
});
|
});
|
||||||
@@ -17299,6 +17300,42 @@ TEST(SSLClientRedirectTest, KeepCaCertStore) {
|
|||||||
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The target's certificate is signed by the root CA, which the first server's
|
||||||
|
// is not. Its name is not checked, as it carries none of 127.0.0.1.
|
||||||
|
TEST(SSLClientRedirectTest, KeepEveryCaCertPem) {
|
||||||
|
auto res = GetThroughTlsRedirectToDifferentPort(
|
||||||
|
[](SSLClient &cli) {
|
||||||
|
std::string root_ca, cert;
|
||||||
|
read_file(CLIENT_CA_CERT_FILE, root_ca);
|
||||||
|
read_file(SERVER_CERT2_FILE, cert);
|
||||||
|
cli.load_ca_cert_store(root_ca.data(), root_ca.size());
|
||||||
|
cli.load_ca_cert_store(cert.data(), cert.size());
|
||||||
|
cli.enable_server_hostname_verification(false);
|
||||||
|
},
|
||||||
|
CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
|
||||||
|
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
||||||
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_WOLFSSL_SUPPORT
|
||||||
|
// set_ca_cert_store() replaces the root CA loaded before it, so the target is
|
||||||
|
// not trusted after the redirect either. (wolfSSL adds the store instead.)
|
||||||
|
TEST(SSLClientRedirectTest, CaCertStoreReplacesEarlierPem) {
|
||||||
|
auto res = GetThroughTlsRedirectToDifferentPort(
|
||||||
|
[](SSLClient &cli) {
|
||||||
|
std::string root_ca, cert;
|
||||||
|
read_file(CLIENT_CA_CERT_FILE, root_ca);
|
||||||
|
read_file(SERVER_CERT2_FILE, cert);
|
||||||
|
cli.load_ca_cert_store(root_ca.data(), root_ca.size());
|
||||||
|
cli.set_ca_cert_store(tls::create_ca_store(cert.c_str(), cert.size()));
|
||||||
|
cli.enable_server_hostname_verification(false);
|
||||||
|
},
|
||||||
|
CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
|
||||||
|
ASSERT_FALSE(res);
|
||||||
|
EXPECT_EQ(Error::SSLServerVerification, res.error());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_SSL_ENABLED
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
||||||
|
|||||||
Reference in new issue
Block a user