rcpp_framework/libs/brynet/net/SSLHelper.hpp

176 lines
4.0 KiB
C++
Raw Normal View History

2020-11-24 15:41:18 +01:00
#pragma once
2021-04-30 16:10:14 +02:00
#include <brynet/base/Noexcept.hpp>
#include <brynet/base/NonCopyable.hpp>
#include <brynet/base/Platform.hpp>
2020-11-24 15:41:18 +01:00
#include <memory>
#include <mutex>
2021-04-30 16:10:14 +02:00
#include <string>
2020-11-24 15:41:18 +01:00
#include <thread>
2021-04-30 16:10:14 +02:00
#include <unordered_map>
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_USE_OPENSSL
2021-04-30 16:10:14 +02:00
#ifdef __cplusplus
2020-11-24 15:41:18 +01:00
extern "C" {
#endif
#include <openssl/err.h>
2021-04-30 16:10:14 +02:00
#include <openssl/ssl.h>
#ifdef __cplusplus
2020-11-24 15:41:18 +01:00
}
#endif
#endif
namespace brynet { namespace net {
#ifdef BRYNET_USE_OPENSSL
#ifndef CRYPTO_THREADID_set_callback
2021-04-30 16:10:14 +02:00
static void cryptoSetThreadIDCallback(CRYPTO_THREADID* id)
{
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_PLATFORM_WINDOWS
2021-04-30 16:10:14 +02:00
CRYPTO_THREADID_set_numeric(id,
static_cast<unsigned long>(GetCurrentThreadId()));
2020-11-24 15:41:18 +01:00
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
2021-04-30 16:10:14 +02:00
CRYPTO_THREADID_set_numeric(id,
static_cast<unsigned long>(pthread_self()));
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
}
2020-11-24 15:41:18 +01:00
#endif
#ifndef CRYPTO_set_locking_callback
2021-04-30 16:10:14 +02:00
static std::unordered_map<int, std::shared_ptr<std::mutex>> cryptoLocks;
static void cryptoLockingCallback(int mode,
int type,
const char* file, int line)
{
(void) file;
(void) line;
if (mode & CRYPTO_LOCK)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
cryptoLocks[type]->lock();
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
else if (mode & CRYPTO_UNLOCK)
{
cryptoLocks[type]->unlock();
}
}
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
static std::once_flag initCryptoThreadSafeSupportOnceFlag;
static void InitCryptoThreadSafeSupport()
{
2020-11-24 15:41:18 +01:00
#ifndef CRYPTO_THREADID_set_callback
2021-04-30 16:10:14 +02:00
CRYPTO_THREADID_set_callback(cryptoSetThreadIDCallback);
2020-11-24 15:41:18 +01:00
#endif
#ifndef CRYPTO_set_locking_callback
2021-04-30 16:10:14 +02:00
for (int i = 0; i < CRYPTO_num_locks(); i++)
{
cryptoLocks[i] = std::make_shared<std::mutex>();
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
CRYPTO_set_locking_callback(cryptoLockingCallback);
#endif
}
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
class SSLHelper : public brynet::base::NonCopyable,
public std::enable_shared_from_this<SSLHelper>
{
public:
using Ptr = std::shared_ptr<SSLHelper>;
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_USE_OPENSSL
2021-04-30 16:10:14 +02:00
bool initSSL(const std::string& certificate,
const std::string& privatekey)
{
std::call_once(initCryptoThreadSafeSupportOnceFlag,
InitCryptoThreadSafeSupport);
if (mOpenSSLCTX != nullptr)
{
return false;
}
if (certificate.empty() || privatekey.empty())
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return false;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
mOpenSSLCTX = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_client_CA_list(mOpenSSLCTX,
SSL_load_client_CA_file(certificate.c_str()));
SSL_CTX_set_verify_depth(mOpenSSLCTX, 10);
if (SSL_CTX_use_certificate_chain_file(mOpenSSLCTX,
certificate.c_str()) <= 0)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
SSL_CTX_free(mOpenSSLCTX);
mOpenSSLCTX = nullptr;
return false;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
if (SSL_CTX_use_PrivateKey_file(mOpenSSLCTX,
privatekey.c_str(),
SSL_FILETYPE_PEM) <= 0)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
SSL_CTX_free(mOpenSSLCTX);
mOpenSSLCTX = nullptr;
return false;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
if (!SSL_CTX_check_private_key(mOpenSSLCTX))
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
SSL_CTX_free(mOpenSSLCTX);
mOpenSSLCTX = nullptr;
return false;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
return true;
}
void destroySSL()
{
if (mOpenSSLCTX != nullptr)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
SSL_CTX_free(mOpenSSLCTX);
2020-11-24 15:41:18 +01:00
mOpenSSLCTX = nullptr;
}
2021-04-30 16:10:14 +02:00
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
SSL_CTX* getOpenSSLCTX()
{
return mOpenSSLCTX;
}
#endif
static Ptr Create()
{
class make_shared_enabler : public SSLHelper
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
};
return std::make_shared<make_shared_enabler>();
}
protected:
SSLHelper() BRYNET_NOEXCEPT
{
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_USE_OPENSSL
2021-04-30 16:10:14 +02:00
mOpenSSLCTX = nullptr;
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
}
virtual ~SSLHelper() BRYNET_NOEXCEPT
{
#ifdef BRYNET_USE_OPENSSL
destroySSL();
#endif
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_USE_OPENSSL
2021-04-30 16:10:14 +02:00
SSL_CTX* mOpenSSLCTX;
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
}}// namespace brynet::net