MXS-2483: Move SSL functionality into SSLProvider

The class is intended to be inherited by objects that need an SSL context
and a configuration. In practice this will be servers and listeners.

The SSLContext is stored in a rworker_local shared_ptr that makes it
possible to update safely. As the copying is always done behind a lock the
cached local value always holds a valid SSLContext instance for the
duration of all function calls.

Using the pImpl idiom, the routingworker.hh header is not exposed in the
ssl.hh header. This allows the SSLProvider class to be inherited more
easily.
This commit is contained in:
Markus Mäkelä 2019-05-21 11:15:36 +03:00
parent 8a4b58d52c
commit cb72b2a5cc
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
2 changed files with 82 additions and 1 deletions

View File

@ -58,6 +58,9 @@ ssl_method_type_t string_to_ssl_method_type(const char* str);
extern const MXS_ENUM_VALUE ssl_version_values[];
// The concrete implementation of the SSLProvider class (hides the dependency on routingworker.hh)
class SSLProviderImp;
namespace maxscale
{
@ -134,4 +137,19 @@ private:
SSLContext(const SSLConfig& cfg);
bool init();
};
// A SSL connection provider (incoming or outgoing). Used by servers and listeners.
class SSLProvider
{
public:
const mxs::SSLConfig& config() const;
mxs::SSLContext* context() const;
void set_context(std::unique_ptr<mxs::SSLContext> ssl);
SSLProvider(std::unique_ptr<mxs::SSLContext>&& context);
~SSLProvider();
private:
std::unique_ptr<SSLProviderImp> m_imp;
};
}

View File

@ -33,6 +33,7 @@
#include <maxscale/dcb.hh>
#include <maxscale/poll.hh>
#include <maxscale/service.hh>
#include <maxscale/routingworker.hh>
static RSA* rsa_512 = NULL;
static RSA* rsa_1024 = NULL;
@ -196,10 +197,48 @@ static const char* get_ssl_errors()
return ssl_errbuf->c_str();
}
class SSLProviderImp
{
public:
const mxs::SSLConfig& config() const;
mxs::SSLContext* context() const;
void set_context(std::unique_ptr<mxs::SSLContext> ssl);
SSLProviderImp(std::unique_ptr<mxs::SSLContext>&& context);
private:
mxs::rworker_local<std::shared_ptr<mxs::SSLContext>> m_context; /**< SSL context */
mxs::SSLConfig m_config; /**< SSL configuration */
};
const mxs::SSLConfig& SSLProviderImp::config() const
{
return m_config;
}
mxs::SSLContext* SSLProviderImp::context() const
{
mxb_assert_message(mxs::RoutingWorker::get_current(), "Must be used on a RoutingWorker");
return m_context->get();
}
void SSLProviderImp::set_context(std::unique_ptr<mxs::SSLContext> ssl)
{
mxb_assert_message(mxs::RoutingWorker::get_current()
== mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN),
"Must be only set on the main RoutingWorker");
m_config = ssl ? ssl->config() : mxs::SSLConfig {};
m_context.assign(std::move(ssl));
}
SSLProviderImp::SSLProviderImp(std::unique_ptr<mxs::SSLContext>&& context)
: m_context {std::move(context)}
{
}
namespace maxscale
{
SSLConfig::SSLConfig(const MXS_CONFIG_PARAMETER& params)
: key(params.get_string(CN_SSL_KEY))
, cert(params.get_string(CN_SSL_CERT))
@ -413,4 +452,28 @@ SSLContext::~SSLContext()
{
SSL_CTX_free(m_ctx);
}
SSLProvider::SSLProvider(std::unique_ptr<mxs::SSLContext>&& ssl)
: m_imp(new SSLProviderImp(std::move(ssl)))
{
}
SSLProvider::~SSLProvider()
{
}
mxs::SSLContext* SSLProvider::context() const
{
return m_imp->context();
}
const mxs::SSLConfig& SSLProvider::config() const
{
return m_imp->config();
}
void SSLProvider::set_context(std::unique_ptr<mxs::SSLContext> ssl)
{
m_imp->set_context(std::move(ssl));
}
}