Commit 0e0710e3 authored by Xiangyu Bu's avatar Xiangyu Bu Committed by Facebook Github Bot

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
parent 389f2c45
......@@ -87,30 +87,6 @@ void SSLContext::ciphers(const std::string& ciphers) {
setCiphersOrThrow(ciphers);
}
void SSLContext::setCipherList(const std::vector<std::string>& ciphers) {
if (ciphers.size() == 0) {
return;
}
std::string opensslCipherList;
join(":", ciphers, opensslCipherList);
setCiphersOrThrow(opensslCipherList);
}
void SSLContext::setSignatureAlgorithms(
const std::vector<std::string>& 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<std::string>& ecCurves) {
if (ecCurves.size() == 0) {
......
......@@ -32,6 +32,7 @@
#include <folly/Portability.h>
#include <folly/Range.h>
#include <folly/String.h>
#include <folly/io/async/ssl/OpenSSLUtils.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLLockTypes.h>
......@@ -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<std::string>& 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<std::string>& sigalgs);
template <typename Iterator>
void setCipherList(Iterator ibegin, Iterator iend) {
if (ibegin != iend) {
std::string opensslCipherList;
folly::join(":", ibegin, iend, opensslCipherList);
setCiphersOrThrow(opensslCipherList);
}
}
template <typename Container>
void setCipherList(const Container& cipherList) {
using namespace std;
setCipherList(begin(cipherList), end(cipherList));
}
template <typename Value>
void setCipherList(const std::initializer_list<Value>& cipherList) {
setCipherList(cipherList.begin(), cipherList.end());
}
/**
* Sets the signature algorithms to be used during SSL negotiation
* for TLS1.2+.
*/
template <typename Iterator>
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 <typename Container>
void setSignatureAlgorithms(const Container& sigalgs) {
using namespace std;
setSignatureAlgorithms(begin(sigalgs), end(sigalgs));
}
template <typename Value>
void setSignatureAlgorithms(const std::initializer_list<Value>& sigalgs) {
setSignatureAlgorithms(sigalgs.begin(), sigalgs.end());
}
/**
* Sets the list of EC curves supported by the client.
......
......@@ -14,43 +14,22 @@
* limitations under the License.
*/
#include "SSLOptions.h"
#include <folly/io/async/SSLOptions.h>
#include <folly/Format.h>
#include <folly/Logging.h>
namespace folly {
namespace ssl {
const std::vector<std::string>& SSLCommonOptions::getCipherList() {
static const std::vector<std::string> 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<std::string>& SSLCommonOptions::getSignatureAlgorithms() {
static const std::vector<std::string> kCommonSigAlgs = {
"RSA+SHA512",
"ECDSA+SHA512",
"RSA+SHA384",
"ECDSA+SHA384",
"RSA+SHA256",
"ECDSA+SHA256",
"RSA+SHA1",
"ECDSA+SHA1",
};
return kCommonSigAlgs;
}
constexpr std::array<const char*, 12> SSLCommonOptions::kCipherList;
constexpr std::array<const char*, 8> SSLCommonOptions::kSignatureAlgorithms;
void SSLCommonOptions::setClientOptions(SSLContext& ctx) {
#ifdef SSL_MODE_HANDSHAKE_CUTTHROUGH
ctx.enableFalseStart();
......
......@@ -16,25 +16,47 @@
#pragma once
#include <folly/Format.h>
#include <folly/Array.h>
#include <folly/io/async/SSLContext.h>
#include <glog/logging.h>
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<std::string>& 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<std::string>& 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 <typename TSSLOptions>
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 <typename TSSLOptions>
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);
}
}
......
......@@ -16,6 +16,7 @@
#include <folly/io/async/SSLContext.h>
#include <folly/portability/GTest.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
using namespace std;
using namespace testing;
......@@ -30,12 +31,11 @@ class SSLContextTest : public testing::Test {
void SSLContextTest::verifySSLCipherList(const vector<string>& 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) {
......
......@@ -26,18 +26,15 @@ namespace folly {
class SSLOptionsTest : public testing::Test {};
void verifySSLCipherList(SSLContext& ctx, const vector<string>& ciphers) {
TEST_F(SSLOptionsTest, TestSetCommonCipherList) {
SSLContext ctx;
ssl::setCipherSuites<ssl::SSLCommonOptions>(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<ssl::SSLCommonOptions>(ctx);
verifySSLCipherList(ctx, ssl::SSLCommonOptions::getCipherList());
}
}
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