Commit 7dabbf60 authored by Zonr Chang's avatar Zonr Chang Committed by Facebook Github Bot

Add FOLLY_OPENSSL_HAS_ALPN and FOLLY_OPENSSL_HAS_SNI.

Summary:
This expresses the intention of long predicate on OpenSSL version and
OPENSSL_NO_TLSEXT more clearly.

This also enables ALPN and SNI support when BoringSSL is in use.

ALPN is an essential function to make HTTP/2 work when building Proxygen
with BoringSSL.
Closes https://github.com/facebook/folly/pull/534

Reviewed By: Orvid

Differential Revision: D4375391

Pulled By: yfeldblum

fbshipit-source-id: 009f311bceb0ee911d904d96a3e678a5f7241575
parent 827187dc
......@@ -234,7 +234,7 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
}
}
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
/**
* Create a client AsyncSSLSocket and allow tlsext_hostname
* to be sent in Client Hello.
......@@ -258,7 +258,7 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
AsyncSSLSocket(ctx, evb, fd, false, deferSecurityNegotiation) {
tlsextHostname_ = serverName;
}
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
AsyncSSLSocket::~AsyncSSLSocket() {
VLOG(3) << "actual destruction of AsyncSSLSocket(this=" << this
......@@ -519,7 +519,7 @@ void AsyncSSLSocket::detachSSLContext() {
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
void AsyncSSLSocket::switchServerSSLContext(
const std::shared_ptr<SSLContext>& handshakeCtx) {
CHECK(server_);
......@@ -560,7 +560,7 @@ void AsyncSSLSocket::setServerName(std::string serverName) noexcept {
tlsextHostname_ = std::move(serverName);
}
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
void AsyncSSLSocket::timeoutExpired() noexcept {
if (state_ == StateEnum::ESTABLISHED &&
......@@ -736,7 +736,7 @@ void AsyncSSLSocket::sslConn(
SSL_SESSION_free(sslSession_);
sslSession_ = nullptr;
}
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
if (tlsextHostname_.size()) {
SSL_set_tlsext_host_name(ssl_, tlsextHostname_.c_str());
}
......@@ -797,7 +797,7 @@ bool AsyncSSLSocket::getSelectedNextProtocolNoThrow(
SSLContext::NextProtocolType* protoType) const {
*protoName = nullptr;
*protoLen = 0;
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
SSL_get0_alpn_selected(ssl_, protoName, protoLen);
if (*protoLen > 0) {
if (protoType) {
......
......@@ -32,6 +32,7 @@
#include <folly/Bits.h>
#include <folly/io/IOBuf.h>
#include <folly/io/Cursor.h>
#include <folly/portability/OpenSSL.h>
#include <folly/portability/Sockets.h>
namespace folly {
......@@ -202,7 +203,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
}
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
/**
* Create a client AsyncSSLSocket with tlsext_servername in
* the Client Hello message.
......@@ -242,7 +243,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
new AsyncSSLSocket(ctx, evb, serverName, deferSecurityNegotiation),
Destructor());
}
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
/**
* TODO: implement support for SSL renegotiation.
......@@ -518,7 +519,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
void detachSSLContext();
#endif
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
/**
* Switch the SSLContext to continue the SSL handshake.
* It can only be used in server mode.
......@@ -541,7 +542,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
* ClientHello message.
*/
void setServerName(std::string serverName) noexcept;
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
void timeoutExpired() noexcept;
......@@ -790,7 +791,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
// When openssl is about to sendmsg() across the minEorRawBytesNo_,
// it will pass MSG_EOR to sendmsg().
size_t minEorRawByteNo_{0};
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
std::shared_ptr<folly::SSLContext> handshakeCtx_;
std::string tlsextHostname_;
#endif
......
......@@ -87,7 +87,7 @@ SSLContext::SSLContext(SSLVersion version) {
SSL_CTX_set_options(ctx_, SSL_OP_NO_COMPRESSION);
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
SSL_CTX_set_tlsext_servername_callback(ctx_, baseServerNameOpenSSLCallback);
SSL_CTX_set_tlsext_servername_arg(ctx_, this);
#endif
......@@ -371,7 +371,7 @@ void SSLContext::passwordCollector(std::shared_ptr<PasswordCollector> collector)
SSL_CTX_set_default_passwd_cb_userdata(ctx_, this);
}
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
void SSLContext::setServerNameCallback(const ServerNameCallback& cb) {
serverNameCb_ = cb;
......@@ -466,9 +466,9 @@ void SSLContext::switchCiphersIfTLS11(
SSL_set_cipher_list(ssl, providedCiphersString_.c_str());
}
}
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
int SSLContext::alpnSelectCallback(SSL* /* ssl */,
const unsigned char** out,
unsigned char* outlen,
......@@ -494,7 +494,7 @@ int SSLContext::alpnSelectCallback(SSL* /* ssl */,
}
return SSL_TLSEXT_ERR_OK;
}
#endif
#endif // FOLLY_OPENSSL_HAS_ALPN
#ifdef OPENSSL_NPN_NEGOTIATED
......@@ -552,7 +552,7 @@ bool SSLContext::setRandomizedAdvertisedNextProtocols(
ctx_, advertisedNextProtocolCallback, this);
SSL_CTX_set_next_proto_select_cb(ctx_, selectNextProtocolCallback, this);
}
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
if ((uint8_t)protocolType & (uint8_t)NextProtocolType::ALPN) {
SSL_CTX_set_alpn_select_cb(ctx_, alpnSelectCallback, this);
// Client cannot really use randomized alpn
......@@ -576,7 +576,7 @@ void SSLContext::unsetNextProtocols() {
deleteNextProtocolsStrings();
SSL_CTX_set_next_protos_advertised_cb(ctx_, nullptr, nullptr);
SSL_CTX_set_next_proto_select_cb(ctx_, nullptr, nullptr);
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
SSL_CTX_set_alpn_select_cb(ctx_, nullptr, nullptr);
SSL_CTX_set_alpn_protos(ctx_, nullptr, 0);
#endif
......
......@@ -283,7 +283,7 @@ class SSLContext {
virtual std::shared_ptr<PasswordCollector> passwordCollector() {
return collector_;
}
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
/**
* Provide SNI support
*/
......@@ -336,7 +336,7 @@ class SSLContext {
*/
typedef std::function<void(SSL* ssl)> ClientHelloCallback;
virtual void addClientHelloCallback(const ClientHelloCallback& cb);
#endif
#endif // FOLLY_OPENSSL_HAS_SNI
/**
* Create an SSL object from this context.
......@@ -519,7 +519,7 @@ class SSLContext {
bool checkPeerName_;
std::string peerFixedName_;
std::shared_ptr<PasswordCollector> collector_;
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
ServerNameCallback serverNameCb_;
std::vector<ClientHelloCallback> clientHelloCbs_;
#endif
......@@ -553,7 +553,7 @@ class SSLContext {
SSL* ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *server, unsigned int server_len, void *args);
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
static int alpnSelectCallback(SSL* ssl,
const unsigned char** out,
unsigned char* outlen,
......@@ -567,7 +567,7 @@ class SSLContext {
static int passwordCallback(char* password, int size, int, void* data);
#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_SNI
/**
* The function that will be called directly from openssl
* in order for the application to get the tlsext_hostname just after
......
......@@ -23,6 +23,7 @@
#include <folly/io/async/EventBase.h>
#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>
#include <folly/portability/OpenSSL.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Unistd.h>
......@@ -633,7 +634,7 @@ INSTANTIATE_TEST_CASE_P(
SSLContext::NextProtocolType::ANY,
SSLContext::NextProtocolType::ANY)));
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
INSTANTIATE_TEST_CASE_P(
AsyncSSLSocketTest,
NextProtocolTLSExtTest,
......@@ -655,7 +656,7 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(NextProtocolTypePair(SSLContext::NextProtocolType::NPN,
SSLContext::NextProtocolType::NPN)));
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
#if FOLLY_OPENSSL_HAS_ALPN
INSTANTIATE_TEST_CASE_P(
AsyncSSLSocketTest,
NextProtocolMismatchTest,
......
......@@ -35,6 +35,24 @@ namespace ssl {
#define FOLLY_OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
#endif // !defined(OPENSSL_IS_BORINGSSL)
// BoringSSL and OpenSSL 1.0.2 later with TLS extension support ALPN.
#if defined(OPENSSL_IS_BORINGSSL) || \
(OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
!defined(OPENSSL_NO_TLSEXT))
#define FOLLY_OPENSSL_HAS_ALPN 1
#else
#define FOLLY_OPENSSL_HAS_ALPN 0
#endif
// BoringSSL and OpenSSL 0.9.8f later with TLS extension support SNI.
#if defined(OPENSSL_IS_BORINGSSL) || \
(OPENSSL_VERSION_NUMBER >= 0x00908070L && \
!defined(OPENSSL_NO_TLSEXT))
#define FOLLY_OPENSSL_HAS_SNI 1
#else
#define FOLLY_OPENSSL_HAS_SNI 0
#endif
// This class attempts to "unify" the OpenSSL libssl APIs between OpenSSL 1.0.2,
// 1.1.0 and BoringSSL. The general idea is to provide wrapper methods for 1.0.2
// which already exist in BoringSSL and 1.1.0, but there are few APIs such as
......
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