From 8a4b58d52c7f838291cbf104a12e3d6925fce4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 21 May 2019 10:03:40 +0300 Subject: [PATCH] MXS-2483: Move SSL configuration into SSLConfig This way the configuration information can be accessed without the SSLContext. --- include/maxscale/server.hh | 7 ++ include/maxscale/ssl.hh | 49 +++++------ server/core/mysql_utils.cc | 9 +- server/core/ssl.cc | 83 +++++++++---------- .../PAM/PAMBackendAuth/pam_backend_auth.cc | 2 +- server/modules/protocol/MySQL/mysql_common.cc | 6 +- .../modules/routing/binlogrouter/blr_slave.cc | 16 ++-- 7 files changed, 89 insertions(+), 83 deletions(-) diff --git a/include/maxscale/server.hh b/include/maxscale/server.hh index 4ee3ab425..61208c252 100644 --- a/include/maxscale/server.hh +++ b/include/maxscale/server.hh @@ -517,6 +517,11 @@ public: */ void response_time_add(double ave, int num_samples); + const mxs::SSLConfig& ssl_config() const + { + return m_ssl_config; + } + mxs::SSLContext* ssl_context() const { return m_ssl_context.get(); @@ -525,6 +530,7 @@ public: void set_ssl_context(std::unique_ptr ssl) { m_ssl_context.swap(ssl); + m_ssl_config = m_ssl_context->config(); } protected: @@ -540,4 +546,5 @@ private: std::mutex m_average_write_mutex; /**< Protects response time from concurrent writing */ std::unique_ptr m_ssl_context; /**< SSL context */ + mxs::SSLConfig m_ssl_config; /**< SSL configuration */ }; diff --git a/include/maxscale/ssl.hh b/include/maxscale/ssl.hh index ddfdda2d3..5d6ad9668 100644 --- a/include/maxscale/ssl.hh +++ b/include/maxscale/ssl.hh @@ -61,6 +61,26 @@ extern const MXS_ENUM_VALUE ssl_version_values[]; namespace maxscale { +// SSL configuration +struct SSLConfig +{ + SSLConfig() = default; + SSLConfig(const MXS_CONFIG_PARAMETER& params); + + // CA must always be defined for non-empty configurations + bool empty() const + { + return ca.empty(); + } + + std::string key; /**< SSL private key */ + std::string cert; /**< SSL certificate */ + std::string ca; /**< SSL CA certificate */ + ssl_method_type_t version = SERVICE_SSL_TLS_MAX; /**< Which TLS version to use */ + int verify_depth = 9; /**< SSL certificate verification depth */ + bool verify_peer = true; /**< Enable peer certificate verification */ +}; + /** * The SSLContext is used to aggregate the SSL configuration and data for a particular object. */ @@ -91,22 +111,10 @@ public: return SSL_new(m_ctx); } - // Private key - const std::string& ssl_key() const + // SSL configuration + const SSLConfig& config() const { - return m_key; - } - - // Public cert - const std::string& ssl_cert() const - { - return m_cert; - } - - // Certificate authority - const std::string& ssl_ca() const - { - return m_ca; + return m_cfg; } // Convert to JSON representation @@ -121,16 +129,9 @@ private: SSL_CTX* m_ctx = nullptr; SSL_METHOD* m_method = nullptr; /**< SSLv3 or TLS1.0/1.1/1.2 methods * see: https://www.openssl.org/docs/ssl/SSL_CTX_new.html */ + SSLConfig m_cfg; - std::string m_key; /**< SSL private key */ - std::string m_cert; /**< SSL certificate */ - std::string m_ca; /**< SSL CA certificate */ - ssl_method_type_t m_version; /**< Which TLS version to use */ - int m_verify_depth; /**< SSL certificate verification depth */ - bool m_verify_peer; /**< Enable peer certificate verification */ - - SSLContext(const std::string& key, const std::string& cert, const std::string& ca, - ssl_method_type_t version, int verify_depth, bool verify_peer_cert); + SSLContext(const SSLConfig& cfg); bool init(); }; } diff --git a/server/core/mysql_utils.cc b/server/core/mysql_utils.cc index f2bef85b9..6b8faf791 100644 --- a/server/core/mysql_utils.cc +++ b/server/core/mysql_utils.cc @@ -155,12 +155,11 @@ char* mxs_lestr_consume(uint8_t** c, size_t* size) MYSQL* mxs_mysql_real_connect(MYSQL* con, SERVER* server, const char* user, const char* passwd) { - mxs::SSLContext* ssl = server->ssl_context(); + auto ssl = server->ssl_config(); - if (ssl) + if (!ssl.empty()) { - mysql_ssl_set(con, ssl->ssl_key().c_str(), ssl->ssl_cert().c_str(), ssl->ssl_ca().c_str(), - NULL, NULL); + mysql_ssl_set(con, ssl.key.c_str(), ssl.cert.c_str(), ssl.ca.c_str(), NULL, NULL); } char yes = 1; @@ -205,7 +204,7 @@ MYSQL* mxs_mysql_real_connect(MYSQL* con, SERVER* server, const char* user, cons mysql_get_character_set_info(mysql, &cs_info); server->charset = cs_info.number; - if (ssl && mysql_get_ssl_cipher(con) == NULL) + if (!ssl.empty() && mysql_get_ssl_cipher(con) == NULL) { if (server->warn_ssl_not_enabled) { diff --git a/server/core/ssl.cc b/server/core/ssl.cc index 5d8216ad2..1c6c08fca 100644 --- a/server/core/ssl.cc +++ b/server/core/ssl.cc @@ -199,6 +199,17 @@ static const char* get_ssl_errors() namespace maxscale { + +SSLConfig::SSLConfig(const MXS_CONFIG_PARAMETER& params) + : key(params.get_string(CN_SSL_KEY)) + , cert(params.get_string(CN_SSL_CERT)) + , ca(params.get_string(CN_SSL_CA_CERT)) + , version((ssl_method_type_t)params.get_enum(CN_SSL_VERSION, ssl_version_values)) + , verify_depth(params.get_integer(CN_SSL_CERT_VERIFY_DEPTH)) + , verify_peer(params.get_bool(CN_SSL_VERIFY_PEER_CERTIFICATE)) +{ +} + // static std::unique_ptr SSLContext::create(const MXS_CONFIG_PARAMETER& params) { @@ -208,13 +219,7 @@ std::unique_ptr SSLContext::create(const MXS_CONFIG_PARAMETER& param mxb_assert(params.get_string(CN_SSL_KEY).empty() || access(params.get_string(CN_SSL_KEY).c_str(), F_OK) == 0); - std::unique_ptr ssl( - new(std::nothrow) SSLContext(params.get_string(CN_SSL_KEY), - params.get_string(CN_SSL_CERT), - params.get_string(CN_SSL_CA_CERT), - (ssl_method_type_t)params.get_enum(CN_SSL_VERSION, ssl_version_values), - params.get_integer(CN_SSL_CERT_VERIFY_DEPTH), - params.get_bool(CN_SSL_VERIFY_PEER_CERTIFICATE))); + std::unique_ptr ssl(new(std::nothrow) SSLContext(SSLConfig(params))); if (ssl && !ssl->init()) { @@ -224,14 +229,8 @@ std::unique_ptr SSLContext::create(const MXS_CONFIG_PARAMETER& param return ssl; } -SSLContext::SSLContext(const std::string& key, const std::string& cert, const std::string& ca, - ssl_method_type_t version, int verify_depth, bool verify_peer) - : m_key(key) - , m_cert(cert) - , m_ca(ca) - , m_version(version) - , m_verify_depth(verify_depth) - , m_verify_peer(verify_peer) +SSLContext::SSLContext(const SSLConfig& cfg) + : m_cfg(cfg) { } @@ -240,21 +239,21 @@ std::string SSLContext::serialize() const std::ostringstream ss; ss << "ssl=required\n"; - if (!m_cert.empty()) + if (!m_cfg.cert.empty()) { - ss << "ssl_cert=" << m_cert << "\n"; + ss << "ssl_cert=" << m_cfg.cert << "\n"; } - if (!m_key.empty()) + if (!m_cfg.key.empty()) { - ss << "ssl_key=" << m_key << "\n"; + ss << "ssl_key=" << m_cfg.key << "\n"; } - mxb_assert(!m_ca.empty()); - ss << "ssl_ca_cert=" << m_ca << "\n"; - ss << "ssl_version=" << ssl_method_type_to_string(m_version) << "\n"; - ss << "ssl_cert_verify_depth=" << m_verify_depth << "\n"; - ss << "ssl_verify_peer_certificate=" << (m_verify_peer ? "true" : "false") << "\n"; + mxb_assert(!m_cfg.ca.empty()); + ss << "ssl_ca_cert=" << m_cfg.ca << "\n"; + ss << "ssl_version=" << ssl_method_type_to_string(m_cfg.version) << "\n"; + ss << "ssl_cert_verify_depth=" << m_cfg.verify_depth << "\n"; + ss << "ssl_verify_peer_certificate=" << (m_cfg.verify_peer ? "true" : "false") << "\n"; return ss.str(); } @@ -262,7 +261,7 @@ bool SSLContext::init() { bool rval = true; - switch (m_version) + switch (m_cfg.version) { #ifndef OPENSSL_1_1 case SERVICE_TLS10: @@ -337,26 +336,26 @@ bool SSLContext::init() SSL_CTX_set_tmp_rsa_callback(m_ctx, tmp_rsa_callback); } - mxb_assert(!m_ca.empty()); + mxb_assert(!m_cfg.ca.empty()); /* Load the CA certificate into the SSL_CTX structure */ - if (!SSL_CTX_load_verify_locations(m_ctx, m_ca.c_str(), NULL)) + if (!SSL_CTX_load_verify_locations(m_ctx, m_cfg.ca.c_str(), NULL)) { MXS_ERROR("Failed to set Certificate Authority file"); return false; } - if (!m_cert.empty() && !m_key.empty()) + if (!m_cfg.cert.empty() && !m_cfg.key.empty()) { /** Load the server certificate */ - if (SSL_CTX_use_certificate_chain_file(m_ctx, m_cert.c_str()) <= 0) + if (SSL_CTX_use_certificate_chain_file(m_ctx, m_cfg.cert.c_str()) <= 0) { MXS_ERROR("Failed to set server SSL certificate: %s", get_ssl_errors()); return false; } /* Load the private-key corresponding to the server certificate */ - if (SSL_CTX_use_PrivateKey_file(m_ctx, m_key.c_str(), SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_PrivateKey_file(m_ctx, m_cfg.key.c_str(), SSL_FILETYPE_PEM) <= 0) { MXS_ERROR("Failed to set server SSL key: %s", get_ssl_errors()); return false; @@ -371,13 +370,13 @@ bool SSLContext::init() } /* Set to require peer (client) certificate verification */ - if (m_verify_peer) + if (m_cfg.verify_peer) { SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER, NULL); } /* Set the verification depth */ - SSL_CTX_set_verify_depth(m_ctx, m_verify_depth); + SSL_CTX_set_verify_depth(m_ctx, m_cfg.verify_depth); return true; } @@ -385,12 +384,12 @@ bool SSLContext::init() json_t* SSLContext::to_json() const { json_t* ssl = json_object(); - const char* ssl_method = ssl_method_type_to_string(m_version); + const char* ssl_method = ssl_method_type_to_string(m_cfg.version); json_object_set_new(ssl, "ssl_version", json_string(ssl_method)); - json_object_set_new(ssl, "ssl_cert", json_string(m_cert.c_str())); - json_object_set_new(ssl, "ssl_ca_cert", json_string(m_ca.c_str())); - json_object_set_new(ssl, "ssl_key", json_string(m_key.c_str())); + json_object_set_new(ssl, "ssl_cert", json_string(m_cfg.cert.c_str())); + json_object_set_new(ssl, "ssl_ca_cert", json_string(m_cfg.ca.c_str())); + json_object_set_new(ssl, "ssl_key", json_string(m_cfg.key.c_str())); return ssl; } @@ -400,12 +399,12 @@ std::string SSLContext::to_string() const std::ostringstream ss; ss << "\tSSL initialized: yes\n" - << "\tSSL method type: " << ssl_method_type_to_string(m_version) << "\n" - << "\tSSL certificate verification depth: " << m_verify_depth << "\n" - << "\tSSL peer verification : " << (m_verify_peer ? "true" : "false") << "\n" - << "\tSSL certificate: " << m_cert << "\n" - << "\tSSL key: " << m_key << "\n" - << "\tSSL CA certificate: " << m_ca << "\n"; + << "\tSSL method type: " << ssl_method_type_to_string(m_cfg.version) << "\n" + << "\tSSL certificate verification depth: " << m_cfg.verify_depth << "\n" + << "\tSSL peer verification : " << (m_cfg.verify_peer ? "true" : "false") << "\n" + << "\tSSL certificate: " << m_cfg.cert << "\n" + << "\tSSL key: " << m_cfg.key << "\n" + << "\tSSL CA certificate: " << m_cfg.ca << "\n"; return ss.str(); } diff --git a/server/modules/authenticator/PAM/PAMBackendAuth/pam_backend_auth.cc b/server/modules/authenticator/PAM/PAMBackendAuth/pam_backend_auth.cc index 7f2aa1b43..68c7819de 100644 --- a/server/modules/authenticator/PAM/PAMBackendAuth/pam_backend_auth.cc +++ b/server/modules/authenticator/PAM/PAMBackendAuth/pam_backend_auth.cc @@ -52,7 +52,7 @@ static bool pam_backend_auth_extract(DCB* dcb, GWBUF* buffer) */ static bool pam_backend_auth_connectssl(DCB* dcb) { - return dcb->server->ssl_context() != NULL; + return dcb->server->ssl_context(); } /** diff --git a/server/modules/protocol/MySQL/mysql_common.cc b/server/modules/protocol/MySQL/mysql_common.cc index a405933a8..5e3cb40c4 100644 --- a/server/modules/protocol/MySQL/mysql_common.cc +++ b/server/modules/protocol/MySQL/mysql_common.cc @@ -952,10 +952,8 @@ mxs_auth_state_t gw_send_backend_auth(DCB* dcb) mxs_auth_state_t rval = MXS_AUTH_STATE_FAILED; if (dcb->session == NULL - || (dcb->session->state != SESSION_STATE_CREATED - && dcb->session->state != SESSION_STATE_STARTED) - || (dcb->server->ssl_context() - && dcb->ssl_state == SSL_HANDSHAKE_FAILED)) + || (dcb->session->state != SESSION_STATE_CREATED && dcb->session->state != SESSION_STATE_STARTED) + || (dcb->server->ssl_context() && dcb->ssl_state == SSL_HANDSHAKE_FAILED)) { return rval; } diff --git a/server/modules/routing/binlogrouter/blr_slave.cc b/server/modules/routing/binlogrouter/blr_slave.cc index 48f93e2a5..a8088eb2a 100644 --- a/server/modules/routing/binlogrouter/blr_slave.cc +++ b/server/modules/routing/binlogrouter/blr_slave.cc @@ -4850,24 +4850,26 @@ static void blr_master_get_config(ROUTER_INSTANCE* router, MasterServerConfig* c curr_master->password = router->password; curr_master->filestem = router->fileroot; /* SSL options */ - if (auto server_ssl = router->service->dbref->server->ssl_context()) + auto server_ssl = router->service->dbref->server->ssl_config(); + + if (!server_ssl.empty()) { curr_master->ssl_enabled = router->ssl_enabled; if (router->ssl_version) { curr_master->ssl_version = router->ssl_version; } - if (!server_ssl->ssl_key().empty()) + if (!server_ssl.key.empty()) { - curr_master->ssl_key = server_ssl->ssl_key(); + curr_master->ssl_key = server_ssl.key; } - if (!server_ssl->ssl_cert().empty()) + if (!server_ssl.cert.empty()) { - curr_master->ssl_cert = server_ssl->ssl_cert(); + curr_master->ssl_cert = server_ssl.cert; } - if (!server_ssl->ssl_ca().empty()) + if (!server_ssl.ca.empty()) { - curr_master->ssl_ca = server_ssl->ssl_ca(); + curr_master->ssl_ca = server_ssl.ca; } } /* Connect options */