109 lines
2.9 KiB
C++
109 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its 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 <folly/ssl/Init.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include <folly/portability/OpenSSL.h>
|
|
#include <folly/ssl/detail/OpenSSLThreading.h>
|
|
#include <glog/logging.h>
|
|
|
|
namespace folly {
|
|
namespace ssl {
|
|
|
|
namespace {
|
|
bool initialized_ = false;
|
|
|
|
std::mutex& initMutex() {
|
|
static std::mutex m;
|
|
return m;
|
|
}
|
|
|
|
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.");
|
|
}
|
|
|
|
// OpenSSL implicitly seeds its RNG since 1.1.0, so this call is unnecessary
|
|
// and is only here for compatibility with older versions of OpenSSL.
|
|
#if !(FOLLY_OPENSSL_IS_110)
|
|
if (RAND_poll() != 1) {
|
|
// Similarly, if we fail to seed the RNG, future crypto operations
|
|
// may no longer be safe to use; fail fast and hard here.
|
|
throw std::runtime_error("Failed to initialize OpenSSL RNG.");
|
|
}
|
|
#endif
|
|
initialized_ = true;
|
|
}
|
|
|
|
void cleanupOpenSSLLocked() {
|
|
if (!initialized_) {
|
|
return;
|
|
}
|
|
|
|
OPENSSL_cleanup();
|
|
initialized_ = false;
|
|
}
|
|
} // namespace
|
|
|
|
void init() {
|
|
std::lock_guard<std::mutex> g(initMutex());
|
|
initializeOpenSSLLocked();
|
|
}
|
|
|
|
void cleanup() {
|
|
std::lock_guard<std::mutex> g(initMutex());
|
|
cleanupOpenSSLLocked();
|
|
}
|
|
|
|
void markInitialized() {
|
|
std::lock_guard<std::mutex> g(initMutex());
|
|
initialized_ = true;
|
|
}
|
|
|
|
void setLockTypesAndInit(LockTypeMapping inLockTypes) {
|
|
std::lock_guard<std::mutex> g(initMutex());
|
|
CHECK(!initialized_) << "OpenSSL is already initialized";
|
|
detail::setLockTypes(std::move(inLockTypes));
|
|
initializeOpenSSLLocked();
|
|
}
|
|
|
|
void setLockTypes(LockTypeMapping inLockTypes) {
|
|
std::lock_guard<std::mutex> 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));
|
|
}
|
|
|
|
bool isLockDisabled(int lockId) {
|
|
return detail::isSSLLockDisabled(lockId);
|
|
}
|
|
|
|
} // namespace ssl
|
|
} // namespace folly
|