Commit 77f06ada authored by Mingtao Yang's avatar Mingtao Yang Committed by Facebook Github Bot

SSLContext::loadCertificateFromBufferPEM should load entire chain

Summary:
SSLContext::loadCertificate() loads a certificate chain with SSL_CTX_use_certificate_chain_file.

A method named SSLContext::loadCertificateFromBufferPEM() should have the same semantics.

Reviewed By: yfeldblum

Differential Revision: D13037752

fbshipit-source-id: da7b150065d2207421c6bba86d44ce5e2c57e1a9
parent df642f04
......@@ -248,6 +248,25 @@ void SSLContext::loadCertificateFromBufferPEM(folly::StringPiece cert) {
if (SSL_CTX_use_certificate(ctx_, x509.get()) == 0) {
throw std::runtime_error("SSL_CTX_use_certificate: " + getErrors());
}
// Any further X509 PEM blocks are treated as additional certificates in
// the certificate chain.
constexpr size_t kMaxCertChain = 64;
for (size_t i = 0; i < kMaxCertChain; i++) {
x509.reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
if (x509 == nullptr) {
ERR_clear_error();
return;
}
if (SSL_CTX_add1_chain_cert(ctx_, x509.get()) == 0) {
throw std::runtime_error("SSL_CTX_add0_chain_cert: " + getErrors());
}
}
throw std::runtime_error(
"loadCertificateFromBufferPEM(): Too many certificates in chain");
}
void SSLContext::loadPrivateKey(const char* path, const char* format) {
......
......@@ -288,14 +288,16 @@ class SSLContext {
bool checkPeerName,
const std::string& peerName = std::string());
/**
* Load server certificate.
* Loads a certificate chain stored on disk to be sent to the peer during
* TLS connection establishment.
*
* @param path Path to the certificate file
* @param format Certificate file format
*/
virtual void loadCertificate(const char* path, const char* format = "PEM");
/**
* Load server certificate from memory.
* Loads a PEM formatted certificate chain from memory to be sent to the peer
* during TLS connection establishment.
*
* @param cert A PEM formatted certificate
*/
......
......@@ -137,4 +137,31 @@ TEST_F(SSLContextTest, TestLoadCertKey) {
tmpCtx.loadCertKeyPairFromFiles(certPath, keyPath);
}
}
TEST_F(SSLContextTest, TestLoadCertificateChain) {
constexpr auto kCertChainPath = "folly/io/async/test/certs/client_chain.pem";
std::unique_ptr<SSLContext> ctx;
STACK_OF(X509) * stack;
SSL_CTX* sctx;
std::string contents;
EXPECT_TRUE(folly::readFile(kCertChainPath, contents));
ctx = std::make_unique<SSLContext>();
ctx->loadCertificate(kCertChainPath, "PEM");
stack = nullptr;
sctx = ctx->getSSLCtx();
SSL_CTX_get0_chain_certs(sctx, &stack);
ASSERT_NE(stack, nullptr);
EXPECT_EQ(1, sk_X509_num(stack));
ctx = std::make_unique<SSLContext>();
ctx->loadCertificateFromBufferPEM(contents);
stack = nullptr;
sctx = ctx->getSSLCtx();
SSL_CTX_get0_chain_certs(sctx, &stack);
ASSERT_NE(stack, nullptr);
EXPECT_EQ(1, sk_X509_num(stack));
}
} // namespace folly
-----BEGIN CERTIFICATE-----
MIICVzCCAf2gAwIBAgIUB/qVvTbWZsztr6u/wXwjmEnXz+swCgYIKoZIzj0EAwIw
TDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
c2NvMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwHhcNMTgxMTEzMDE0MzAwWhcN
MTkxMTEzMDE0MzAwWjBNMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNV
BAcTDVNhbiBGcmFuY2lzY28xGTAXBgNVBAMTEGxlYWYuZXhhbXBsZS5uZXQwWTAT
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARRiN/3qvao/w5Th8VKoDXPpie83L1R2Pvy
p7foZ1ZrL9pc4GzX4ySWYAWGWyy5c2SdEViCyk3xzMJjJSPhmpoCo4G7MIG4MA4G
A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD
VR0TAQH/BAIwADAdBgNVHQ4EFgQURh82WDnSPqkvNqKGz6yPm2l2fnYwHwYDVR0j
BBgwFoAUKOEhuE+Vl0OihP80sAf8mQnZ1VkwOQYDVR0RBDIwMIILZXhhbXBsZS5u
ZXSCD3d3dy5leGFtcGxlLm5ldIIQbGVhZi5leGFtcGxlLm5ldDAKBggqhkjOPQQD
AgNIADBFAiEApbOwJiXXyvaq0mJOXUOSCxLXHlgcw6Kni2ObVRTofmgCIFQxxCsk
mXwjMzhBO1V0iv8bwais/ZtD9L99tyRCQPvW
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB2zCCAYKgAwIBAgIUUUublA7fgBvQ5kTGcp6ch/SrnAEwCgYIKoZIzj0EAwIw
TDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
c2NvMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwHhcNMTgxMTEzMDE0MTAwWhcN
MjMxMTEyMDE0MTAwWjBMMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNV
BAcTDVNhbiBGcmFuY2lzY28xGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTBZMBMG
ByqGSM49AgEGCCqGSM49AwEHA0IABC4WqVy2GthTC157KiQ3ojizm7p4gD5H1XMZ
sGXW1T+9UMVlTiQEPr/F36lbw+Gts01ApkeE13nbKUZeqRZDIvqjQjBAMA4GA1Ud
DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQo4SG4T5WXQ6KE
/zSwB/yZCdnVWTAKBggqhkjOPQQDAgNHADBEAiATD0cfB4Nf/g9hF3GOHxPE6QUe
w8MeJlMRwkUsblabhwIgZVLqoRNY3UVLQwl7kBj2nwZ0217Cmr6aOEAVR9A2I6U=
-----END CERTIFICATE-----
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment