Add OpenSSL portability layer
authorAnirudh Ramachandran <avr@fb.com>
Thu, 29 Dec 2016 02:54:04 +0000 (18:54 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 29 Dec 2016 03:03:37 +0000 (19:03 -0800)
Summary:
Enable folly to build with OpenSSL alternatives (e.g., BoringSSL).

Some SSL-related tests are disabled:

 - Async session cache ones (BoringSSL has an async cache impl but with a different API)
 - TFO tests
 - Some changes to error tests which expect specific error strings. This is
   flaky as a test because it will break everytime even within a version, so we
   should fix that first.

This should be a noop for OpenSSL 1.0.2.

BoringSSL commit used is 35c8afd3143289c99aa3820e01950c564d7aced8 (10/26/2016)

Closes: https://github.com/facebook/folly/issues/198
Reviewed By: siyengar

Differential Revision: D3280382

fbshipit-source-id: 4141d992e0d8dd797ac4af479cfe90844a23278f

15 files changed:
folly/Makefile.am
folly/io/async/AsyncSSLSocket.cpp
folly/io/async/SSLContext.cpp
folly/io/async/SSLContext.h
folly/io/async/ssl/OpenSSLUtils.cpp
folly/io/async/ssl/test/SSLErrorsTest.cpp
folly/io/async/test/AsyncSSLSocketTest.cpp
folly/io/async/test/AsyncSSLSocketTest.h
folly/io/async/test/AsyncSSLSocketTest2.cpp
folly/portability/OpenSSL.cpp [new file with mode: 0644]
folly/portability/OpenSSL.h [new file with mode: 0644]
folly/ssl/OpenSSLVersionFinder.h [new file with mode: 0644]
folly/ssl/SSLSession.h
folly/ssl/detail/OpenSSLVersionFinder.h [deleted file]
folly/ssl/detail/SSLSessionImpl.cpp

index 6c6d4baf2540134e85b00f348961ff616359b656..d0416648b6aff1b6f9ccf0ee1230367a32427db4 100644 (file)
@@ -295,6 +295,7 @@ nobase_follyinclude_HEADERS = \
        portability/Malloc.h \
        portability/Math.h \
        portability/Memory.h \
        portability/Malloc.h \
        portability/Math.h \
        portability/Memory.h \
+       portability/OpenSSL.h \
        portability/PThread.h \
        portability/Sockets.h \
        portability/Stdio.h \
        portability/PThread.h \
        portability/Sockets.h \
        portability/Stdio.h \
@@ -336,8 +337,8 @@ nobase_follyinclude_HEADERS = \
        SpookyHashV1.h \
        SpookyHashV2.h \
        ssl/OpenSSLHash.h \
        SpookyHashV1.h \
        SpookyHashV2.h \
        ssl/OpenSSLHash.h \
+       ssl/OpenSSLVersionFinder.h \
        ssl/SSLSession.h \
        ssl/SSLSession.h \
-       ssl/detail/OpenSSLVersionFinder.h \
        ssl/detail/SSLSessionImpl.h \
        stats/BucketedTimeSeries-defs.h \
        stats/BucketedTimeSeries.h \
        ssl/detail/SSLSessionImpl.h \
        stats/BucketedTimeSeries-defs.h \
        stats/BucketedTimeSeries.h \
@@ -477,6 +478,7 @@ libfolly_la_SOURCES = \
        portability/Libgen.cpp \
        portability/Malloc.cpp \
        portability/Memory.cpp \
        portability/Libgen.cpp \
        portability/Malloc.cpp \
        portability/Memory.cpp \
+       portability/OpenSSL.cpp \
        portability/Sockets.cpp \
        portability/Stdio.cpp \
        portability/Stdlib.cpp \
        portability/Sockets.cpp \
        portability/Stdio.cpp \
        portability/Stdlib.cpp \
index 7b22c3d293d9615a9bf5e74c75b1e2ded70522d1..a61e761770d493d6df17fb29a2f2301f68b2e64b 100644 (file)
@@ -31,8 +31,9 @@
 #include <folly/Bits.h>
 #include <folly/SocketAddress.h>
 #include <folly/SpinLock.h>
 #include <folly/Bits.h>
 #include <folly/SocketAddress.h>
 #include <folly/SpinLock.h>
-#include <folly/io/IOBuf.h>
 #include <folly/io/Cursor.h>
 #include <folly/io/Cursor.h>
+#include <folly/io/IOBuf.h>
+#include <folly/portability/OpenSSL.h>
 #include <folly/portability/Unistd.h>
 
 using folly::SocketAddress;
 #include <folly/portability/Unistd.h>
 
 using folly::SocketAddress;
@@ -54,6 +55,8 @@ using folly::AsyncSocketException;
 using folly::AsyncSSLSocket;
 using folly::Optional;
 using folly::SSLContext;
 using folly::AsyncSSLSocket;
 using folly::Optional;
 using folly::SSLContext;
+// For OpenSSL portability API
+using namespace folly::ssl;
 using folly::ssl::OpenSSLUtils;
 
 // We have one single dummy SSL context so that we can implement attach
 using folly::ssl::OpenSSLUtils;
 
 // We have one single dummy SSL context so that we can implement attach
@@ -475,8 +478,8 @@ void AsyncSSLSocket::attachSSLContext(
   // previously called.
   // We need to update the initial_ctx if necessary
   auto sslCtx = ctx->getSSLCtx();
   // previously called.
   // We need to update the initial_ctx if necessary
   auto sslCtx = ctx->getSSLCtx();
+  SSL_CTX_up_ref(sslCtx);
 #ifndef OPENSSL_NO_TLSEXT
 #ifndef OPENSSL_NO_TLSEXT
-  CRYPTO_add(&sslCtx->references, 1, CRYPTO_LOCK_SSL_CTX);
   // note that detachSSLContext has already freed ssl_->initial_ctx
   ssl_->initial_ctx = sslCtx;
 #endif
   // note that detachSSLContext has already freed ssl_->initial_ctx
   ssl_->initial_ctx = sslCtx;
 #endif
@@ -773,7 +776,8 @@ void AsyncSSLSocket::setSSLSession(SSL_SESSION *session, bool takeOwnership) {
   sslSession_ = session;
   if (!takeOwnership && session != nullptr) {
     // Increment the reference count
   sslSession_ = session;
   if (!takeOwnership && session != nullptr) {
     // Increment the reference count
-    CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+    // This API exists in BoringSSL and OpenSSL 1.1.0
+    SSL_SESSION_up_ref(session);
   }
 }
 
   }
 }
 
index 43703f2f3a083a02bf3bb66670fbe9793e4e4983..ddb60e350bf9cf7906340ff0baab9b92baf301a1 100644 (file)
@@ -35,6 +35,9 @@ struct CRYPTO_dynlock_value {
 };
 
 namespace folly {
 };
 
 namespace folly {
+//
+// For OpenSSL portability API
+using namespace folly::ssl;
 
 bool SSLContext::initialized_ = false;
 
 
 bool SSLContext::initialized_ = false;
 
index a8f18620e47377de4a71d993adcce9fcd641e0d3..2b927c772cf1b64ef7c2d24af5785ce67bfd7509 100644 (file)
@@ -25,6 +25,7 @@
 #include <random>
 
 // This has to come before SSL.
 #include <random>
 
 // This has to come before SSL.
+#include <folly/portability/OpenSSL.h>
 #include <folly/portability/Sockets.h>
 
 #include <openssl/ssl.h>
 #include <folly/portability/Sockets.h>
 
 #include <openssl/ssl.h>
index b2e9d8cb5dec2e938849feecbe5b9a282704726d..aa142f76fd6e2e67cf8d3e5f610dc182a7f79739 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include <folly/io/async/ssl/OpenSSLUtils.h>
 #include <folly/ScopeGuard.h>
  */
 #include <folly/io/async/ssl/OpenSSLUtils.h>
 #include <folly/ScopeGuard.h>
+#include <folly/portability/OpenSSL.h>
 #include <folly/portability/Sockets.h>
 #include <glog/logging.h>
 #include <openssl/bio.h>
 #include <folly/portability/Sockets.h>
 #include <glog/logging.h>
 #include <openssl/bio.h>
 #include <openssl/x509v3.h>
 #include <unordered_map>
 
 #include <openssl/x509v3.h>
 #include <unordered_map>
 
-#define OPENSSL_IS_101 (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
-                         OPENSSL_VERSION_NUMBER < 0x1000200fL)
-#define OPENSSL_IS_102 (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
-                        OPENSSL_VERSION_NUMBER < 0x10100000L)
-#define OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-
 namespace {
 #if defined(OPENSSL_IS_BORINGSSL)
 // BoringSSL doesn't (as of May 2016) export the equivalent
 namespace {
 #if defined(OPENSSL_IS_BORINGSSL)
 // BoringSSL doesn't (as of May 2016) export the equivalent
@@ -45,7 +40,7 @@ namespace ssl {
 bool OpenSSLUtils::getTLSMasterKey(
     const SSL_SESSION* session,
     MutableByteRange keyOut) {
 bool OpenSSLUtils::getTLSMasterKey(
     const SSL_SESSION* session,
     MutableByteRange keyOut) {
-#if OPENSSL_IS_101 || OPENSSL_IS_102
+#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102
   if (session &&
       session->master_key_length == static_cast<int>(keyOut.size())) {
     auto masterKey = session->master_key;
   if (session &&
       session->master_key_length == static_cast<int>(keyOut.size())) {
     auto masterKey = session->master_key;
@@ -53,6 +48,9 @@ bool OpenSSLUtils::getTLSMasterKey(
         masterKey, masterKey + session->master_key_length, keyOut.begin());
     return true;
   }
         masterKey, masterKey + session->master_key_length, keyOut.begin());
     return true;
   }
+#else
+  (SSL_SESSION*)session;
+  (MutableByteRange) keyOut;
 #endif
   return false;
 }
 #endif
   return false;
 }
@@ -60,13 +58,16 @@ bool OpenSSLUtils::getTLSMasterKey(
 bool OpenSSLUtils::getTLSClientRandom(
     const SSL* ssl,
     MutableByteRange randomOut) {
 bool OpenSSLUtils::getTLSClientRandom(
     const SSL* ssl,
     MutableByteRange randomOut) {
-#if OPENSSL_IS_101 || OPENSSL_IS_102
+#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102
   if ((SSL_version(ssl) >> 8) == TLS1_VERSION_MAJOR && ssl->s3 &&
       randomOut.size() == SSL3_RANDOM_SIZE) {
     auto clientRandom = ssl->s3->client_random;
     std::copy(clientRandom, clientRandom + SSL3_RANDOM_SIZE, randomOut.begin());
     return true;
   }
   if ((SSL_version(ssl) >> 8) == TLS1_VERSION_MAJOR && ssl->s3 &&
       randomOut.size() == SSL3_RANDOM_SIZE) {
     auto clientRandom = ssl->s3->client_random;
     std::copy(clientRandom, clientRandom + SSL3_RANDOM_SIZE, randomOut.begin());
     return true;
   }
+#else
+  (SSL*)ssl;
+  (MutableByteRange) randomOut;
 #endif
   return false;
 }
 #endif
   return false;
 }
@@ -121,7 +122,7 @@ bool OpenSSLUtils::validatePeerCertNames(X509* cert,
     }
   }
 
     }
   }
 
