From 0e0710e36a4350cbf7744cafc3cd688d61bb15f5 Mon Sep 17 00:00:00 2001 From: Xiangyu Bu Date: Fri, 18 Aug 2017 16:35:27 -0700 Subject: [PATCH] Let SSLContext::setCipherList accept generic container type. Summary: Make SSLContext::setCipherList() and SSLContext::setSignatureAlgorithms() accept std::array besides std::vector so that cipher lists in SSLOptions can be initialized POD. Reviewed By: yfeldblum Differential Revision: D5578758 fbshipit-source-id: 7e5c2e9a75600e93c89e7b13a9042434a4189384 --- folly/io/async/SSLContext.cpp | 24 ---------- folly/io/async/SSLContext.h | 63 +++++++++++++++++++++----- folly/io/async/SSLOptions.cpp | 39 ++++------------ folly/io/async/SSLOptions.h | 54 +++++++++++++++++----- folly/io/async/test/SSLContextTest.cpp | 8 ++-- folly/io/async/test/SSLOptionsTest.cpp | 15 +++--- 6 files changed, 113 insertions(+), 90 deletions(-) diff --git a/folly/io/async/SSLContext.cpp b/folly/io/async/SSLContext.cpp index 45936d0c..58f6defa 100644 --- a/folly/io/async/SSLContext.cpp +++ b/folly/io/async/SSLContext.cpp @@ -87,30 +87,6 @@ void SSLContext::ciphers(const std::string& ciphers) { setCiphersOrThrow(ciphers); } -void SSLContext::setCipherList(const std::vector& ciphers) { - if (ciphers.size() == 0) { - return; - } - std::string opensslCipherList; - join(":", ciphers, opensslCipherList); - setCiphersOrThrow(opensslCipherList); -} - -void SSLContext::setSignatureAlgorithms( - const std::vector& sigalgs) { - if (sigalgs.size() == 0) { - return; - } -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL - std::string opensslSigAlgsList; - join(":", sigalgs, opensslSigAlgsList); - int rc = SSL_CTX_set1_sigalgs_list(ctx_, opensslSigAlgsList.c_str()); - if (rc == 0) { - throw std::runtime_error("SSL_CTX_set1_sigalgs_list " + getErrors()); - } -#endif -} - void SSLContext::setClientECCurvesList( const std::vector& ecCurves) { if (ecCurves.size() == 0) { diff --git a/folly/io/async/SSLContext.h b/folly/io/async/SSLContext.h index d556806f..4e507714 100644 --- a/folly/io/async/SSLContext.h +++ b/folly/io/async/SSLContext.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -130,13 +131,6 @@ class SSLContext { */ virtual void ciphers(const std::string& ciphers); - /** - * Set default ciphers to be used in SSL handshake process. - * - * @param ciphers A list of ciphers to use for TLS. - */ - virtual void setCipherList(const std::vector& ciphers); - /** * Low-level method that attempts to set the provided ciphers on the * SSL_CTX object, and throws if something goes wrong. @@ -144,12 +138,57 @@ class SSLContext { virtual void setCiphersOrThrow(const std::string& ciphers); /** - * Sets the signature algorithms to be used during SSL negotiation - * for TLS1.2+ - * - * @param sigalgs A list of signature algorithms, eg. RSA+SHA512 + * Set default ciphers to be used in SSL handshake process. */ - void setSignatureAlgorithms(const std::vector& sigalgs); + + template + void setCipherList(Iterator ibegin, Iterator iend) { + if (ibegin != iend) { + std::string opensslCipherList; + folly::join(":", ibegin, iend, opensslCipherList); + setCiphersOrThrow(opensslCipherList); + } + } + + template + void setCipherList(const Container& cipherList) { + using namespace std; + setCipherList(begin(cipherList), end(cipherList)); + } + + template + void setCipherList(const std::initializer_list& cipherList) { + setCipherList(cipherList.begin(), cipherList.end()); + } + + /** + * Sets the signature algorithms to be used during SSL negotiation + * for TLS1.2+. + */ + + template + void setSignatureAlgorithms(Iterator ibegin, Iterator iend) { + if (ibegin != iend) { +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + std::string opensslSigAlgsList; + join(":", ibegin, iend, opensslSigAlgsList); + if (!SSL_CTX_set1_sigalgs_list(ctx_, opensslSigAlgsList.c_str())) { + throw std::runtime_error("SSL_CTX_set1_sigalgs_list " + getErrors()); + } +#endif + } + } + + template + void setSignatureAlgorithms(const Container& sigalgs) { + using namespace std; + setSignatureAlgorithms(begin(sigalgs), end(sigalgs)); + } + + template + void setSignatureAlgorithms(const std::initializer_list& sigalgs) { + setSignatureAlgorithms(sigalgs.begin(), sigalgs.end()); + } /** * Sets the list of EC curves supported by the client. diff --git a/folly/io/async/SSLOptions.cpp b/folly/io/async/SSLOptions.cpp index bada56c3..32f3ccb6 100644 --- a/folly/io/async/SSLOptions.cpp +++ b/folly/io/async/SSLOptions.cpp @@ -14,43 +14,22 @@ * limitations under the License. */ -#include "SSLOptions.h" +#include +#include +#include namespace folly { namespace ssl { -const std::vector& SSLCommonOptions::getCipherList() { - static const std::vector kCommonCipherList = { - "ECDHE-ECDSA-AES128-GCM-SHA256", - "ECDHE-RSA-AES128-GCM-SHA256", - "ECDHE-ECDSA-AES256-GCM-SHA384", - "ECDHE-RSA-AES256-GCM-SHA384", - "ECDHE-ECDSA-AES256-SHA", - "ECDHE-RSA-AES256-SHA", - "ECDHE-ECDSA-AES128-SHA", - "ECDHE-RSA-AES128-SHA", - "ECDHE-RSA-AES256-SHA384", - "AES128-GCM-SHA256", - "AES256-SHA", - "AES128-SHA", - }; - return kCommonCipherList; +namespace ssl_options_detail { +void logDfatal(std::exception const& e) { + LOG(DFATAL) << exceptionStr(e); } - -const std::vector& SSLCommonOptions::getSignatureAlgorithms() { - static const std::vector kCommonSigAlgs = { - "RSA+SHA512", - "ECDSA+SHA512", - "RSA+SHA384", - "ECDSA+SHA384", - "RSA+SHA256", - "ECDSA+SHA256", - "RSA+SHA1", - "ECDSA+SHA1", - }; - return kCommonSigAlgs; } +constexpr std::array SSLCommonOptions::kCipherList; +constexpr std::array SSLCommonOptions::kSignatureAlgorithms; + void SSLCommonOptions::setClientOptions(SSLContext& ctx) { #ifdef SSL_MODE_HANDSHAKE_CUTTHROUGH ctx.enableFalseStart(); diff --git a/folly/io/async/SSLOptions.h b/folly/io/async/SSLOptions.h index 963cad27..94dc8ed1 100644 --- a/folly/io/async/SSLOptions.h +++ b/folly/io/async/SSLOptions.h @@ -16,25 +16,47 @@ #pragma once -#include +#include #include -#include - namespace folly { namespace ssl { +namespace ssl_options_detail { +void logDfatal(std::exception const&); +} + struct SSLCommonOptions { /** - * Return the cipher list recommended for this options configuration. + * The cipher list recommended for this options configuration. */ - static const std::vector& getCipherList(); + static constexpr auto kCipherList = folly::make_array( + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES256-SHA", + "ECDHE-RSA-AES256-SHA", + "ECDHE-ECDSA-AES128-SHA", + "ECDHE-RSA-AES128-SHA", + "ECDHE-RSA-AES256-SHA384", + "AES128-GCM-SHA256", + "AES256-SHA", + "AES128-SHA"); /** - * Return the list of signature algorithms recommended for this options + * The list of signature algorithms recommended for this options * configuration. */ - static const std::vector& getSignatureAlgorithms(); + static constexpr auto kSignatureAlgorithms = folly::make_array( + "RSA+SHA512", + "ECDSA+SHA512", + "RSA+SHA384", + "ECDSA+SHA384", + "RSA+SHA256", + "ECDSA+SHA256", + "RSA+SHA1", + "ECDSA+SHA1"); /** * Set common parameters on a client SSL context, for example, @@ -44,21 +66,31 @@ struct SSLCommonOptions { static void setClientOptions(SSLContext& ctx); }; +/** + * Set the cipher suite of ctx to that in TSSLOptions, and print any runtime + * error it catches. + * @param ctx The SSLContext to apply the desired SSL options to. + */ template void setCipherSuites(SSLContext& ctx) { try { - ctx.setCipherList(TSSLOptions::getCipherList()); + ctx.setCipherList(TSSLOptions::kCipherList); } catch (std::runtime_error const& e) { - LOG(DFATAL) << exceptionStr(e); + ssl_options_detail::logDfatal(e); } } +/** + * Set the signature algorithm list of ctx to that in TSSLOptions, and print + * any runtime errors it catche. + * @param ctx The SSLContext to apply the desired SSL options to. + */ template void setSignatureAlgorithms(SSLContext& ctx) { try { - ctx.setSignatureAlgorithms(TSSLOptions::getSignatureAlgorithms()); + ctx.setSignatureAlgorithms(TSSLOptions::kSignatureAlgorithms); } catch (std::runtime_error const& e) { - LOG(DFATAL) << exceptionStr(e); + ssl_options_detail::logDfatal(e); } } diff --git a/folly/io/async/test/SSLContextTest.cpp b/folly/io/async/test/SSLContextTest.cpp index 98f6467c..7ecf0553 100644 --- a/folly/io/async/test/SSLContextTest.cpp +++ b/folly/io/async/test/SSLContextTest.cpp @@ -16,6 +16,7 @@ #include #include +#include using namespace std; using namespace testing; @@ -30,12 +31,11 @@ class SSLContextTest : public testing::Test { void SSLContextTest::verifySSLCipherList(const vector& ciphers) { int i = 0; - SSL* ssl = ctx.createSSL(); + ssl::SSLUniquePtr ssl(ctx.createSSL()); for (auto& cipher : ciphers) { - ASSERT_STREQ(cipher.c_str(), SSL_get_cipher_list(ssl, i++)); + ASSERT_STREQ(cipher.c_str(), SSL_get_cipher_list(ssl.get(), i++)); } - ASSERT_EQ(nullptr, SSL_get_cipher_list(ssl, i)); - SSL_free(ssl); + ASSERT_EQ(nullptr, SSL_get_cipher_list(ssl.get(), i)); } TEST_F(SSLContextTest, TestSetCipherString) { diff --git a/folly/io/async/test/SSLOptionsTest.cpp b/folly/io/async/test/SSLOptionsTest.cpp index f0c8f974..471f9313 100644 --- a/folly/io/async/test/SSLOptionsTest.cpp +++ b/folly/io/async/test/SSLOptionsTest.cpp @@ -26,18 +26,15 @@ namespace folly { class SSLOptionsTest : public testing::Test {}; -void verifySSLCipherList(SSLContext& ctx, const vector& ciphers) { +TEST_F(SSLOptionsTest, TestSetCommonCipherList) { + SSLContext ctx; + ssl::setCipherSuites(ctx); + int i = 0; ssl::SSLUniquePtr ssl(ctx.createSSL()); - for (auto& cipher : ciphers) { - ASSERT_STREQ(cipher.c_str(), SSL_get_cipher_list(ssl.get(), i++)); + for (auto& cipher : ssl::SSLCommonOptions::kCipherList) { + ASSERT_STREQ(cipher, SSL_get_cipher_list(ssl.get(), i++)); } ASSERT_EQ(nullptr, SSL_get_cipher_list(ssl.get(), i)); } - -TEST_F(SSLOptionsTest, TestSetCommonCipherList) { - SSLContext ctx; - ssl::setCipherSuites(ctx); - verifySSLCipherList(ctx, ssl::SSLCommonOptions::getCipherList()); -} } -- 2.34.1