summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/net/tls/openssl_impl/openssl_impl_test.cpp47
1 files changed, 45 insertions, 2 deletions
diff --git a/vespalib/src/tests/net/tls/openssl_impl/openssl_impl_test.cpp b/vespalib/src/tests/net/tls/openssl_impl/openssl_impl_test.cpp
index a75c7dff150..6d5c5fa6308 100644
--- a/vespalib/src/tests/net/tls/openssl_impl/openssl_impl_test.cpp
+++ b/vespalib/src/tests/net/tls/openssl_impl/openssl_impl_test.cpp
@@ -455,8 +455,8 @@ struct CertFixture : Fixture {
{}
~CertFixture();
- CertKeyWrapper create_ca_issued_peer_cert(const std::vector<vespalib::string>& common_names,
- const std::vector<vespalib::string>& sans) {
+ static X509Certificate::SubjectInfo make_subject_info(const std::vector<vespalib::string>& common_names,
+ const std::vector<vespalib::string>& sans) {
auto dn = X509Certificate::DistinguishedName()
.country("US").state("CA").locality("Sunnyvale")
.organization("Wile E. Coyote, Ltd.")
@@ -468,12 +468,27 @@ struct CertFixture : Fixture {
for (auto& san : sans) {
subject.add_subject_alt_name(san);
}
+ return subject;
+ }
+
+ CertKeyWrapper create_ca_issued_peer_cert(const std::vector<vespalib::string>& common_names,
+ const std::vector<vespalib::string>& sans) const {
+ auto subject = make_subject_info(common_names, sans);
auto key = PrivateKey::generate_p256_ec_key();
auto params = X509Certificate::Params::issued_by(std::move(subject), key, root_ca.cert, root_ca.key);
auto cert = X509Certificate::generate_from(std::move(params));
return {std::move(cert), std::move(key)};
}
+ CertKeyWrapper create_self_signed_peer_cert(const std::vector<vespalib::string>& common_names,
+ const std::vector<vespalib::string>& sans) const {
+ auto subject = make_subject_info(common_names, sans);
+ auto key = PrivateKey::generate_p256_ec_key();
+ auto params = X509Certificate::Params::self_signed(std::move(subject), key);
+ auto cert = X509Certificate::generate_from(std::move(params));
+ return {std::move(cert), std::move(key)};
+ }
+
static std::unique_ptr<OpenSslCryptoCodecImpl> create_openssl_codec_with_authz_mode(
const TransportSecurityOptions& opts,
std::shared_ptr<CertificateVerificationCallback> cert_verify_callback,
@@ -663,6 +678,34 @@ TEST_F("Only DNS and URI SANs are enumerated", CertFixture) {
EXPECT_EQUAL(0u, server_cb->creds.uri_sans.size());
}
+// A server must only trust the actual verified peer certificate, not any other random
+// certificate that the client decides to include in its certificate chain. See CVE-2023-2422.
+// Note: this is a preemptive test; we are not--and have never been--vulnerable to this issue.
+TEST_F("Certificate credential extraction is not vulnerable to CVE-2023-2422", CertFixture) {
+ auto good_ck = f.create_ca_issued_peer_cert({}, {{"DNS:legit.example.com"}});
+ auto evil_ck = f.create_self_signed_peer_cert({"rudolf.example.com"}, {{"DNS:blodstrupmoen.example.com"}});
+
+ auto ts_params = TransportSecurityOptions::Params().
+ ca_certs_pem(f.root_ca.cert->to_pem()).
+ // Concatenate CA-signed good cert with self-signed cert with different credentials.
+ // We should only ever look at the good cert.
+ cert_chain_pem(good_ck.cert->to_pem() + evil_ck.cert->to_pem()).
+ private_key_pem(good_ck.key->private_to_pem() + evil_ck.key->private_to_pem()).
+ authorized_peers(AuthorizedPeers::allow_all_authenticated());
+
+ f.client = f.create_openssl_codec(TransportSecurityOptions(std::move(ts_params)),
+ std::make_shared<PrintingCertificateCallback>(),
+ CryptoCodec::Mode::Client);
+ auto server_cb = std::make_shared<MockCertificateCallback>();
+ f.reset_server_with_cert_opts(good_ck, server_cb);
+ ASSERT_TRUE(f.handshake());
+
+ auto& creds = server_cb->creds;
+ EXPECT_EQUAL("", creds.common_name);
+ ASSERT_EQUAL(1u, creds.dns_sans.size());
+ EXPECT_EQUAL("legit.example.com", creds.dns_sans[0]);
+}
+
// We don't test too many combinations of peer policies here, only that
// the wiring is set up. Verification logic is tested elsewhere.