-  for (int i = 0; i < sk_GENERAL_NAME_num(altNames); i++) {
+  for (size_t i = 0; i < (size_t)sk_GENERAL_NAME_num(altNames); i++) {
     auto name = sk_GENERAL_NAME_value(altNames, i);
     if ((addr4 != nullptr || addr6 != nullptr) && name->type == GEN_IPADD) {
       // Extra const-ness for paranoia
     auto name = sk_GENERAL_NAME_value(altNames, i);
     if ((addr4 != nullptr || addr6 != nullptr) && name->type == GEN_IPADD) {
       // Extra const-ness for paranoia
@@ -199,13 +200,7 @@ bool OpenSSLUtils::setCustomBioReadMethod(
     BIO_METHOD* bioMeth,
     int (*meth)(BIO*, char*, int)) {
   bool ret = false;
     BIO_METHOD* bioMeth,
     int (*meth)(BIO*, char*, int)) {
   bool ret = false;
-#if OPENSSL_IS_110
   ret = (BIO_meth_set_read(bioMeth, meth) == 1);
   ret = (BIO_meth_set_read(bioMeth, meth) == 1);
-#elif (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_IS_101 || OPENSSL_IS_102)
-  bioMeth->bread = meth;
-  ret = true;
-#endif
-
   return ret;
 }
 
   return ret;
 }
 
@@ -213,13 +208,7 @@ bool OpenSSLUtils::setCustomBioWriteMethod(
     BIO_METHOD* bioMeth,
     int (*meth)(BIO*, const char*, int)) {
   bool ret = false;
     BIO_METHOD* bioMeth,
     int (*meth)(BIO*, const char*, int)) {
   bool ret = false;
-#if OPENSSL_IS_110
   ret = (BIO_meth_set_write(bioMeth, meth) == 1);
   ret = (BIO_meth_set_write(bioMeth, meth) == 1);
-#elif (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_IS_101 || OPENSSL_IS_102)
-  bioMeth->bwrite = meth;
-  ret = true;
-#endif
-
   return ret;
 }
 
   return ret;
 }
 
index 6643cf2e6883859e6634432f0aab5281f8c28465..b2cee3d3d7619dfc0cc385f69a2dd70cadf75d75 100644 (file)
@@ -26,15 +26,29 @@ using namespace folly;
 
 TEST(SSLErrorsTest, TestMessage) {
   ERR_load_crypto_strings();
 
 TEST(SSLErrorsTest, TestMessage) {
   ERR_load_crypto_strings();
-  auto err = ERR_PACK(
+  unsigned long err;
+#ifdef OPENSSL_IS_BORINGSSL
+  err = ERR_PACK(ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+#else
+  err = ERR_PACK(
       ERR_LIB_X509,
       X509_F_X509_STORE_ADD_CERT,
       X509_R_CERT_ALREADY_IN_HASH_TABLE);
       ERR_LIB_X509,
       X509_F_X509_STORE_ADD_CERT,
       X509_R_CERT_ALREADY_IN_HASH_TABLE);
+#endif
   SSLException ex(0, err, 0, 0);
   SSLException ex(0, err, 0, 0);
+
+// This is flaky - we should not be testing error strings
+// which may change version to version
+#if defined(OPENSSL_IS_BORINGSSL)
+  std::string expectedMsg =
+      "AsyncSocketException: error:0b000069:X.509 certificate routines:"
+      "OPENSSL_internal:CERT_ALREADY_IN_HASH_TABLE, type = SSL error";
+#else
   std::string expectedMsg =
       "AsyncSocketException: error:0B07C065:"
       "x509 certificate routines:X509_STORE_add_cert:"
       "cert already in hash table, type = SSL error";
   std::string expectedMsg =
       "AsyncSocketException: error:0B07C065:"
       "x509 certificate routines:X509_STORE_add_cert:"
       "cert already in hash table, type = SSL error";
+#endif
   std::string actual = ex.what();
   EXPECT_EQ(expectedMsg, actual);
 }
   std::string actual = ex.what();
   EXPECT_EQ(expectedMsg, actual);
 }
index 181a33451e226b0f227f9cc2b9688988a592ed7d..30109874b12b69bc1ac6f480e422ecd78d8cfa9f 100644 (file)
@@ -239,6 +239,7 @@ TEST(AsyncSSLSocketTest, ReadAfterClose) {
 /**
  * Test bad renegotiation
  */
 /**
  * Test bad renegotiation
  */
+#if !defined(OPENSSL_IS_BORINGSSL)
 TEST(AsyncSSLSocketTest, Renegotiate) {
   EventBase eventBase;
   auto clientCtx = std::make_shared<SSLContext>();
 TEST(AsyncSSLSocketTest, Renegotiate) {
   EventBase eventBase;
   auto clientCtx = std::make_shared<SSLContext>();
@@ -284,6 +285,7 @@ TEST(AsyncSSLSocketTest, Renegotiate) {
   eventBase.loop();
   ASSERT_TRUE(server.renegotiationError_);
 }
   eventBase.loop();
   ASSERT_TRUE(server.renegotiationError_);
 }
+#endif
 
 /**
  * Negative test for handshakeError().
 
 /**
  * Negative test for handshakeError().
@@ -549,7 +551,18 @@ TEST_P(NextProtocolTest, NpnTestNoOverlap) {
     // mismatch should result in a fatal alert, but this is OpenSSL's current
     // behavior and we want to know if it changes.
     expectNoProtocol();
     // mismatch should result in a fatal alert, but this is OpenSSL's current
     // behavior and we want to know if it changes.
     expectNoProtocol();
-  } else {
+  }
+#if defined(OPENSSL_IS_BORINGSSL)
+  // BoringSSL also doesn't fatal on mismatch but behaves slightly differently
+  // from OpenSSL 1.0.2h+ - it doesn't select a protocol if both ends support
+  // NPN *and* ALPN
+  else if (
+      GetParam().first == SSLContext::NextProtocolType::ANY &&
+      GetParam().second == SSLContext::NextProtocolType::ANY) {
+    expectNoProtocol();
+  }
+#endif
+  else {
     expectProtocol("blub");
     expectProtocolType(
         {SSLContext::NextProtocolType::NPN, SSLContext::NextProtocolType::NPN});
     expectProtocol("blub");
     expectProtocolType(
         {SSLContext::NextProtocolType::NPN, SSLContext::NextProtocolType::NPN});
@@ -877,7 +890,7 @@ TEST(AsyncSSLSocketTest, SSLClientTimeoutTest) {
   cerr << "SSLClientTimeoutTest test completed" << endl;
 }
 
   cerr << "SSLClientTimeoutTest test completed" << endl;
 }
 
-// This is a FB-only extension, and the tests will fail without it
+// The next 3 tests need an FB-only extension, and will fail without it
 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
 /**
  * Test SSL server async cache
 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
 /**
  * Test SSL server async cache
@@ -907,7 +920,6 @@ TEST(AsyncSSLSocketTest, SSLServerAsyncCacheTest) {
   cerr << "SSLServerAsyncCacheTest test completed" << endl;
 }
 
   cerr << "SSLServerAsyncCacheTest test completed" << endl;
 }
 
-
 /**
  * Test SSL server accept timeout with cache path
  */
 /**
  * Test SSL server accept timeout with cache path
  */
@@ -999,7 +1011,7 @@ TEST(AsyncSSLSocketTest, SSLServerCacheCloseTest) {
 
   cerr << "SSLServerCacheCloseTest test completed" << endl;
 }
 
   cerr << "SSLServerCacheCloseTest test completed" << endl;
 }
-#endif
+#endif // !SSL_ERROR_WANT_SESS_CACHE_LOOKUP
 
 /**
  * Verify Client Ciphers obtained using SSL MSG Callback.
 
 /**
  * Verify Client Ciphers obtained using SSL MSG Callback.
@@ -1016,7 +1028,7 @@ TEST(AsyncSSLSocketTest, SSLParseClientHelloSuccess) {
   serverCtx->loadClientCAList(testCA);
 
   clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY);
   serverCtx->loadClientCAList(testCA);
 
   clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY);
-  clientCtx->ciphers("AES256-SHA:RC4-MD5");
+  clientCtx->ciphers("AES256-SHA:AES128-SHA");
   clientCtx->loadPrivateKey(testKey);
   clientCtx->loadCertificate(testCert);
   clientCtx->loadTrustedCertificates(testCA);
   clientCtx->loadPrivateKey(testKey);
   clientCtx->loadCertificate(testCert);
   clientCtx->loadTrustedCertificates(testCA);
@@ -1034,7 +1046,11 @@ TEST(AsyncSSLSocketTest, SSLParseClientHelloSuccess) {
 
   eventBase.loop();
 
 
   eventBase.loop();
 
-  EXPECT_EQ(server.clientCiphers_, "AES256-SHA:RC4-MD5:00ff");
+#if defined(OPENSSL_IS_BORINGSSL)
+  EXPECT_EQ(server.clientCiphers_, "AES256-SHA:AES128-SHA");
+#else
+  EXPECT_EQ(server.clientCiphers_, "AES256-SHA:AES128-SHA:00ff");
+#endif
   EXPECT_EQ(server.chosenCipher_, "AES256-SHA");
   EXPECT_TRUE(client.handshakeVerify_);
   EXPECT_TRUE(client.handshakeSuccess_);
   EXPECT_EQ(server.chosenCipher_, "AES256-SHA");
   EXPECT_TRUE(client.handshakeVerify_);
   EXPECT_TRUE(client.handshakeSuccess_);
@@ -1692,8 +1708,14 @@ TEST(AsyncSSLSocketTest, ConnOpenSSLErrorString) {
   handshakeCallback.waitForHandshake();
   EXPECT_NE(handshakeCallback.errorString_.find("SSL routines"),
             std::string::npos);
   handshakeCallback.waitForHandshake();
   EXPECT_NE(handshakeCallback.errorString_.find("SSL routines"),
             std::string::npos);
+#if defined(OPENSSL_IS_BORINGSSL)
+  EXPECT_NE(
+      handshakeCallback.errorString_.find("ENCRYPTED_LENGTH_TOO_LONG"),
+      std::string::npos);
+#else
   EXPECT_NE(handshakeCallback.errorString_.find("unknown protocol"),
             std::string::npos);
   EXPECT_NE(handshakeCallback.errorString_.find("unknown protocol"),
             std::string::npos);
+#endif
 }
 
 TEST(AsyncSSLSocketTest, TestSSLCipherCodeToNameMap) {
 }
 
 TEST(AsyncSSLSocketTest, TestSSLCipherCodeToNameMap) {
@@ -1868,6 +1890,7 @@ TEST(AsyncSSLSocketTest, ConnectWriteReadCloseTFOFallback) {
   sock.close();
 }
 
   sock.close();
 }
 
+#if !defined(OPENSSL_IS_BORINGSSL)
 TEST(AsyncSSLSocketTest, ConnectTFOTimeout) {
   // Start listening on a local port
   ConnectTimeoutCallback acceptCallback;
 TEST(AsyncSSLSocketTest, ConnectTFOTimeout) {
   // Start listening on a local port
   ConnectTimeoutCallback acceptCallback;
@@ -1883,7 +1906,9 @@ TEST(AsyncSSLSocketTest, ConnectTFOTimeout) {
   EXPECT_THROW(
       socket->open(std::chrono::milliseconds(20)), AsyncSocketException);
 }
   EXPECT_THROW(
       socket->open(std::chrono::milliseconds(20)), AsyncSocketException);
 }
+#endif
 
 
+#if !defined(OPENSSL_IS_BORINGSSL)
 TEST(AsyncSSLSocketTest, ConnectTFOFallbackTimeout) {
   // Start listening on a local port
   ConnectTimeoutCallback acceptCallback;
 TEST(AsyncSSLSocketTest, ConnectTFOFallbackTimeout) {
   // Start listening on a local port
   ConnectTimeoutCallback acceptCallback;
@@ -1899,6 +1924,7 @@ TEST(AsyncSSLSocketTest, ConnectTFOFallbackTimeout) {
   evb.loop();
   EXPECT_EQ(ConnCallback::State::ERROR, ccb.state);
 }
   evb.loop();
   EXPECT_EQ(ConnCallback::State::ERROR, ccb.state);
 }
+#endif
 
 TEST(AsyncSSLSocketTest, HandshakeTFOFallbackTimeout) {
   // Start listening on a local port
 
 TEST(AsyncSSLSocketTest, HandshakeTFOFallbackTimeout) {
   // Start listening on a local port
index ecf3aa514c2de03e54e79cbb46cfe898654507b2..1cf0c910f4282cfda656f91e2e4f7e6835bbc347 100644 (file)
@@ -683,6 +683,7 @@ class TestSSLAsyncCacheServer : public TestSSLServer {
                                          int* copyflag) {
     *copyflag = 0;
     asyncCallbacks_++;
                                          int* copyflag) {
     *copyflag = 0;
     asyncCallbacks_++;
+    (void)ssl;
 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
     if (!SSL_want_sess_cache_lookup(ssl)) {
       // libssl.so mismatch
 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
     if (!SSL_want_sess_cache_lookup(ssl)) {
       // libssl.so mismatch
index 4d766b68dd47968053c09ec00b46cee26a412e7e..8f1f275618144072f055937e4cab006cc17c5ae7 100644 (file)
@@ -197,9 +197,16 @@ int main(int argc, char *argv[]) {
   signal(SIGPIPE, SIG_IGN);
 #endif
   folly::SSLContext::setSSLLockTypes({
   signal(SIGPIPE, SIG_IGN);
 #endif
   folly::SSLContext::setSSLLockTypes({
+#ifdef CRYPTO_LOCK_EVP_PKEY
       {CRYPTO_LOCK_EVP_PKEY, folly::SSLContext::LOCK_NONE},
       {CRYPTO_LOCK_EVP_PKEY, folly::SSLContext::LOCK_NONE},
+#endif
+#ifdef CRYPTO_LOCK_SSL_SESSION
       {CRYPTO_LOCK_SSL_SESSION, folly::SSLContext::LOCK_SPINLOCK},
       {CRYPTO_LOCK_SSL_SESSION, folly::SSLContext::LOCK_SPINLOCK},
-      {CRYPTO_LOCK_SSL_CTX, folly::SSLContext::LOCK_NONE}});
+#endif
+#ifdef CRYPTO_LOCK_SSL_CTX
+      {CRYPTO_LOCK_SSL_CTX, folly::SSLContext::LOCK_NONE}
+#endif
+  });
   testing::InitGoogleTest(&argc, argv);
   gflags::ParseCommandLineFlags(&argc, &argv, true);
   return RUN_ALL_TESTS();
   testing::InitGoogleTest(&argc, argv);
   gflags::ParseCommandLineFlags(&argc, &argv, true);
   return RUN_ALL_TESTS();
diff --git a/folly/portability/OpenSSL.cpp b/folly/portability/OpenSSL.cpp
new file mode 100644 (file)
index 0000000..dacf774
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <folly/portability/OpenSSL.h>
+
+namespace folly {
+namespace ssl {
+
+#ifdef OPENSSL_IS_BORINGSSL
+int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) {
+  return 1; // 0 implies error
+}
+
+int TLS1_get_client_version(SSL* s) {
+  return s->client_version;
+}
+
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) {
+  biom->bread = read;
+  return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) {
+  biom->bwrite = write;
+  return 1;
+}
+
+#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101
+int SSL_CTX_up_ref(SSL_CTX* ctx) {
+  return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION* session) {
+  return CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+}
+
+int X509_up_ref(X509* x) {
+  return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+}
+
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) {
+  biom->bread = read;
+  return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) {
+  biom->bwrite = write;
+  return 1;
+}
+
+#elif FOLLY_OPENSSL_IS_110
+
+#endif
+}
+}
diff --git a/folly/portability/OpenSSL.h b/folly/portability/OpenSSL.h
new file mode 100644 (file)
index 0000000..97ed213
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+namespace folly {
+namespace ssl {
+
+// BoringSSL doesn't have notion of versioning although it defines
+// OPENSSL_VERSION_NUMBER to maintain compatibility. The following variables are
+// intended to be specific to OpenSSL.
+#if !defined(OPENSSL_IS_BORINGSSL)
+#define FOLLY_OPENSSL_IS_101                \
+  (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
+   OPENSSL_VERSION_NUMBER < 0x1000200fL)
+#define FOLLY_OPENSSL_IS_102                \
+  (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
+   OPENSSL_VERSION_NUMBER < 0x10100000L)
+#define FOLLY_OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#endif // !defined(OPENSSL_IS_BORINGSSL)
+
+// 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
+// SSL_CTX_set1_sigalgs_list and so on which exist in 1.0.2 but were removed
+// in BoringSSL
+
+#ifdef OPENSSL_IS_BORINGSSL
+
+int SSL_CTX_set1_sigalgs_list(SSL_CTX* ctx, const char* sigalgs_list);
+int TLS1_get_client_version(SSL* s);
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int));
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int));
+
+#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101
+
+int SSL_CTX_up_ref(SSL_CTX* session);
+int SSL_SESSION_up_ref(SSL_SESSION* session);
+int X509_up_ref(X509* x);
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int));
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int));
+
+#elif FOLLY_OPENSSL_IS_110
+
+#else
+#warning Compiling with unsupported OpenSSL version
+#endif
+
+} // ssl
+} // folly
diff --git a/folly/ssl/OpenSSLVersionFinder.h b/folly/ssl/OpenSSLVersionFinder.h
new file mode 100644 (file)
index 0000000..9511396
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <folly/Conv.h>
+#include <folly/portability/OpenSSL.h>
+
+#include <openssl/crypto.h>
+#include <openssl/opensslv.h>
+
+// This is used to find the OpenSSL version at runtime. Just returning
+// OPENSSL_VERSION_NUMBER is insufficient as runtime version may be different
+// from the compile-time version
+struct OpenSSLVersionFinder {
+  static std::string getOpenSSLLongVersion(void) {
+#ifdef OPENSSL_VERSION_TEXT
+    return SSLeay_version(SSLEAY_VERSION);
+#elif defined(OPENSSL_VERSION_NUMBER)
+    return folly::format("0x{:x}", OPENSSL_VERSION_NUMBER).str();
+#else
+    return "";
+#endif
+  }
+
+  uint64_t getOpenSSLNumericVersion(void) {
+#ifdef OPENSSL_VERSION_NUMBER
+    return SSLeay();
+#else
+    return 0;
+#endif
+  }
+};
index e7424abb030129eec3d48a5a0ad84672b49c2b15..071c7fc30d8063306b3ab71ac840039946fcccfd 100644 (file)
@@ -17,7 +17,7 @@
 #pragma once
 
 #include <folly/Memory.h>
 #pragma once
 
 #include <folly/Memory.h>
-#include <folly/ssl/detail/OpenSSLVersionFinder.h>
+#include <folly/portability/OpenSSL.h>
 #include <folly/ssl/detail/SSLSessionImpl.h>
 
 namespace folly {
 #include <folly/ssl/detail/SSLSessionImpl.h>
 
 namespace folly {
diff --git a/folly/ssl/detail/OpenSSLVersionFinder.h b/folly/ssl/detail/OpenSSLVersionFinder.h
deleted file mode 100644 (file)
index 5360ff6..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <folly/Conv.h>
-
-#include <openssl/crypto.h>
-#include <openssl/opensslv.h>
-
-// BoringSSL doesn't have notion of versioning although it defines
-// OPENSSL_VERSION_NUMBER to maintain compatibility. The following variables are
-// intended to be specific to OpenSSL.
-#if !defined(OPENSSL_IS_BORINGSSL)
-# define OPENSSL_IS_101                       \
-    (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
-     OPENSSL_VERSION_NUMBER < 0x1000200fL)
-# define OPENSSL_IS_102                       \
-    (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
-     OPENSSL_VERSION_NUMBER < 0x10100000L)
-# define OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-#endif  // !defined(OPENSSL_IS_BORINGSSL)
-
-// This is used to find the OpenSSL version at runtime. Just returning
-// OPENSSL_VERSION_NUMBER is insufficient as runtime version may be different
-// from the compile-time version
-struct OpenSSLVersionFinder {
-  static std::string getOpenSSLLongVersion(void) {
-#ifdef OPENSSL_VERSION_TEXT
-    return SSLeay_version(SSLEAY_VERSION);
-#elif defined(OPENSSL_VERSION_NUMBER)
-    return folly::format("0x{:x}", OPENSSL_VERSION_NUMBER).str();
-#else
-    return "";
-#endif
-  }
-
-  uint64_t getOpenSSLNumericVersion(void) {
-#ifdef OPENSSL_VERSION_NUMBER
-    return SSLeay();
-#else
-    return 0;
-#endif
-  }
-};
index 4154c3b10f6217759008f8962377706a7943791d..47b3c3431240ee52bfc261de4989f4c34cb51965 100644 (file)
@@ -15,7 +15,8 @@
  */
 
 #include <folly/ssl/detail/SSLSessionImpl.h>
  */
 
 #include <folly/ssl/detail/SSLSessionImpl.h>
-#include <folly/ssl/detail/OpenSSLVersionFinder.h>
+#include <folly/portability/OpenSSL.h>
+#include <folly/ssl/OpenSSLVersionFinder.h>
 
 namespace folly {
 namespace ssl {
 
 namespace folly {
 namespace ssl {
@@ -74,12 +75,7 @@ std::string SSLSessionImpl::getSessionID() const {
   if (session_) {
     const unsigned char* ptr = nullptr;
     unsigned int len = 0;
   if (session_) {
     const unsigned char* ptr = nullptr;
     unsigned int len = 0;
-#if defined(OPENSSL_IS_102) || defined(OPENSSL_IS_101)
-    len = session_->session_id_length;
-    ptr = session_->session_id;
-#elif defined(OPENSSL_IS_110) || defined(OPENSSL_IS_BORINGSSL)
     ptr = SSL_SESSION_get_id(session_, &len);
     ptr = SSL_SESSION_get_id(session_, &len);
-#endif
     ret.assign(ptr, ptr + len);
   }
   return ret;
     ret.assign(ptr, ptr + len);
   }
   return ret;
@@ -96,11 +92,7 @@ SSL_SESSION* SSLSessionImpl::getRawSSLSessionDangerous() {
 
 void SSLSessionImpl::upRef() {
   if (session_) {
 
 void SSLSessionImpl::upRef() {
   if (session_) {
-#if defined(OPENSSL_IS_102) || defined(OPENSSL_IS_101)
-    CRYPTO_add(&session_->references, 1, CRYPTO_LOCK_SSL_SESSION);
-#elif defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_110)
     SSL_SESSION_up_ref(session_);
     SSL_SESSION_up_ref(session_);
-#endif
   }
 }
 
   }
 }