blob: 6116a767a7e6978462b18f42a221f364d30280ce [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 <sstream>
#include "ignite/common/utils.h"
#include "ignite/odbc/ssl/ssl_gateway.h"
#include "ignite/odbc/log.h"
#ifndef ADDITIONAL_OPENSSL_HOME_ENV
# define ADDITIONAL_OPENSSL_HOME_ENV "OPEN_SSL_HOME"
#endif // ADDITIONAL_OPENSSL_HOME_ENV
#ifndef SSL_CTRL_OPTIONS
# define SSL_CTRL_OPTIONS 32
#endif // SSL_CTRL_OPTIONS
#ifndef OPENSSL_INIT_LOAD_SSL_STRINGS
# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
#endif // OPENSSL_INIT_LOAD_SSL_STRINGS
#ifndef OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
#endif // OPENSSL_INIT_LOAD_CRYPTO_STRINGS
namespace ignite
{
namespace odbc
{
namespace ssl
{
SslGateway::SslGateway() :
inited(false),
functions()
{
memset(&functions, 0, sizeof(functions));
}
SslGateway::~SslGateway()
{
// No-op.
}
void SslGateway::UnloadAll()
{
libeay32.Unload();
ssleay32.Unload();
libssl.Unload();
libcrypto.Unload();
memset(&functions, 0, sizeof(functions));
}
common::dynamic::Module SslGateway::LoadSslLibrary(const char* name)
{
using namespace common;
using namespace dynamic;
std::string home = GetEnv(ADDITIONAL_OPENSSL_HOME_ENV);
if (home.empty())
home = GetEnv("OPENSSL_HOME");
std::string fullName = GetDynamicLibraryName(name);
if (!home.empty())
{
std::stringstream constructor;
constructor << home << Fs << "bin" << Fs << fullName;
std::string fullPath = constructor.str();
Module mod = LoadModule(fullPath);
if (mod.IsLoaded())
return mod;
}
return LoadModule(fullName);
}
bool SslGateway::LoadSslLibraries()
{
libssl = LoadSslLibrary("libssl");
if (!libssl.IsLoaded())
{
libcrypto = LoadSslLibrary("libcrypto-1_1-x64");
libssl = LoadSslLibrary("libssl-1_1-x64");
}
if (!libssl.IsLoaded())
{
libeay32 = LoadSslLibrary("libeay32");
ssleay32 = LoadSslLibrary("ssleay32");
}
if (!libssl.IsLoaded() && (!libeay32.IsLoaded() || !ssleay32.IsLoaded()))
{
if (!libeay32.IsLoaded())
LOG_MSG("Can not load libeay32.");
if (!ssleay32.IsLoaded())
LOG_MSG("Can not load ssleay32.");
if (!libssl.IsLoaded())
LOG_MSG("Can not load libssl.");
return false;
}
return true;
}
void SslGateway::LoadMandatoryMethods()
{
functions.fpSSLeay_version = TryLoadSslMethod("SSLeay_version");
if (!functions.fpSSLeay_version)
functions.fpOpenSSL_version = LoadSslMethod("OpenSSL_version");
functions.fpSSL_library_init = TryLoadSslMethod("SSL_library_init");
functions.fpSSL_load_error_strings = TryLoadSslMethod("SSL_load_error_strings");
if (!functions.fpSSL_library_init || !functions.fpSSL_load_error_strings)
functions.fpOPENSSL_init_ssl = LoadSslMethod("OPENSSL_init_ssl");
functions.fpSSLv23_client_method = TryLoadSslMethod("SSLv23_client_method");
if (!functions.fpSSLv23_client_method)
functions.fpTLS_client_method = LoadSslMethod("TLS_client_method");
functions.fpSSL_CTX_new = LoadSslMethod("SSL_CTX_new");
functions.fpSSL_CTX_free = LoadSslMethod("SSL_CTX_free");
functions.fpSSL_CTX_set_verify = LoadSslMethod("SSL_CTX_set_verify");
functions.fpSSL_CTX_set_verify_depth = LoadSslMethod("SSL_CTX_set_verify_depth");
functions.fpSSL_CTX_load_verify_locations = LoadSslMethod("SSL_CTX_load_verify_locations");
functions.fpSSL_CTX_use_certificate_chain_file = LoadSslMethod("SSL_CTX_use_certificate_chain_file");
functions.fpSSL_CTX_use_RSAPrivateKey_file = LoadSslMethod("SSL_CTX_use_RSAPrivateKey_file");
functions.fpSSL_CTX_set_cipher_list = LoadSslMethod("SSL_CTX_set_cipher_list");
functions.fpSSL_get_verify_result = LoadSslMethod("SSL_get_verify_result");
functions.fpSSL_get_peer_certificate = LoadSslMethod("SSL_get_peer_certificate");
functions.fpSSL_ctrl = LoadSslMethod("SSL_ctrl");
functions.fpSSL_CTX_ctrl = LoadSslMethod("SSL_CTX_ctrl");
functions.fpSSL_set_connect_state = LoadSslMethod("SSL_set_connect_state");
functions.fpSSL_connect = LoadSslMethod("SSL_connect");
functions.fpSSL_get_error = LoadSslMethod("SSL_get_error");
functions.fpSSL_want = LoadSslMethod("SSL_want");
functions.fpSSL_write = LoadSslMethod("SSL_write");
functions.fpSSL_read = LoadSslMethod("SSL_read");
functions.fpSSL_pending = LoadSslMethod("SSL_pending");
functions.fpSSL_get_fd = LoadSslMethod("SSL_get_fd");
functions.fpSSL_free = LoadSslMethod("SSL_free");
functions.fpBIO_new_ssl_connect = LoadSslMethod("BIO_new_ssl_connect");
functions.fpOPENSSL_config = LoadSslMethod("OPENSSL_config");
functions.fpX509_free = LoadSslMethod("X509_free");
functions.fpBIO_free_all = LoadSslMethod("BIO_free_all");
functions.fpBIO_ctrl = LoadSslMethod("BIO_ctrl");
functions.fpERR_get_error = LoadSslMethod("ERR_get_error");
functions.fpERR_error_string_n = LoadSslMethod("ERR_error_string_n");
}
SslGateway& SslGateway::GetInstance()
{
static SslGateway self;
return self;
}
bool SslGateway::LoadAll()
{
using namespace common::dynamic;
if (inited)
return true;
common::concurrent::CsLockGuard lock(initCs);
if (inited)
return true;
common::MethodGuard<SslGateway> guard(this, &SslGateway::UnloadAll);
if (!LoadSslLibraries())
{
LOG_MSG("Can not load neccessary OpenSSL libraries.");
return false;
}
LoadMandatoryMethods();
functions.fpSSL_CTX_set_options = TryLoadSslMethod("SSL_CTX_set_options");
functions.fpERR_print_errors_fp = TryLoadSslMethod("ERR_print_errors_fp");
(void)SSL_library_init_();
SSL_load_error_strings_();
OPENSSL_config_(0);
guard.Release();
inited = true;
return true;
}
void* SslGateway::TryLoadSslMethod(const char* name)
{
void* fp = libeay32.FindSymbol(name);
if (!fp)
fp = ssleay32.FindSymbol(name);
if (!fp)
fp = libcrypto.FindSymbol(name);
if (!fp)
fp = libssl.FindSymbol(name);
return fp;
}
void* SslGateway::LoadSslMethod(const char* name)
{
void* fp = TryLoadSslMethod(name);
if (!fp)
LOG_MSG("Can not load function " << name);
return fp;
}
char* SslGateway::SSLeay_version_(int type)
{
typedef char* (FuncType)(int);
FuncType* fp = 0;
if (functions.fpSSLeay_version)
fp = reinterpret_cast<FuncType*>(functions.fpSSLeay_version);
else
fp = reinterpret_cast<FuncType*>(functions.fpOpenSSL_version);
assert(fp != 0);
return fp(type);
}
int SslGateway::OPENSSL_init_ssl_(uint64_t opts, const void* settings)
{
assert(functions.fpOPENSSL_init_ssl != 0);
typedef int (FuncType)(uint64_t, const void*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpOPENSSL_init_ssl);
return fp(opts, settings);
}
long SslGateway::SSL_CTX_set_options_(SSL_CTX* ctx, long options)
{
if (functions.fpSSL_CTX_set_options)
{
typedef long (FuncType)(SSL_CTX*, long);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_set_options);
return fp(ctx, options);
}
return SSL_CTX_ctrl_(ctx, SSL_CTRL_OPTIONS, options, NULL);
}
long SslGateway::SSL_CTX_ctrl_(SSL_CTX* ctx, int cmd, long larg, void* parg)
{
assert(functions.fpSSL_CTX_ctrl != 0);
typedef long (FuncType)(SSL_CTX*, int, long, void*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_ctrl);
return fp(ctx, cmd, larg, parg);
}
SSL_CTX* SslGateway::SSL_CTX_new_(const SSL_METHOD* meth)
{
assert(functions.fpSSL_CTX_new != 0);
typedef SSL_CTX*(FuncType)(const SSL_METHOD*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_new);
return fp(meth);
}
void SslGateway::SSL_CTX_free_(SSL_CTX* ctx)
{
assert(functions.fpSSL_CTX_free != 0);
typedef void (FuncType)(SSL_CTX*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_free);
fp(ctx);
}
void SslGateway::SSL_CTX_set_verify_(SSL_CTX* ctx, int mode, int (* callback)(int, X509_STORE_CTX*))
{
assert(functions.fpSSL_CTX_set_verify != 0);
typedef void (FuncType)(SSL_CTX*, int, int (*)(int, X509_STORE_CTX*));
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_set_verify);
fp(ctx, mode, callback);
}
void SslGateway::SSL_CTX_set_verify_depth_(SSL_CTX* ctx, int depth)
{
assert(functions.fpSSL_CTX_set_verify_depth != 0);
typedef void (FuncType)(SSL_CTX*, int);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_set_verify_depth);
fp(ctx, depth);
}
int SslGateway::SSL_CTX_load_verify_locations_(SSL_CTX* ctx, const char* cAfile, const char* cApath)
{
assert(functions.fpSSL_CTX_load_verify_locations != 0);
typedef int (FuncType)(SSL_CTX*, const char*, const char*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_load_verify_locations);
return fp(ctx, cAfile, cApath);
}
int SslGateway::SSL_CTX_use_certificate_chain_file_(SSL_CTX* ctx, const char* file)
{
assert(functions.fpSSL_CTX_use_certificate_chain_file != 0);
typedef int (FuncType)(SSL_CTX*, const char*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_use_certificate_chain_file);
return fp(ctx, file);
}
int SslGateway::SSL_CTX_use_RSAPrivateKey_file_(SSL_CTX* ctx, const char* file, int type)
{
assert(functions.fpSSL_CTX_use_RSAPrivateKey_file != 0);
typedef int (FuncType)(SSL_CTX*, const char*, int);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_use_RSAPrivateKey_file);
return fp(ctx, file, type);
}
int SslGateway::SSL_CTX_set_cipher_list_(SSL_CTX* ctx, const char* str)
{
assert(functions.fpSSL_CTX_set_cipher_list != 0);
typedef int (FuncType)(SSL_CTX*, const char*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_CTX_set_cipher_list);
return fp(ctx, str);
}
long SslGateway::SSL_get_verify_result_(const SSL* s)
{
assert(functions.fpSSL_get_verify_result != 0);
typedef long (FuncType)(const SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_get_verify_result);
return fp(s);
}
int SslGateway::SSL_library_init_()
{
typedef int (FuncType)();
if (functions.fpSSL_library_init)
{
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_library_init);
return fp();
}
return OPENSSL_init_ssl_(0, NULL);
}
void SslGateway::SSL_load_error_strings_()
{
typedef void (FuncType)();
if (functions.fpSSL_load_error_strings)
{
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_load_error_strings);
fp();
return;
}
OPENSSL_init_ssl_(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
}
X509* SslGateway::SSL_get_peer_certificate_(const SSL* s)
{
assert(functions.fpSSL_get_peer_certificate != 0);
typedef X509*(FuncType)(const SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_get_peer_certificate);
return fp(s);
}
long SslGateway::SSL_ctrl_(SSL* s, int cmd, long larg, void* parg)
{
assert(functions.fpSSL_ctrl != 0);
typedef long (FuncType)(SSL*, int, long, void*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_ctrl);
return fp(s, cmd, larg, parg);
}
long SslGateway::SSL_set_tlsext_host_name_(SSL* s, const char* name)
{
return SSL_ctrl_(s, SSL_CTRL_SET_TLSEXT_HOSTNAME,
TLSEXT_NAMETYPE_host_name, const_cast<char*>(name));
}
void SslGateway::SSL_set_connect_state_(SSL* s)
{
assert(functions.fpSSL_set_connect_state != 0);
typedef void (FuncType)(SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_set_connect_state);
return fp(s);
}
int SslGateway::SSL_connect_(SSL* s)
{
assert(functions.fpSSL_connect != 0);
typedef int (FuncType)(SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_connect);
return fp(s);
}
int SslGateway::SSL_get_error_(const SSL* s, int ret)
{
assert(functions.fpSSL_get_error != 0);
typedef int (FuncType)(const SSL*, int);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_get_error);
return fp(s, ret);
}
int SslGateway::SSL_want_(const SSL* s)
{
assert(functions.fpSSL_want != 0);
typedef int (FuncType)(const SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_want);
return fp(s);
}
int SslGateway::SSL_write_(SSL* s, const void* buf, int num)
{
assert(functions.fpSSL_write != 0);
typedef int (FuncType)(SSL*, const void*, int);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_write);
return fp(s, buf, num);
}
int SslGateway::SSL_read_(SSL* s, void* buf, int num)
{
assert(functions.fpSSL_read != 0);
typedef int (FuncType)(SSL*, void*, int);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_read);
return fp(s, buf, num);
}
int SslGateway::SSL_pending_(const SSL* ssl)
{
assert(functions.fpSSL_pending != 0);
typedef int (FuncType)(const SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_pending);
return fp(ssl);
}
int SslGateway::SSL_get_fd_(const SSL* ssl)
{
assert(functions.fpSSL_get_fd != 0);
typedef int (FuncType)(const SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_get_fd);
return fp(ssl);
}
void SslGateway::SSL_free_(SSL* ssl)
{
assert(functions.fpSSL_free != 0);
typedef void (FuncType)(SSL*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSL_free);
fp(ssl);
}
const SSL_METHOD* SslGateway::SSLv23_client_method_()
{
if (functions.fpSSLv23_client_method)
{
typedef const SSL_METHOD*(FuncType)();
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpSSLv23_client_method);
return fp();
}
return TLS_client_method_();
}
const SSL_METHOD* SslGateway::TLS_client_method_()
{
assert(functions.fpTLS_client_method != 0);
typedef const SSL_METHOD*(FuncType)();
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpTLS_client_method);
return fp();
}
void SslGateway::OPENSSL_config_(const char* configName)
{
assert(functions.fpOPENSSL_config != 0);
typedef void (FuncType)(const char*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpOPENSSL_config);
fp(configName);
}
void SslGateway::X509_free_(X509* a)
{
assert(functions.fpX509_free != 0);
typedef void (FuncType)(X509*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpX509_free);
fp(a);
}
BIO* SslGateway::BIO_new_ssl_connect_(SSL_CTX* ctx)
{
assert(functions.fpBIO_new_ssl_connect != 0);
typedef BIO*(FuncType)(SSL_CTX*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpBIO_new_ssl_connect);
return fp(ctx);
}
void SslGateway::BIO_free_all_(BIO* a)
{
assert(functions.fpBIO_free_all != 0);
typedef void (FuncType)(BIO*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpBIO_free_all);
fp(a);
}
long SslGateway::BIO_ctrl_(BIO* bp, int cmd, long larg, void* parg)
{
assert(functions.fpBIO_ctrl != 0);
typedef long (FuncType)(BIO*, int, long, void*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpBIO_ctrl);
return fp(bp, cmd, larg, parg);
}
long SslGateway::BIO_get_fd_(BIO* bp, int* fd)
{
return BIO_ctrl_(bp, BIO_C_GET_FD, 0, reinterpret_cast<void*>(fd));
}
long SslGateway::BIO_get_ssl_(BIO* bp, SSL** ssl)
{
return BIO_ctrl_(bp, BIO_C_GET_SSL, 0, reinterpret_cast<void*>(ssl));
}
long SslGateway::BIO_set_nbio_(BIO* bp, long n)
{
return BIO_ctrl_(bp, BIO_C_SET_NBIO, n, NULL);
}
long SslGateway::BIO_set_conn_hostname_(BIO* bp, const char* name)
{
return BIO_ctrl_(bp, BIO_C_SET_CONNECT, 0, const_cast<char*>(name));
}
unsigned long SslGateway::ERR_get_error_()
{
assert(functions.fpERR_get_error != 0);
typedef unsigned long (FuncType)();
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpERR_get_error);
return fp();
}
void SslGateway::ERR_error_string_n_(unsigned long e, char* buf, size_t len)
{
assert(functions.fpERR_error_string_n != 0);
typedef void (FuncType)(unsigned long, char*, size_t);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpERR_error_string_n);
fp(e, buf, len);
}
void SslGateway::ERR_print_errors_fp_(FILE* fd)
{
if (!functions.fpERR_print_errors_fp)
return;
typedef void (FuncType)(FILE*);
FuncType* fp = reinterpret_cast<FuncType*>(functions.fpERR_print_errors_fp);
fp(fd);
}
}
}
}