diff --git a/include/maxscale/config.h b/include/maxscale/config.h index f2daf3801..fe236f28b 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -64,6 +64,7 @@ MXS_BEGIN_DECLS #define MXS_JSON_PTR_PARAM_SSL_CA_CERT MXS_JSON_PTR_PARAMETERS "/ssl_ca_cert" #define MXS_JSON_PTR_PARAM_SSL_VERSION MXS_JSON_PTR_PARAMETERS "/ssl_version" #define MXS_JSON_PTR_PARAM_SSL_CERT_VERIFY_DEPTH MXS_JSON_PTR_PARAMETERS "/ssl_cert_verify_depth" +#define MXS_JSON_PTR_PARAM_SSL_VERIFY_PEER_CERT MXS_JSON_PTR_PARAMETERS "/ssl_verify_peer_certificate" /** Non-parameter JSON pointers */ #define MXS_JSON_PTR_MODULE "/data/attributes/module" diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index b274165de..f852b0f81 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -249,7 +249,8 @@ bool runtime_destroy_server(SERVER *server) } static SSL_LISTENER* create_ssl(const char *name, const char *key, const char *cert, - const char *ca, const char *version, const char *depth) + const char *ca, const char *version, const char *depth, + const char *verify) { SSL_LISTENER *rval = NULL; CONFIG_CONTEXT *obj = config_context_create(name); @@ -261,7 +262,8 @@ static SSL_LISTENER* create_ssl(const char *name, const char *key, const char *c config_add_param(obj, CN_SSL_CERT, cert) && config_add_param(obj, CN_SSL_CA_CERT, ca) && (!version || config_add_param(obj, CN_SSL_VERSION, version)) && - (!depth || config_add_param(obj, CN_SSL_CERT_VERIFY_DEPTH, depth))) + (!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); @@ -279,14 +281,15 @@ static SSL_LISTENER* create_ssl(const char *name, const char *key, const char *c } bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert, - const char *ca, const char *version, const char *depth) + const char *ca, const char *version, const char *depth, + const char *verify) { bool rval = false; if (key && cert && ca) { spinlock_acquire(&crt_lock); - SSL_LISTENER *ssl = create_ssl(server->unique_name, key, cert, ca, version, depth); + SSL_LISTENER *ssl = create_ssl(server->unique_name, key, cert, ca, version, depth, verify); if (ssl) { @@ -796,7 +799,8 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add const char *port, const char *proto, const char *auth, const char *auth_opt, const char *ssl_key, const char *ssl_cert, const char *ssl_ca, - const char *ssl_version, const char *ssl_depth) + const char *ssl_version, const char *ssl_depth, + const char *verify_ssl) { if (addr == NULL || strcasecmp(addr, CN_DEFAULT) == 0) @@ -834,7 +838,7 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add SSL_LISTENER *ssl = NULL; if (ssl_key && ssl_cert && ssl_ca && - (ssl = create_ssl(name, ssl_key, ssl_cert, ssl_ca, ssl_version, ssl_depth)) == NULL) + (ssl = create_ssl(name, ssl_key, ssl_cert, ssl_ca, ssl_version, ssl_depth, verify_ssl)) == NULL) { MXS_ERROR("SSL initialization for listener '%s' failed.", name); runtime_error("SSL initialization for listener '%s' failed.", name); @@ -1271,6 +1275,7 @@ static bool process_ssl_parameters(SERVER* server, json_t* params) if (validate_ssl_json(params)) { char buf[20]; // Enough to hold the string form of the ssl_cert_verify_depth + char buf_verify[20]; // Enough to hold the string form of the ssl_verify_peer_certificate const char* key = json_string_value(mxs_json_pointer(params, CN_SSL_KEY)); const char* cert = json_string_value(mxs_json_pointer(params, CN_SSL_CERT)); const char* ca = json_string_value(mxs_json_pointer(params, CN_SSL_CA_CERT)); @@ -1284,7 +1289,16 @@ static bool process_ssl_parameters(SERVER* server, json_t* params) depth = buf; } - if (!runtime_enable_server_ssl(server, key, cert, ca, version, depth)) + const char* verify = NULL; + json_t* verify_json = mxs_json_pointer(params, CN_SSL_VERIFY_PEER_CERTIFICATE); + + if (verify_json) + { + snprintf(buf_verify, sizeof(buf), "%s", json_boolean_value(verify_json) ? "true" : "false"); + verify = buf_verify; + } + + if (!runtime_enable_server_ssl(server, key, cert, ca, version, depth, verify)) { runtime_error("Failed to initialize SSL for server '%s'. See " "error log for more details.", server->unique_name); @@ -1962,11 +1976,12 @@ bool runtime_create_listener_from_json(SERVICE* service, json_t* json) const char* ssl_ca_cert = get_string_or_null(json, MXS_JSON_PTR_PARAM_SSL_CA_CERT); const char* ssl_version = get_string_or_null(json, MXS_JSON_PTR_PARAM_SSL_VERSION); const char* ssl_cert_verify_depth = get_string_or_null(json, MXS_JSON_PTR_PARAM_SSL_CERT_VERIFY_DEPTH); + const char* ssl_verify_peer_certificate = get_string_or_null(json, MXS_JSON_PTR_PARAM_SSL_VERIFY_PEER_CERT); rval = runtime_create_listener(service, id, address, port.c_str(), protocol, authenticator, authenticator_options, ssl_key, ssl_cert, ssl_ca_cert, ssl_version, - ssl_cert_verify_depth); + ssl_cert_verify_depth, ssl_verify_peer_certificate); } return rval; diff --git a/server/core/internal/config_runtime.h b/server/core/internal/config_runtime.h index 60297f8c6..ed0ed489a 100644 --- a/server/core/internal/config_runtime.h +++ b/server/core/internal/config_runtime.h @@ -106,10 +106,13 @@ bool runtime_alter_server(SERVER *server, const char *key, const char *value); * @param ca Path to certificate authority * @param version Required SSL Version * @param depth Certificate verification depth + * @param verify Verify peer certificate + * * @return True if SSL was successfully enabled */ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert, - const char *ca, const char *version, const char *depth); + const char *ca, const char *version, const char *depth, + const char *verify); /** * @brief Alter monitor parameters @@ -159,6 +162,7 @@ bool runtime_alter_maxscale(const char* name, const char* value); * @param ssl_ca SSL CA cert, NULL for no CA cert * @param ssl_version SSL version, NULL for default of "MAX" * @param ssl_depth SSL cert verification depth, NULL for default + * @param verify_ssl SSL peer certificate verification, NULL for default * * @return True if the listener was successfully created and started */ @@ -166,7 +170,8 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add const char *port, const char *proto, const char *auth, const char *auth_opt, const char *ssl_key, const char *ssl_cert, const char *ssl_ca, - const char *ssl_version, const char *ssl_depth); + const char *ssl_version, const char *ssl_depth, + const char *verify_ssl); /** * @brief Destroy a listener diff --git a/server/core/server.cc b/server/core/server.cc index 6dd532503..60fa28e1f 100644 --- a/server/core/server.cc +++ b/server/core/server.cc @@ -1455,6 +1455,8 @@ static json_t* server_json_attributes(const SERVER* server) json_object_set_new(params, CN_SSL_CA_CERT, json_string(server->server_ssl->ssl_ca_cert)); json_object_set_new(params, CN_SSL_CERT_VERIFY_DEPTH, json_integer(server->server_ssl->ssl_cert_verify_depth)); + json_object_set_new(params, CN_SSL_VERIFY_PEER_CERTIFICATE, + json_boolean(server->server_ssl->ssl_verify_peer_certificate)); json_object_set_new(params, CN_SSL_VERSION, json_string(ssl_method_type_to_string(server->server_ssl->ssl_method_type))); } diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 2e8c74cbf..79399ae52 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -64,7 +64,7 @@ #include "../../../core/internal/poll.h" #include "../../../core/internal/session.h" -#define MAXARGS 12 +#define MAXARGS 14 #define ARG_TYPE_NONE 0 #define ARG_TYPE_ADDRESS 1 @@ -1165,11 +1165,11 @@ static void createServer(DCB *dcb, char *name, char *address, char *port, static void createListener(DCB *dcb, SERVICE *service, char *name, char *address, char *port, char *protocol, char *authenticator, char *authenticator_options, char *key, char *cert, - char *ca, char *version, char *depth) + char *ca, char *version, char *depth, char *verify) { if (runtime_create_listener(service, name, address, port, protocol, authenticator, authenticator_options, - key, cert, ca, version, depth)) + key, cert, ca, version, depth, verify)) { dcb_printf(dcb, "Listener '%s' created\n", name); } @@ -1378,6 +1378,7 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, char *ssl_ca = NULL; char *ssl_version = NULL; char *ssl_depth = NULL; + char *ssl_verify = NULL; bool enable = false; for (int i = 0; i < items && values[i]; i++) @@ -1411,6 +1412,10 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, { ssl_depth = value; } + else if (strcmp("ssl_verify_peer_certificate", key) == 0) + { + ssl_verify = value; + } else { enable = strcmp("ssl", key) == 0 && strcmp(value, "required") == 0; @@ -1434,7 +1439,7 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, { /** We have SSL parameters, try to process them */ if (!runtime_enable_server_ssl(server, ssl_key, ssl_cert, ssl_ca, - ssl_version, ssl_depth)) + ssl_version, ssl_depth, ssl_verify)) { dcb_printf(dcb, "Enabling SSL for server '%s' failed, see log " "for more details.\n", server->unique_name); @@ -1536,7 +1541,7 @@ static void alterMaxScale(DCB *dcb, char *v1, char *v2, char *v3, struct subcommand alteroptions[] = { { - "server", 2, 12, alterServer, + "server", 2, 14, alterServer, "Alter server parameters", "Usage: alter server NAME KEY=VALUE ...\n" "\n" @@ -1546,18 +1551,19 @@ struct subcommand alteroptions[] = "\n" "This will alter an existing parameter of a server. The accepted values for KEY are:\n" "\n" - "address Server address\n" - "port Server port\n" - "monitoruser Monitor user for this server\n" - "monitorpw Monitor password for this server\n" - "ssl Enable SSL, value must be 'required'\n" - "ssl_key Path to SSL private key\n" - "ssl_cert Path to SSL certificate\n" - "ssl_ca_cert Path to SSL CA certificate\n" - "ssl_version SSL version\n" - "ssl_cert_verify_depth Certificate verification depth\n" - "persistpoolmax Persisted connection pool size\n" - "persistmaxtime Persisted connection maximum idle time\n" + "address Server address\n" + "port Server port\n" + "monitoruser Monitor user for this server\n" + "monitorpw Monitor password for this server\n" + "ssl Enable SSL, value must be 'required'\n" + "ssl_key Path to SSL private key\n" + "ssl_cert Path to SSL certificate\n" + "ssl_ca_cert Path to SSL CA certificate\n" + "ssl_version SSL version\n" + "ssl_cert_verify_depth Certificate verification depth\n" + "ssl_verify_peer_certificate Peer certificate verification\n" + "persistpoolmax Persisted connection pool size\n" + "persistmaxtime Persisted connection maximum idle time\n" "\n" "To configure SSL for a newly created server, the 'ssl', 'ssl_cert',\n" "'ssl_key' and 'ssl_ca_cert' parameters must be given at the same time.\n"