From 63ae436bd576c1d327ec9934ead574ed6901ebac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 14 Nov 2017 13:21:40 +0200 Subject: [PATCH] MXS-1019: Make peer certificate verification configurable The new `ssl_verify_peer_certificate` parameter controls whether the peer certificate is verified. This allows self-signed certificates to be properly used with MaxScale. --- include/maxscale/ssl.h | 2 + server/core/config.c | 23 +++++-- server/core/listener.c | 54 +--------------- server/core/server.c | 53 +--------------- server/core/ssl.c | 61 +++++++++++++++++++ server/modules/routing/binlogrouter/blr.c | 1 + .../modules/routing/binlogrouter/blr_slave.c | 1 + 7 files changed, 87 insertions(+), 108 deletions(-) diff --git a/include/maxscale/ssl.h b/include/maxscale/ssl.h index f1d761982..8f61e6db0 100644 --- a/include/maxscale/ssl.h +++ b/include/maxscale/ssl.h @@ -65,6 +65,7 @@ typedef struct ssl_listener char *ssl_key; /*< SSL private key */ char *ssl_ca_cert; /*< SSL CA certificate */ bool ssl_init_done; /*< If SSL has already been initialized for this service */ + bool ssl_verify_peer_certificate; /*< Enable peer certificate verification */ struct ssl_listener *next; /*< Next SSL configuration, currently used to store obsolete configurations */ } SSL_LISTENER; @@ -75,5 +76,6 @@ bool ssl_check_data_to_process(struct dcb *dcb); bool ssl_required_by_dcb(struct dcb *dcb); bool ssl_required_but_not_negotiated(struct dcb *dcb); const char* ssl_method_type_to_string(ssl_method_type_t method_type); +void write_ssl_config(int fd, SSL_LISTENER* ssl); MXS_END_DECLS diff --git a/server/core/config.c b/server/core/config.c index 34f4bb97d..083a0ed3c 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -154,6 +154,7 @@ static const char *listener_params[] = "ssl_key", "ssl_version", "ssl_cert_verify_depth", + "ssl_verify_peer_certificate", NULL }; @@ -199,6 +200,7 @@ static const char *server_params[] = "ssl_key", "ssl_version", "ssl_cert_verify_depth", + "ssl_verify_peer_certificate", NULL }; @@ -1466,8 +1468,11 @@ SSL_LISTENER* make_ssl_structure (CONFIG_CONTEXT *obj, bool require_cert, int *e ssl_key = config_get_value(obj->parameters, "ssl_key"); ssl_ca_cert = config_get_value(obj->parameters, "ssl_ca_cert"); ssl_version = config_get_value(obj->parameters, "ssl_version"); + char* ssl_verify_peer_certificate = config_get_value(obj->parameters, "ssl_verify_peer_certificate"); ssl_cert_verify_depth = config_get_value(obj->parameters, "ssl_cert_verify_depth"); 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) { @@ -1490,12 +1495,20 @@ SSL_LISTENER* make_ssl_structure (CONFIG_CONTEXT *obj, bool require_cert, int *e local_errors++; } } - else + + if (ssl_verify_peer_certificate) { - /** - * Default of 9 as per Linux man page - */ - new_ssl->ssl_cert_verify_depth = 9; + int rv = config_truth_value(ssl_verify_peer_certificate); + if (rv == -1) + { + MXS_ERROR("Invalid parameter value for 'ssl_verify_peer_certificate" + " for service '%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); diff --git a/server/core/listener.c b/server/core/listener.c index 8d2adc1ad..9a067fe07 100644 --- a/server/core/listener.c +++ b/server/core/listener.c @@ -337,7 +337,7 @@ listener_init_SSL(SSL_LISTENER *ssl_listener) } /* Set to require peer (client) certificate verification */ - if (ssl_listener->ssl_cert_verify_depth) + if (ssl_listener->ssl_verify_peer_certificate) { SSL_CTX_set_verify(ssl_listener->ctx, SSL_VERIFY_PEER, NULL); } @@ -430,57 +430,7 @@ static bool create_listener_config(const SERV_LISTENER *listener, const char *fi if (listener->ssl) { - dprintf(file, "ssl=required\n"); - - if (listener->ssl->ssl_cert) - { - dprintf(file, "ssl_cert=%s\n", listener->ssl->ssl_cert); - } - - if (listener->ssl->ssl_key) - { - dprintf(file, "ssl_key=%s\n", listener->ssl->ssl_key); - } - - if (listener->ssl->ssl_ca_cert) - { - dprintf(file, "ssl_ca_cert=%s\n", listener->ssl->ssl_ca_cert); - } - if (listener->ssl->ssl_cert_verify_depth) - { - dprintf(file, "ssl_cert_verify_depth=%d\n", listener->ssl->ssl_cert_verify_depth); - } - - const char *version = NULL; - - switch (listener->ssl->ssl_method_type) - { -#ifndef OPENSSL_1_1 - case SERVICE_TLS10: - version = "TLSV10"; - break; -#endif -#ifdef OPENSSL_1_0 - case SERVICE_TLS11: - version = "TLSV11"; - break; - - case SERVICE_TLS12: - version = "TLSV12"; - break; -#endif - case SERVICE_SSL_TLS_MAX: - version = "MAX"; - break; - - default: - break; - } - - if (version) - { - dprintf(file, "ssl_version=%s\n", version); - } + write_ssl_config(file, listener->ssl); } close(file); diff --git a/server/core/server.c b/server/core/server.c index 0a5b434e2..744e0d931 100644 --- a/server/core/server.c +++ b/server/core/server.c @@ -577,6 +577,7 @@ dprintServer(DCB *dcb, const SERVER *server) dcb_printf(dcb, "\tSSL method type: %s\n", ssl_method_type_to_string(l->ssl_method_type)); dcb_printf(dcb, "\tSSL certificate verification depth: %d\n", l->ssl_cert_verify_depth); + dcb_printf(dcb, "\tSSL peer verification : %s\n", l->ssl_verify_peer_certificate ? "true" : "false"); dcb_printf(dcb, "\tSSL certificate: %s\n", l->ssl_cert ? l->ssl_cert : "null"); dcb_printf(dcb, "\tSSL key: %s\n", @@ -1167,57 +1168,7 @@ static bool create_server_config(const SERVER *server, const char *filename) if (server->server_ssl) { - dprintf(file, "ssl=required\n"); - - if (server->server_ssl->ssl_cert) - { - dprintf(file, "ssl_cert=%s\n", server->server_ssl->ssl_cert); - } - - if (server->server_ssl->ssl_key) - { - dprintf(file, "ssl_key=%s\n", server->server_ssl->ssl_key); - } - - if (server->server_ssl->ssl_ca_cert) - { - dprintf(file, "ssl_ca_cert=%s\n", server->server_ssl->ssl_ca_cert); - } - if (server->server_ssl->ssl_cert_verify_depth) - { - dprintf(file, "ssl_cert_verify_depth=%d\n", server->server_ssl->ssl_cert_verify_depth); - } - - const char *version = NULL; - - switch (server->server_ssl->ssl_method_type) - { -#ifndef OPENSSL_1_1 - case SERVICE_TLS10: - version = "TLSV10"; - break; -#endif -#ifdef OPENSSL_1_0 - case SERVICE_TLS11: - version = "TLSV11"; - break; - - case SERVICE_TLS12: - version = "TLSV12"; - break; -#endif - case SERVICE_SSL_TLS_MAX: - version = "MAX"; - break; - - default: - break; - } - - if (version) - { - dprintf(file, "ssl_version=%s\n", version); - } + write_ssl_config(file, server->server_ssl); } close(file); diff --git a/server/core/ssl.c b/server/core/ssl.c index 02c1f7385..32ee7c340 100644 --- a/server/core/ssl.c +++ b/server/core/ssl.c @@ -214,3 +214,64 @@ const char* ssl_method_type_to_string(ssl_method_type_t method_type) return "Unknown"; } } + +void write_ssl_config(int fd, SSL_LISTENER* ssl) +{ + if (ssl) + { + dprintf(fd, "ssl=required\n"); + + if (ssl->ssl_cert) + { + dprintf(fd, "ssl_cert=%s\n", ssl->ssl_cert); + } + + if (ssl->ssl_key) + { + dprintf(fd, "ssl_key=%s\n", ssl->ssl_key); + } + + if (ssl->ssl_ca_cert) + { + dprintf(fd, "ssl_ca_cert=%s\n", ssl->ssl_ca_cert); + } + if (ssl->ssl_cert_verify_depth) + { + dprintf(fd, "ssl_cert_verify_depth=%d\n", ssl->ssl_cert_verify_depth); + } + + dprintf(fd, "ssl_verify_peer_certificate=%s\n", + ssl->ssl_verify_peer_certificate ? "true" : "false"); + + const char *version = NULL; + + switch (ssl->ssl_method_type) + { +#ifndef OPENSSL_1_1 + case SERVICE_TLS10: + version = "TLSV10"; + break; +#endif +#ifdef OPENSSL_1_0 + case SERVICE_TLS11: + version = "TLSV11"; + break; + + case SERVICE_TLS12: + version = "TLSV12"; + break; +#endif + case SERVICE_SSL_TLS_MAX: + version = "MAX"; + break; + + default: + break; + } + + if (version) + { + dprintf(fd, "ssl_version=%s\n", version); + } + } +} \ No newline at end of file diff --git a/server/modules/routing/binlogrouter/blr.c b/server/modules/routing/binlogrouter/blr.c index fb17426c7..e091f188f 100644 --- a/server/modules/routing/binlogrouter/blr.c +++ b/server/modules/routing/binlogrouter/blr.c @@ -712,6 +712,7 @@ createInstance(SERVICE *service, char **options) ssl_cfg->ssl_init_done = false; ssl_cfg->ssl_method_type = SERVICE_SSL_TLS_MAX; ssl_cfg->ssl_cert_verify_depth = 9; + ssl_cfg->ssl_verify_peer_certificate = true; /** Set SSL pointer in in server struct */ server->server_ssl = ssl_cfg; diff --git a/server/modules/routing/binlogrouter/blr_slave.c b/server/modules/routing/binlogrouter/blr_slave.c index 1eb6571bc..de009b213 100644 --- a/server/modules/routing/binlogrouter/blr_slave.c +++ b/server/modules/routing/binlogrouter/blr_slave.c @@ -5766,6 +5766,7 @@ blr_set_master_ssl(ROUTER_INSTANCE *router, CHANGE_MASTER_OPTIONS config, char * server_ssl->ssl_init_done = false; server_ssl->ssl_method_type = SERVICE_SSL_TLS_MAX; server_ssl->ssl_cert_verify_depth = 9; + server_ssl->ssl_verify_peer_certificate = true; /* Set the pointer */ router->service->dbref->server->server_ssl = server_ssl;