From d28b1c9d1db916548e3f4ace23e6a54e89e6dd24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 14 Jul 2018 23:02:45 +0300 Subject: [PATCH] Validate SSL parameters via the module-type parameters The configuration system that modules use allows the SSL parameter validation to be simplified. It should also provide more consistent error messages for similar types of errors. The SSL_LISTENER initialization is now done in one step. There was no good reason to do it in two separate steps for listeners but in one step for servers. The `ssl` parameter now also accepts boolean values. As the parameter behaves like a boolean and looks like a boolean, it ought to be a boolean. It still accepts the custom `required` and `disabled` values simply for backwards compatibility. Also added the missing freeing functions for the SSL_LISTENER type. This prevents failed SSL_LISTENER creations from leaking memory. --- include/maxscale/listener.h | 26 +- server/core/config.cc | 250 ++++++++---------- server/core/config_runtime.cc | 8 +- server/core/internal/config.h | 13 +- server/core/listener.cc | 216 ++++++++------- server/core/service.cc | 5 - server/modules/routing/binlogrouter/blr.cc | 22 +- .../modules/routing/binlogrouter/blr_slave.cc | 22 -- 8 files changed, 267 insertions(+), 295 deletions(-) diff --git a/include/maxscale/listener.h b/include/maxscale/listener.h index 0a4aff2b4..3fcf1e1b9 100644 --- a/include/maxscale/listener.h +++ b/include/maxscale/listener.h @@ -82,7 +82,31 @@ SERV_LISTENER* listener_alloc(struct service* service, const char* name, const c void listener_free(SERV_LISTENER* listener); int listener_set_ssl_version(SSL_LISTENER *ssl_listener, char* version); void listener_set_certificates(SSL_LISTENER *ssl_listener, char* cert, char* key, char* ca_cert); -int listener_init_SSL(SSL_LISTENER *ssl_listener); + + +/** + * Initialize SSL configuration + * + * This sets up the generated RSA encryption keys, chooses the listener + * encryption level and configures the listener certificate, private key and + * certificate authority file. + * + * @note This function should not be called directly, use config_create_ssl() instead + * + * @todo Combine this with config_create_ssl() into one function + * + * @param ssl SSL configuration to initialize + * + * @return True on success, false on error + */ +bool SSL_LISTENER_init(SSL_LISTENER* ssl); + +/** + * Free an SSL_LISTENER + * + * @param ssl SSL_LISTENER to free + */ +void SSL_LISTENER_free(SSL_LISTENER* ssl); /** * @brief Check if listener is active diff --git a/server/core/config.cc b/server/core/config.cc index 5a58fa3ca..646b9bfd1 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -224,6 +224,36 @@ char *version_string = NULL; static bool is_persisted_config = false; /**< True if a persisted configuration file is being parsed */ static CONFIG_CONTEXT config_context; +// Values for the `ssl` parameter. These are plain boolean types but for legacy +// reasons the required and disabled keywords need to be allowed. +static const MXS_ENUM_VALUE ssl_values[] = +{ + {"required", 1}, + {"true", 1}, + {"yes", 1}, + {"on", 1}, + {"1", 1}, + {"disabled", 0}, + {"false", 0}, + {"no", 0}, + {"off", 0}, + {"0", 0}, + {NULL} +}; + +static const MXS_ENUM_VALUE ssl_version_values[] = +{ + {"MAX", 1}, +#ifndef OPENSSL_1_1 + {"TLSV10", 1}, +#endif +#ifdef OPENSSL_1_0 + {"TLSV11", 1}, + {"TLSV12", 1}, +#endif + {NULL} +}; + const MXS_MODULE_PARAM config_service_params[] = { {CN_TYPE, MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED}, @@ -258,13 +288,13 @@ const MXS_MODULE_PARAM config_listener_params[] = {CN_PROTOCOL, MXS_MODULE_PARAM_STRING, "MariaDBClient"}, {CN_ADDRESS, MXS_MODULE_PARAM_STRING, "::"}, {CN_AUTHENTICATOR, MXS_MODULE_PARAM_STRING}, - {CN_SSL, MXS_MODULE_PARAM_STRING}, - {CN_SSL_CERT, MXS_MODULE_PARAM_STRING}, - {CN_SSL_KEY, MXS_MODULE_PARAM_STRING}, - {CN_SSL_CA_CERT, MXS_MODULE_PARAM_STRING}, - {CN_SSL_VERSION, MXS_MODULE_PARAM_STRING}, - {CN_SSL_CERT_VERIFY_DEPTH, MXS_MODULE_PARAM_STRING}, - {CN_SSL_VERIFY_PEER_CERTIFICATE, MXS_MODULE_PARAM_STRING}, + {CN_SSL, MXS_MODULE_PARAM_STRING, "false", MXS_MODULE_OPT_ENUM_UNIQUE, ssl_values}, + {CN_SSL_CERT, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_KEY, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_CA_CERT, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_VERSION, MXS_MODULE_PARAM_STRING, "MAX", MXS_MODULE_OPT_ENUM_UNIQUE, ssl_version_values}, + {CN_SSL_CERT_VERIFY_DEPTH, MXS_MODULE_PARAM_COUNT, "9"}, + {CN_SSL_VERIFY_PEER_CERTIFICATE, MXS_MODULE_PARAM_BOOL, "true"}, {NULL} }; @@ -302,19 +332,19 @@ const MXS_MODULE_PARAM config_server_params[] = {CN_ADDRESS, MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED}, {CN_PROTOCOL, MXS_MODULE_PARAM_STRING, "MariaDBBackend"}, {CN_PORT, MXS_MODULE_PARAM_COUNT, "3306"}, - {CN_AUTHENTICATOR, MXS_MODULE_PARAM_STRING, "MySQLBackendAuth"}, + {CN_AUTHENTICATOR, MXS_MODULE_PARAM_STRING}, {CN_MONITORUSER, MXS_MODULE_PARAM_STRING}, {CN_MONITORPW, MXS_MODULE_PARAM_STRING}, {CN_PERSISTPOOLMAX, MXS_MODULE_PARAM_COUNT, "0"}, {CN_PERSISTMAXTIME, MXS_MODULE_PARAM_COUNT, "0"}, {CN_PROXY_PROTOCOL, MXS_MODULE_PARAM_BOOL, "false"}, - {CN_SSL, MXS_MODULE_PARAM_STRING}, - {CN_SSL_CERT, MXS_MODULE_PARAM_PATH}, - {CN_SSL_KEY, MXS_MODULE_PARAM_PATH}, - {CN_SSL_CA_CERT, MXS_MODULE_PARAM_PATH}, - {CN_SSL_VERSION, MXS_MODULE_PARAM_STRING}, - {CN_SSL_CERT_VERIFY_DEPTH, MXS_MODULE_PARAM_COUNT}, - {CN_SSL_VERIFY_PEER_CERTIFICATE, MXS_MODULE_PARAM_BOOL}, + {CN_SSL, MXS_MODULE_PARAM_STRING, "false", MXS_MODULE_OPT_ENUM_UNIQUE, ssl_values}, + {CN_SSL_CERT, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_KEY, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_CA_CERT, MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, + {CN_SSL_VERSION, MXS_MODULE_PARAM_STRING, "MAX", MXS_MODULE_OPT_ENUM_UNIQUE, ssl_version_values}, + {CN_SSL_CERT_VERIFY_DEPTH, MXS_MODULE_PARAM_COUNT, "9"}, + {CN_SSL_VERIFY_PEER_CERTIFICATE, MXS_MODULE_PARAM_BOOL, "true"}, {NULL} }; @@ -2097,133 +2127,80 @@ free_ssl_structure(SSL_LISTENER *ssl) } } -/** - * Form an SSL structure from listener section parameters - * - * @param obj The configuration object for the item being created - * @param require_cert Whether a certificate and key are required - * @param *error_count An error count which may be incremented - * @return SSL_LISTENER structure or NULL - */ -SSL_LISTENER* make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *error_count) +bool config_create_ssl(const char* name, MXS_CONFIG_PARAMETER* params, + bool require_cert, SSL_LISTENER** dest) { - char *ssl, *ssl_version, *ssl_cert, *ssl_key, *ssl_ca_cert, *ssl_cert_verify_depth; - int local_errors = 0; - SSL_LISTENER *new_ssl; + SSL_LISTENER* ssl = NULL; - ssl = config_get_value(obj->parameters, CN_SSL); + // The enum values convert to bool + int value = config_get_enum(params, CN_SSL, ssl_values); + ss_dassert(value != -1); - if (ssl) + if (value) { - if (!strcmp(ssl, CN_REQUIRED)) + bool error = false; + char* ssl_cert = config_get_value(params, CN_SSL_CERT); + char* ssl_key = config_get_value(params, CN_SSL_KEY); + char* ssl_ca_cert = config_get_value(params, CN_SSL_CA_CERT); + + if (ssl_ca_cert == NULL) { - if ((new_ssl = (SSL_LISTENER*)MXS_CALLOC(1, sizeof(SSL_LISTENER))) == NULL) - { - return NULL; - } - new_ssl->ssl_method_type = SERVICE_SSL_TLS_MAX; - ssl_cert = config_get_value(obj->parameters, CN_SSL_CERT); - ssl_key = config_get_value(obj->parameters, CN_SSL_KEY); - ssl_ca_cert = config_get_value(obj->parameters, CN_SSL_CA_CERT); - ssl_version = config_get_value(obj->parameters, CN_SSL_VERSION); - ssl_cert_verify_depth = config_get_value(obj->parameters, CN_SSL_CERT_VERIFY_DEPTH); - const char* ssl_verify_peer_certificate = config_get_value(obj->parameters, CN_SSL_VERIFY_PEER_CERTIFICATE); - new_ssl->ssl_init_done = false; - new_ssl->ssl_cert_verify_depth = 9; // Default of 9 as per Linux man page - new_ssl->ssl_verify_peer_certificate = true; - - if (ssl_version && listener_set_ssl_version(new_ssl, ssl_version) != 0) - { - MXS_ERROR("Unknown parameter value for 'ssl_version' for '%s': %s", - obj->object, ssl_version); - local_errors++; - } - - if (ssl_cert_verify_depth && - (new_ssl->ssl_cert_verify_depth = atoi(ssl_cert_verify_depth)) < 0) - { - MXS_ERROR("Invalid parameter value for 'ssl_cert_verify_depth for '%s': %s", - obj->object, ssl_cert_verify_depth); - new_ssl->ssl_cert_verify_depth = 0; - local_errors++; - } - - if (ssl_verify_peer_certificate) - { - int rv = config_truth_value(ssl_verify_peer_certificate); - if (rv == -1) - { - MXS_ERROR("Invalid parameter value for 'ssl_verify_peer_certificate" - " for '%s': %s", obj->object, ssl_verify_peer_certificate); - local_errors++; - } - else - { - new_ssl->ssl_verify_peer_certificate = rv; - } - } - - listener_set_certificates(new_ssl, ssl_cert, ssl_key, ssl_ca_cert); - - if (require_cert) - { - if (new_ssl->ssl_cert == NULL) - { - local_errors++; - MXS_ERROR("Server certificate missing for listener '%s'." - "Please provide the path to the server certificate by adding " - "the ssl_cert= parameter", obj->object); - } - else if (access(new_ssl->ssl_cert, F_OK) != 0) - { - MXS_ERROR("Server certificate file for listener '%s' not found: %s", - obj->object, new_ssl->ssl_cert); - local_errors++; - } - - if (new_ssl->ssl_key == NULL) - { - local_errors++; - MXS_ERROR("Server private key missing for listener '%s'. " - "Please provide the path to the server certificate key by " - "adding the ssl_key= parameter", obj->object); - } - else if (access(new_ssl->ssl_key, F_OK) != 0) - { - MXS_ERROR("Server private key file for listener '%s' not found: %s", - obj->object, new_ssl->ssl_key); - local_errors++; - } - } - - if (new_ssl->ssl_ca_cert == NULL) - { - local_errors++; - MXS_ERROR("CA Certificate missing for '%s'." - "Please provide the path to the certificate authority " - "certificate by adding the ssl_ca_cert= parameter", - obj->object); - } - else if (access(new_ssl->ssl_ca_cert, F_OK) != 0) - { - MXS_ERROR("Certificate authority file for '%s' not found: %s", - obj->object, new_ssl->ssl_ca_cert); - local_errors++; - } - - if (0 == local_errors) - { - return new_ssl; - } - *error_count += local_errors; - MXS_FREE(new_ssl); + MXS_ERROR("CA Certificate missing for '%s'." + "Please provide the path to the certificate authority " + "certificate by adding the ssl_ca_cert= parameter", + name); + error = true; } - else if (strcmp(ssl, "disabled") != 0) + + if (require_cert) { - MXS_ERROR("Unknown value for 'ssl': %s. Service will not use SSL.", ssl); + if (ssl_cert == NULL) + { + MXS_ERROR("Server certificate missing for listener '%s'." + "Please provide the path to the server certificate by adding " + "the ssl_cert= parameter", name); + error = true; + } + + if (ssl_key == NULL) + { + MXS_ERROR("Server private key missing for listener '%s'. " + "Please provide the path to the server certificate key by " + "adding the ssl_key= parameter", name); + error = true; + } + } + + if (error) + { + return false; + } + + ssl = (SSL_LISTENER*)MXS_CALLOC(1, sizeof(SSL_LISTENER)); + MXS_ABORT_IF_NULL(ssl); + + int ssl_version = config_get_enum(params, CN_SSL_VERSION, ssl_version_values); + + ssl->ssl_method_type = (ssl_method_type_t)ssl_version; + ssl->ssl_init_done = false; + ssl->ssl_cert_verify_depth = config_get_integer(params, CN_SSL_CERT_VERIFY_DEPTH); + ssl->ssl_verify_peer_certificate = config_get_bool(params, CN_SSL_VERIFY_PEER_CERTIFICATE); + + listener_set_certificates(ssl, ssl_cert, ssl_key, ssl_ca_cert); + + ss_dassert(access(ssl_ca_cert, F_OK) == 0); + ss_dassert(!ssl_cert || access(ssl_cert, F_OK) == 0); + ss_dassert(!ssl_key || access(ssl_key, F_OK) == 0); + + if (!SSL_LISTENER_init(ssl)) + { + SSL_LISTENER_free(ssl); + return false; } } - return NULL; + + *dest = ssl; + return true; } void config_set_global_defaults() @@ -3504,7 +3481,12 @@ int create_new_listener(CONFIG_CONTEXT *obj) } const char *protocol = config_get_string(obj->parameters, CN_PROTOCOL); - SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count); + SSL_LISTENER *ssl_info = NULL; + + if (!config_create_ssl(obj->object, obj->parameters, true, &ssl_info)) + { + return 1; + } // These two values being NULL trigger the loading of the default // authenticators that are specific to each protocol module diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 9bcc81bbc..7846c03a7 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -262,13 +262,7 @@ static SSL_LISTENER* create_ssl(const char *name, const char *key, const char *c (!depth || config_add_param(obj, CN_SSL_CERT_VERIFY_DEPTH, depth)) && (!verify || config_add_param(obj, CN_SSL_VERIFY_PEER_CERTIFICATE, verify))) { - int err = 0; - SSL_LISTENER *ssl = make_ssl_structure(obj, true, &err); - - if (err == 0 && ssl && listener_init_SSL(ssl) == 0) - { - rval = ssl; - } + config_create_ssl(name, obj->parameters, true, &rval); } config_context_free(obj); diff --git a/server/core/internal/config.h b/server/core/internal/config.h index 9f6927145..d47651ed6 100644 --- a/server/core/internal/config.h +++ b/server/core/internal/config.h @@ -135,14 +135,15 @@ void config_remove_param(CONFIG_CONTEXT* obj, const char* name); * * The SSL structure is used by both listeners and servers. * - * TODO: Rename to something like @c config_construct_ssl - * - * @param obj Configuration context + * @param name Name of object being created (usually server or listener name) + * @param params Parameters to create SSL from * @param require_cert Whether certificates are required - * @param error_count Pointer to an int which is incremented for each error - * @return New SSL_LISTENER structure or NULL on error + * @param dest Pointer where initialized SSL structure is stored + * + * @return True on success, false on error */ -SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *error_count); +bool config_create_ssl(const char* name, MXS_CONFIG_PARAMETER* params, + bool require_cert, SSL_LISTENER** dest); /** * @brief Check if all SSL parameters are defined diff --git a/server/core/listener.cc b/server/core/listener.cc index 3ab74cd4c..5c783a825 100644 --- a/server/core/listener.cc +++ b/server/core/listener.cc @@ -260,127 +260,145 @@ static const char* get_ssl_errors() return ssl_errbuf->c_str(); } -/** - * Initialize the listener's SSL context. This sets up the generated RSA - * encryption keys, chooses the listener encryption level and configures the - * listener certificate, private key and certificate authority file. - * @param ssl_listener Listener data to initialize - * @return 0 on success, -1 on error - */ -int -listener_init_SSL(SSL_LISTENER *ssl_listener) +bool SSL_LISTENER_init(SSL_LISTENER* ssl) { - DH* dh; - RSA* rsa; + ss_dassert(!ssl->ssl_init_done); + bool rval = true; - if (!ssl_listener->ssl_init_done) + switch (ssl->ssl_method_type) { - switch (ssl_listener->ssl_method_type) - { #ifndef OPENSSL_1_1 case SERVICE_TLS10: - ssl_listener->method = (SSL_METHOD*)TLSv1_method(); + ssl->method = (SSL_METHOD*)TLSv1_method(); break; #endif #ifdef OPENSSL_1_0 case SERVICE_TLS11: - ssl_listener->method = (SSL_METHOD*)TLSv1_1_method(); + ssl->method = (SSL_METHOD*)TLSv1_1_method(); break; case SERVICE_TLS12: - ssl_listener->method = (SSL_METHOD*)TLSv1_2_method(); + ssl->method = (SSL_METHOD*)TLSv1_2_method(); break; #endif - /** Rest of these use the maximum available SSL/TLS methods */ + /** Rest of these use the maximum available SSL/TLS methods */ case SERVICE_SSL_MAX: - ssl_listener->method = (SSL_METHOD*)SSLv23_method(); + ssl->method = (SSL_METHOD*)SSLv23_method(); break; case SERVICE_TLS_MAX: - ssl_listener->method = (SSL_METHOD*)SSLv23_method(); + ssl->method = (SSL_METHOD*)SSLv23_method(); break; case SERVICE_SSL_TLS_MAX: - ssl_listener->method = (SSL_METHOD*)SSLv23_method(); + ssl->method = (SSL_METHOD*)SSLv23_method(); break; default: - ssl_listener->method = (SSL_METHOD*)SSLv23_method(); + ssl->method = (SSL_METHOD*)SSLv23_method(); break; - } - - if ((ssl_listener->ctx = SSL_CTX_new(ssl_listener->method)) == NULL) - { - MXS_ERROR("SSL context initialization failed: %s", get_ssl_errors()); - return -1; - } - - SSL_CTX_set_default_read_ahead(ssl_listener->ctx, 0); - - /** Enable all OpenSSL bug fixes */ - SSL_CTX_set_options(ssl_listener->ctx, SSL_OP_ALL); - - /** Disable SSLv3 */ - SSL_CTX_set_options(ssl_listener->ctx, SSL_OP_NO_SSLv3); - - // Disable session cache - SSL_CTX_set_session_cache_mode(ssl_listener->ctx, SSL_SESS_CACHE_OFF); - - /** Generate the 512-bit and 1024-bit RSA keys */ - if (rsa_512 == NULL && (rsa_512 = create_rsa(512)) == NULL) - { - MXS_ERROR("512-bit RSA key generation failed."); - return -1; - } - if (rsa_1024 == NULL && (rsa_1024 = create_rsa(1024)) == NULL) - { - MXS_ERROR("1024-bit RSA key generation failed."); - return -1; - } - - ss_dassert(rsa_512 && rsa_1024); - SSL_CTX_set_tmp_rsa_callback(ssl_listener->ctx, tmp_rsa_callback); - - ss_dassert(ssl_listener->ssl_ca_cert); - - /* Load the CA certificate into the SSL_CTX structure */ - if (!SSL_CTX_load_verify_locations(ssl_listener->ctx, ssl_listener->ssl_ca_cert, NULL)) - { - MXS_ERROR("Failed to set Certificate Authority file"); - return -1; - } - - if (ssl_listener->ssl_cert && ssl_listener->ssl_key) - { - /** Load the server certificate */ - if (SSL_CTX_use_certificate_chain_file(ssl_listener->ctx, ssl_listener->ssl_cert) <= 0) - { - MXS_ERROR("Failed to set server SSL certificate: %s", get_ssl_errors()); - return -1; - } - - /* Load the private-key corresponding to the server certificate */ - if (SSL_CTX_use_PrivateKey_file(ssl_listener->ctx, ssl_listener->ssl_key, SSL_FILETYPE_PEM) <= 0) - { - MXS_ERROR("Failed to set server SSL key: %s", get_ssl_errors()); - return -1; - } - - /* Check if the server certificate and private-key matches */ - if (!SSL_CTX_check_private_key(ssl_listener->ctx)) - { - MXS_ERROR("Server SSL certificate and key do not match: %s", get_ssl_errors()); - return -1; - } - } - - /* Set to require peer (client) certificate verification */ - if (ssl_listener->ssl_verify_peer_certificate) - { - SSL_CTX_set_verify(ssl_listener->ctx, SSL_VERIFY_PEER, NULL); - } - - /* Set the verification depth */ - SSL_CTX_set_verify_depth(ssl_listener->ctx, ssl_listener->ssl_cert_verify_depth); - ssl_listener->ssl_init_done = true; } - return 0; + + SSL_CTX* ctx = SSL_CTX_new(ssl->method); + + if (ctx == NULL) + { + MXS_ERROR("SSL context initialization failed: %s", get_ssl_errors()); + return false; + } + + SSL_CTX_set_default_read_ahead(ctx, 0); + + /** Enable all OpenSSL bug fixes */ + SSL_CTX_set_options(ctx, SSL_OP_ALL); + + /** Disable SSLv3 */ + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); + + // Disable session cache + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + + // + // Note: This is not safe if SSL initialization is done concurrently + // + /** Generate the 512-bit and 1024-bit RSA keys */ + if (rsa_512 == NULL && (rsa_512 = create_rsa(512)) == NULL) + { + MXS_ERROR("512-bit RSA key generation failed."); + rval = false; + } + else if (rsa_1024 == NULL && (rsa_1024 = create_rsa(1024)) == NULL) + { + MXS_ERROR("1024-bit RSA key generation failed."); + rval = false; + } + else + { + ss_dassert(rsa_512 && rsa_1024); + SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback); + } + + ss_dassert(ssl->ssl_ca_cert); + + /* Load the CA certificate into the SSL_CTX structure */ + if (!SSL_CTX_load_verify_locations(ctx, ssl->ssl_ca_cert, NULL)) + { + MXS_ERROR("Failed to set Certificate Authority file"); + rval = false; + } + + if (ssl->ssl_cert && ssl->ssl_key) + { + /** Load the server certificate */ + if (SSL_CTX_use_certificate_chain_file(ctx, ssl->ssl_cert) <= 0) + { + MXS_ERROR("Failed to set server SSL certificate: %s", get_ssl_errors()); + rval = false; + } + + /* Load the private-key corresponding to the server certificate */ + if (SSL_CTX_use_PrivateKey_file(ctx, ssl->ssl_key, SSL_FILETYPE_PEM) <= 0) + { + MXS_ERROR("Failed to set server SSL key: %s", get_ssl_errors()); + rval = false; + } + + /* Check if the server certificate and private-key matches */ + if (!SSL_CTX_check_private_key(ctx)) + { + MXS_ERROR("Server SSL certificate and key do not match: %s", get_ssl_errors()); + rval = false; + } + } + + /* Set to require peer (client) certificate verification */ + if (ssl->ssl_verify_peer_certificate) + { + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + } + + /* Set the verification depth */ + SSL_CTX_set_verify_depth(ctx, ssl->ssl_cert_verify_depth); + + if (rval) + { + ssl->ssl_init_done = true; + ssl->ctx = ctx; + } + else + { + SSL_CTX_free(ctx); + } + + return rval; +} + +void SSL_LISTENER_free(SSL_LISTENER* ssl) +{ + if (ssl) + { + SSL_CTX_free(ssl->ctx); + MXS_FREE(ssl->ssl_ca_cert); + MXS_FREE(ssl->ssl_cert); + MXS_FREE(ssl->ssl_key); + MXS_FREE(ssl); + } } /** diff --git a/server/core/service.cc b/server/core/service.cc index 8aec2faec..6eb655f70 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -245,11 +245,6 @@ serviceStartPort(SERVICE *service, SERV_LISTENER *port) port->listener->service = service; - if (port->ssl) - { - listener_init_SSL(port->ssl); - } - if ((funcs = (MXS_PROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL) { MXS_ERROR("Unable to load protocol module %s. Listener for service %s not started.", diff --git a/server/modules/routing/binlogrouter/blr.cc b/server/modules/routing/binlogrouter/blr.cc index 875404fd9..2d5c9a8f7 100644 --- a/server/modules/routing/binlogrouter/blr.cc +++ b/server/modules/routing/binlogrouter/blr.cc @@ -778,6 +778,7 @@ static MXS_ROUTER* createInstance(SERVICE *service, MXS_CONFIG_PARAMETER* params return NULL; } + SSL_LISTENER *ssl_cfg; /* Allocate SSL struct for backend connection */ if ((ssl_cfg = static_cast(MXS_CALLOC(1, sizeof(SSL_LISTENER)))) == NULL) @@ -873,27 +874,6 @@ static MXS_ROUTER* createInstance(SERVICE *service, MXS_CONFIG_PARAMETER* params if (inst->ssl_enabled) { - if (service->dbref && - service->dbref->server && - service->dbref->server->server_ssl) - { - /* Initialise SSL: exit on error */ - if (listener_init_SSL(service->dbref->server->server_ssl) != 0) - { - MXS_ERROR("%s: Unable to initialize SSL with backend server", - service->name); - /* Free SSL struct */ - /* Note: SSL struct in server should be freed by server_free() */ - blr_free_ssl_data(inst); - - server_free(service->dbref->server); - MXS_FREE(service->dbref); - service->dbref = NULL; - sqlite3_close_v2(inst->gtid_maps); - free_instance(inst); - return NULL; - } - } MXS_INFO("%s: Replicating from master with SSL", service->name); } else diff --git a/server/modules/routing/binlogrouter/blr_slave.cc b/server/modules/routing/binlogrouter/blr_slave.cc index cdba68466..2b5cf278b 100644 --- a/server/modules/routing/binlogrouter/blr_slave.cc +++ b/server/modules/routing/binlogrouter/blr_slave.cc @@ -4043,28 +4043,6 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) } } - /** Initialise SSL: exit on error */ - if (router->ssl_enabled && router->service->dbref->server->server_ssl) - { - if (listener_init_SSL(router->service->dbref->server->server_ssl) != 0) - { - MXS_ERROR("%s: Unable to initialise SSL with backend server", - router->service->name); - - blr_slave_send_error_packet(slave, - "Unable to initialise SSL with backend server", - 1210, - "HY000"); - spinlock_acquire(&router->lock); - - router->master_state = BLRM_SLAVE_STOPPED; - - spinlock_release(&router->lock); - - return 1; - } - } - /** Start replication from master */ blr_start_master_in_main(router);