diff --git a/fizz/protocol/DefaultCertificateVerifier.cpp b/fizz/protocol/DefaultCertificateVerifier.cpp index 190c29f86fd..3e36ccc16bd 100644 --- a/fizz/protocol/DefaultCertificateVerifier.cpp +++ b/fizz/protocol/DefaultCertificateVerifier.cpp @@ -49,6 +49,14 @@ DefaultCertificateVerifier::createFromCAFiles( std::shared_ptr DefaultCertificateVerifier::verify( const std::vector>& certs) const { + std::ignore = verifyWithX509StoreCtx(certs); + // Just return the original cert in the default case + return certs.front(); +} + +folly::ssl::X509StoreCtxUniquePtr +DefaultCertificateVerifier::verifyWithX509StoreCtx( + const std::vector>& certs) const { if (certs.empty()) { throw std::runtime_error("no certificates to verify"); } @@ -118,8 +126,7 @@ DefaultCertificateVerifier::verify( throw std::runtime_error("certificate verification failed: " + errorText); } - // Just return the original cert in the default case - return certs.front(); + return ctx; } void DefaultCertificateVerifier::createAuthorities() { diff --git a/fizz/protocol/DefaultCertificateVerifier.h b/fizz/protocol/DefaultCertificateVerifier.h index 5924a9832a2..4fa834ee1c5 100644 --- a/fizz/protocol/DefaultCertificateVerifier.h +++ b/fizz/protocol/DefaultCertificateVerifier.h @@ -9,6 +9,7 @@ #pragma once #include +#include namespace fizz { @@ -45,6 +46,14 @@ class DefaultCertificateVerifier : public CertificateVerifier { const std::vector>& certs) const override; + /** + * Return a std::unique_ptr to X509_STORE_CTX which is used for verifying + * the certificate chain. Additional verification result can be extracted + * from the returned store context. + */ + folly::ssl::X509StoreCtxUniquePtr verifyWithX509StoreCtx( + const std::vector>& certs) const; + void setCustomVerifyCallback(X509VerifyCallback cb) { customVerifyCallback_ = cb; } diff --git a/fizz/protocol/test/DefaultCertificateVerifierTest.cpp b/fizz/protocol/test/DefaultCertificateVerifierTest.cpp index 397e3e9132a..a9b5afe61a1 100644 --- a/fizz/protocol/test/DefaultCertificateVerifierTest.cpp +++ b/fizz/protocol/test/DefaultCertificateVerifierTest.cpp @@ -45,12 +45,25 @@ class DefaultCertificateVerifierTest : public testing::Test { TEST_F(DefaultCertificateVerifierTest, TestVerifySuccess) { verifier_->verify({getPeerCert(leafCertAndKey_)}); + + auto ctx = verifier_->verifyWithX509StoreCtx({getPeerCert(leafCertAndKey_)}); + STACK_OF(X509)* certChain = X509_STORE_CTX_get0_chain(ctx.get()); + X509* rootX509 = sk_X509_value(certChain, sk_X509_num(certChain) - 1); + auto rootCertName = folly::ssl::OpenSSLCertUtils::getCommonName(*rootX509); + EXPECT_EQ(rootCertName, "root"); } TEST_F(DefaultCertificateVerifierTest, TestVerifyWithIntermediates) { auto subauth = createCert("subauth", true, &rootCertAndKey_); auto subleaf = createCert("subleaf", false, &subauth); verifier_->verify({getPeerCert(subleaf), getPeerCert(subauth)}); + + auto ctx = verifier_->verifyWithX509StoreCtx( + {getPeerCert(subleaf), getPeerCert(subauth)}); + STACK_OF(X509)* certChain = X509_STORE_CTX_get0_chain(ctx.get()); + X509* rootX509 = sk_X509_value(certChain, sk_X509_num(certChain) - 1); + auto rootCertName = folly::ssl::OpenSSLCertUtils::getCommonName(*rootX509); + EXPECT_EQ(rootCertName, "root"); } TEST_F(DefaultCertificateVerifierTest, TestVerifySelfSignedCert) { @@ -66,6 +79,11 @@ TEST_F(DefaultCertificateVerifierTest, TestVerifySelfSignedCertWithOverride) { &DefaultCertificateVerifierTest::allowSelfSignedLeafCertCallback); // Will not throw because the override allows for this type of error. verifier_->verify({getPeerCert(selfsigned)}); + auto ctx = verifier_->verifyWithX509StoreCtx({getPeerCert(selfsigned)}); + STACK_OF(X509)* certChain = X509_STORE_CTX_get0_chain(ctx.get()); + X509* rootX509 = sk_X509_value(certChain, sk_X509_num(certChain) - 1); + auto rootCertName = folly::ssl::OpenSSLCertUtils::getCommonName(*rootX509); + EXPECT_EQ(rootCertName, "self"); } TEST_F(DefaultCertificateVerifierTest, TestVerifyWithIntermediateMissing) {