Add FOLLY_OPENSSL_HAS_ALPN and FOLLY_OPENSSL_HAS_SNI.
authorZonr Chang <zonr.net@gmail.com>
Mon, 2 Jan 2017 00:24:34 +0000 (16:24 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 2 Jan 2017 00:32:56 +0000 (16:32 -0800)
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

folly/io/async/AsyncSSLSocket.cpp
folly/io/async/AsyncSSLSocket.h
folly/io/async/SSLContext.cpp
folly/io/async/SSLContext.h
folly/io/async/test/AsyncSSLSocketTest.cpp
folly/portability/OpenSSL.h

index a61e761770d493d6df17fb29a2f2301f68b2e64b..36acfc2aab2cd4fcb482f114473ecfebda418a92 100644 (file)
@@ -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) {
index 17bdd9c95fc153f4935d5fd8a18a3ac431aed637..39f8fe9ebb387fc24198f45a803080b98cde7153 100644 (file)
@@ -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
index ddb60e350bf9cf7906340ff0baab9b92baf301a1..b69c6e1d18a5f52c8c9dcf4339288918d1d2bbc5 100644 (file)
@@ -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
index 2b927c772cf1b64ef7c2d24af5785ce67bfd7509..8e62782f37e890f599b5544856b153026edd4b30 100644 (file)
@@ -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
index 30109874b12b69bc1ac6f480e422ecd78d8cfa9f..173564a957c8c18c61b8a4d5bdcd6df89aed02be 100644 (file)
@@ -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,
index 97ed213b21893c76f7e73a10395bd9a3294527b9..47bd9a07be639f6e01df31223edc6cc933913784 100644 (file)
@@ -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