diff --git a/folly/io/async/test/SSLContextInitializationTest.cpp b/folly/io/async/test/SSLContextInitializationTest.cpp deleted file mode 100644 index e4fcfd87863..00000000000 --- a/folly/io/async/test/SSLContextInitializationTest.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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 - -#include -#include -#include -#include -#include - -namespace folly { - -void setupSSLLocks() { - folly::ssl::setLockTypes({ -#ifdef CRYPTO_LOCK_EVP_PKEY - {CRYPTO_LOCK_EVP_PKEY, folly::ssl::LockType::NONE}, -#endif -#ifdef CRYPTO_LOCK_SSL_SESSION - {CRYPTO_LOCK_SSL_SESSION, folly::ssl::LockType::SPINLOCK}, -#endif -#ifdef CRYPTO_LOCK_SSL_CTX - {CRYPTO_LOCK_SSL_CTX, folly::ssl::LockType::NONE} -#endif - }); -} - -TEST(SSLContextInitializationTest, SSLContextInitializeThenSetLocksAndInit) { - EXPECT_DEATH( - { - folly::ssl::init(); - folly::ssl::setLockTypesAndInit({}); - }, - "OpenSSL is already initialized"); -} - -TEST(SSLContextInitializationTest, SSLContextSetLocksAndInitialize) { - EXPECT_DEATH( - { - folly::ssl::setLockTypesAndInit({}); - folly::ssl::setLockTypesAndInit({}); - }, - "OpenSSL is already initialized"); -} - -TEST(SSLContextInitializationTest, SSLContextLocks) { - EXPECT_EXIT( - { - setupSSLLocks(); - folly::ssl::init(); -#ifdef CRYPTO_LOCK_EVP_PKEY - EXPECT_TRUE(folly::ssl::isLockDisabled(CRYPTO_LOCK_EVP_PKEY)); -#endif -#ifdef CRYPTO_LOCK_SSL_SESSION - EXPECT_FALSE(folly::ssl::isLockDisabled(CRYPTO_LOCK_SSL_SESSION)); -#endif -#ifdef CRYPTO_LOCK_ERR - EXPECT_FALSE(folly::ssl::isLockDisabled(CRYPTO_LOCK_ERR)); -#endif - if (::testing::Test::HasFailure()) { - exit(1); - } - LOG(INFO) << "SSLContextLocks passed"; - exit(0); - }, - ::testing::ExitedWithCode(0), - "SSLContextLocks passed"); -} - -TEST(SSLContextInitializationTest, SSLContextLocksSetAfterInitIgnored) { - EXPECT_EXIT( - { - setupSSLLocks(); - folly::ssl::init(); - folly::ssl::setLockTypes({}); -#ifdef CRYPTO_LOCK_EVP_PKEY - EXPECT_TRUE(folly::ssl::isLockDisabled(CRYPTO_LOCK_EVP_PKEY)); -#endif - if (::testing::Test::HasFailure()) { - exit(1); - } - LOG(INFO) << "SSLContextLocksSetAfterInitIgnored passed"; - exit(0); - }, - ::testing::ExitedWithCode(0), - "SSLContextLocksSetAfterInitIgnored passed"); -} - -TEST(SSLContextInitializationTest, SSLContextSslCtxConstructor) { - folly::ssl::init(); - - // Used to determine when SSL_CTX is freed. - auto onFree = [](void*, void* arg, CRYPTO_EX_DATA*, int, long, void*) { - bool* freed = static_cast(arg); - *freed = true; - }; - static int idx = SSL_CTX_get_ex_new_index( - 0 /*argl */, - nullptr /*argp*/, - nullptr /*new_func*/, - nullptr /*dup_func*/, - onFree /*free_func*/); - - bool freed = false; - SSL_CTX* ctx = SSL_CTX_new(TLS_method()); - EXPECT_NE(ctx, nullptr) << "SSL_CTX* creation for test failed"; - - (void)SSL_CTX_set_ex_data(ctx, idx, &freed); - - { - // SSLContext takes "ownership" (read: increments the ref count), and will - // free ctx on destruction. - folly::SSLContext sslContext(ctx); - } - // Shouldn't be fully freed because SSLContext should've added to the - // refcount. up_ref should succed - EXPECT_EQ(freed, false); - - // Last reference, ctx should no longer be valid. Should trigger the ex_data - // free func. - SSL_CTX_free(ctx); - EXPECT_EQ(freed, true); -} - -} // namespace folly - -int main(int argc, char* argv[]) { -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN); -#endif - testing::InitGoogleTest(&argc, argv); - folly::Init init(&argc, &argv); - - return RUN_ALL_TESTS(); -} diff --git a/folly/ssl/Init.cpp b/folly/ssl/Init.cpp index dd4c841c320..1acc2ac23e4 100644 --- a/folly/ssl/Init.cpp +++ b/folly/ssl/Init.cpp @@ -16,88 +16,21 @@ #include -#include - -#include -#include -#include - -#include - namespace folly { namespace ssl { -namespace { -bool initialized_ = false; +void init() {} -std::mutex& initMutex() { - static folly::Indestructible m; - return *m; -} +void cleanup() {} -void initializeOpenSSLLocked() { - if (initialized_) { - return; - } - if (OPENSSL_init_ssl(0, nullptr) != 1) { - // Fail early if we fail to initialize OpenSSL. Ignoring this means that - // future OpenSSL methods may segfault, since there is an implicit - // precondition that initialization properly initializes internal OpenSSL - // pointers to global resources. - throw std::runtime_error("Failed to initialize OpenSSL."); - } +void markInitialized() {} - // Non-fatal errors may be set during initialization, if OPENSSL_init_ssl - // successfully returned we can safely clear them - ERR_clear_error(); - initialized_ = true; -} +void setLockTypesAndInit(LockTypeMapping) {} -void cleanupOpenSSLLocked() { - if (!initialized_) { - return; - } - - OPENSSL_cleanup(); - initialized_ = false; -} -} // namespace - -void init() { - std::lock_guard g(initMutex()); - initializeOpenSSLLocked(); -} - -void cleanup() { - std::lock_guard g(initMutex()); - cleanupOpenSSLLocked(); -} - -void markInitialized() { - std::lock_guard g(initMutex()); - initialized_ = true; -} - -void setLockTypesAndInit(LockTypeMapping inLockTypes) { - std::lock_guard g(initMutex()); - CHECK(!initialized_) << "OpenSSL is already initialized"; - detail::setLockTypes(std::move(inLockTypes)); - initializeOpenSSLLocked(); -} - -void setLockTypes(LockTypeMapping inLockTypes) { - std::lock_guard g(initMutex()); - if (initialized_) { - // We set the locks on initialization, so if we are already initialized - // this would have no affect. - LOG(INFO) << "Ignoring setSSLLockTypes after initialization"; - return; - } - detail::setLockTypes(std::move(inLockTypes)); -} +void setLockTypes(LockTypeMapping) {} -bool isLockDisabled(int lockId) { - return detail::isSSLLockDisabled(lockId); +bool isLockDisabled(int) { + return false; } } // namespace ssl diff --git a/folly/ssl/detail/OpenSSLThreading.cpp b/folly/ssl/detail/OpenSSLThreading.cpp deleted file mode 100644 index c7cb47a0b91..00000000000 --- a/folly/ssl/detail/OpenSSLThreading.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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 - -#include -#include - -#include - -#include -#include - -// We cannot directly use portability/openssl because it also depends on us. -// Therefore we directly use openssl includes. Order of includes is important -// here. See portability/openssl.h. -// clang-format off -#include -// @lint-ignore CLANGTIDY -#include -// clang-format on - -#if !defined(OPENSSL_IS_BORINGSSL) -#define FOLLY_SSL_DETAIL_OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L) -#else -#define FOLLY_SSL_DETAIL_OPENSSL_IS_110 (false) -#endif - -// OpenSSL requires us to provide the implementation of CRYPTO_dynlock_value -// so it must be done in the global namespace. -// @lint-ignore CLANGTIDY -struct CRYPTO_dynlock_value { - std::mutex mutex; -}; - -namespace folly { -namespace ssl { -namespace detail { - -static std::map& lockTypes() { - static auto lockTypesInst = new std::map(); - return *lockTypesInst; -} - -void setLockTypes(std::map inLockTypes) { -#if FOLLY_SSL_DETAIL_OPENSSL_IS_110 - VLOG(3) << "setLockTypes() is unsupported on OpenSSL >= 1.1.0. " - << "OpenSSL now uses platform native mutexes"; -#endif - - lockTypes() = inLockTypes; -} - -bool isSSLLockDisabled(int lockId) { - const auto& sslLocks = lockTypes(); - const auto it = sslLocks.find(lockId); - return it != sslLocks.end() && it->second == LockType::NONE; -} - -namespace { -struct SSLLock { - [[maybe_unused]] explicit SSLLock(LockType inLockType = LockType::MUTEX) - : lockType(inLockType) {} - - [[maybe_unused]] void lock(bool /* read */) { - if (lockType == LockType::MUTEX) { - mutex.lock(); - } else if (lockType == LockType::SPINLOCK) { - spinLock.lock(); - } - // lockType == LOCK_NONE, no-op - } - - [[maybe_unused]] void unlock(bool /* read */) { - if (lockType == LockType::MUTEX) { - mutex.unlock(); - } else if (lockType == LockType::SPINLOCK) { - spinLock.unlock(); - } - // lockType == LOCK_NONE, no-op - } - - LockType lockType; - folly::SpinLock spinLock{}; - std::mutex mutex; -}; -} // namespace - -// Statics are unsafe in environments that call exit(). -// If one thread calls exit() while another thread is -// references a member of SSLContext, bad things can happen. -// SSLContext runs in such environments. -// Instead of declaring a static member we "new" the static -// member so that it won't be destructed on exit(). -#if !FOLLY_SSL_DETAIL_OPENSSL_IS_110 -static std::unique_ptr& locks() { - static auto locksInst = new std::unique_ptr(); - return *locksInst; -} - -static void callbackLocking(int mode, int n, const char*, int) { - if (mode & CRYPTO_LOCK) { - locks()[size_t(n)].lock(mode & CRYPTO_READ); - } else { - locks()[size_t(n)].unlock(mode & CRYPTO_READ); - } -} - -static void callbackThreadID(CRYPTO_THREADID* id) { - return CRYPTO_THREADID_set_numeric(id, folly::getCurrentThreadID()); -} - -static CRYPTO_dynlock_value* dyn_create(const char*, int) { - return new CRYPTO_dynlock_value; -} - -static void dyn_lock( - int mode, struct CRYPTO_dynlock_value* lock, const char*, int) { - if (lock != nullptr) { - if (mode & CRYPTO_LOCK) { - lock->mutex.lock(); - } else { - lock->mutex.unlock(); - } - } -} - -static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) { - delete lock; -} -#endif - -void installThreadingLocks() { -#if !FOLLY_SSL_DETAIL_OPENSSL_IS_110 - // static locking - locks() = std::make_unique(size_t(CRYPTO_num_locks())); - for (auto it : lockTypes()) { - locks()[size_t(it.first)].lockType = it.second; - } - CRYPTO_THREADID_set_callback(callbackThreadID); - CRYPTO_set_locking_callback(callbackLocking); - // dynamic locking - CRYPTO_set_dynlock_create_callback(dyn_create); - CRYPTO_set_dynlock_lock_callback(dyn_lock); - CRYPTO_set_dynlock_destroy_callback(dyn_destroy); -#endif -} - -void cleanupThreadingLocks() { -#if !FOLLY_SSL_DETAIL_OPENSSL_IS_110 - CRYPTO_THREADID_set_callback(nullptr); - CRYPTO_set_locking_callback(nullptr); - CRYPTO_set_dynlock_create_callback(nullptr); - CRYPTO_set_dynlock_lock_callback(nullptr); - CRYPTO_set_dynlock_destroy_callback(nullptr); - locks().reset(); -#endif -} - -} // namespace detail -} // namespace ssl -} // namespace folly diff --git a/folly/ssl/detail/OpenSSLThreading.h b/folly/ssl/detail/OpenSSLThreading.h deleted file mode 100644 index 4284003e3a6..00000000000 --- a/folly/ssl/detail/OpenSSLThreading.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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 - -#include - -namespace folly { -namespace ssl { -namespace detail { -bool isSSLLockDisabled(int lockId); -void setLockTypes(std::map inLockTypes); -void installThreadingLocks(); -void cleanupThreadingLocks(); -} // namespace detail -} // namespace ssl -} // namespace folly