From 060b1eadf4913f7066484ea34ec62feead1bca44 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 10 Mar 2017 01:19:50 +0400 Subject: [PATCH 1/3] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS CREDENTIALS BEFORE VERIFYING SSL CONNECTION MYSQL_OPT_SSL_MODE option introduced. It is set in case of --ssl-mode=REQUIRED and permits only SSL connection. (cherry picked from commit 3b2d28578c526f347f5cfe763681eff365731f99) --- client/client_priv.h | 34 +++++++++++++----- client/mysql.cc | 6 ++-- client/mysql_upgrade.c | 6 ++-- client/mysqladmin.cc | 6 ++-- client/mysqlcheck.c | 4 +-- client/mysqldump.c | 4 +-- client/mysqlimport.c | 4 +-- client/mysqlshow.c | 4 +-- client/mysqlslap.c | 5 +-- client/mysqltest.cc | 6 ++-- include/mysql.h | 9 +++-- include/mysql.h.pp | 6 +++- include/sql_common.h | 3 +- include/sslopt-case.h | 4 +-- include/sslopt-vars.h | 6 ++-- mysql-test/r/ssl_mode.result | 6 ++-- mysql-test/r/ssl_mode_no_ssl.result | 22 ++++++------ sql-common/client.c | 54 +++++++++++++++++++++++++++-- 18 files changed, 134 insertions(+), 55 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index e53ced7e790..fb83ce9cc8b 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,13 +115,15 @@ enum options_client /** Wrapper for mysql_real_connect() that checks if SSL connection is establised. - The function calls mysql_real_connect() first, then if given ssl_required==TRUE - argument (i.e. --ssl-mode=REQUIRED option used) checks current SSL chiper to - ensure that SSL is used for current connection. - Otherwise it returns NULL and sets errno to CR_SSL_CONNECTION_ERROR. + The function calls mysql_real_connect() first. Then, if the ssl_required + argument is TRUE (i.e., the --ssl-mode=REQUIRED option was specified), it + checks the current SSL cipher to ensure that SSL is used for the current + connection. Otherwise, it returns NULL and sets errno to + CR_SSL_CONNECTION_ERROR. - All clients (except mysqlbinlog which disregards SSL options) use this function - instead of mysql_real_connect() to handle --ssl-mode=REQUIRED option. + All clients (except mysqlbinlog, which disregards SSL options) use this + function instead of mysql_real_connect() to handle the --ssl-mode=REQUIRED + option. */ MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host, const char *user, const char *passwd, @@ -129,8 +131,22 @@ MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host, const char *unix_socket, ulong client_flag, my_bool ssl_required __attribute__((unused))) { - MYSQL *mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port, - unix_socket, client_flag); + MYSQL *mysql; + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + enum mysql_ssl_mode opt_ssl_mode= SSL_MODE_REQUIRED; + if (ssl_required && + mysql_options(mysql_arg, MYSQL_OPT_SSL_MODE, (char *) &opt_ssl_mode)) + { + NET *net= &mysql_arg->net; + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error, "Client library doesn't support MYSQL_SSL_REQUIRED option"); + strmov(net->sqlstate, "HY000"); + return NULL; + } +#endif + mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port, + unix_socket, client_flag); #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (mysql && /* connection established. */ ssl_required && /* --ssl-mode=REQUIRED. */ diff --git a/client/mysql.cc b/client/mysql.cc index cdc2ab0d6e0..2269563814c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1318,7 +1318,7 @@ sig_handler handle_sigint(int sig) kill_mysql= mysql_init(kill_mysql); if (!mysql_connect_ssl_check(kill_mysql, current_host, current_user, opt_password, "", opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; @@ -4461,7 +4461,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, if (!mysql_connect_ssl_check(&mysql, host, user, password, database, opt_mysql_port, opt_mysql_unix_port, connect_flag | CLIENT_MULTI_STATEMENTS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 507df6f7843..be0af089027 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -387,9 +387,11 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) va_end(args); +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) /* If given --ssl-mode=REQUIRED propagate it to the tool. */ - if (opt_ssl_required) + if (opt_ssl_mode == SSL_MODE_REQUIRED) dynstr_append(&ds_cmdline, "--ssl-mode=REQUIRED"); +#endif #ifdef __WIN__ dynstr_append(&ds_cmdline, "\""); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index c03b37ab165..ae9db85b917 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -519,8 +519,8 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) for (;;) { if (mysql_connect_ssl_check(mysql, host, user, opt_password, NullS, - tcp_port, unix_port, - CLIENT_REMEMBER_OPTIONS, opt_ssl_required)) + tcp_port, unix_port, CLIENT_REMEMBER_OPTIONS, + opt_ssl_mode == SSL_MODE_REQUIRED)) { mysql->reconnect= 1; if (info) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 55b941e7f1a..7822460e341 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -907,7 +907,7 @@ static int dbConnect(char *host, char *user, char *passwd) if (!(sock = mysql_connect_ssl_check(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required))) + opt_ssl_mode == SSL_MODE_REQUIRED))) { DBerror(&mysql_connection, "when trying to connect"); return 1; diff --git a/client/mysqldump.c b/client/mysqldump.c index 00265def489..fcd29e26fe3 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1501,7 +1501,7 @@ static int connect_to_db(char *host, char *user,char *passwd) if (!(mysql= mysql_connect_ssl_check(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required))) + opt_ssl_mode == SSL_MODE_REQUIRED))) { DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 5841c0b855a..bab43356bc7 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -463,7 +463,7 @@ static MYSQL *db_connect(char *host, char *database, mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (!(mysql_connect_ssl_check(mysql, host, user, passwd, database, opt_mysql_port, opt_mysql_unix_port, - 0, opt_ssl_required))) + 0, opt_ssl_mode == SSL_MODE_REQUIRED))) { ignore_errors=0; /* NO RETURN FROM db_error */ db_error(mysql); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index d0390ec443b..bd7a37f93b4 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -142,7 +142,7 @@ int main(int argc, char **argv) if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, (first_argument_uses_wildcards) ? "" : argv[0], opt_mysql_port, opt_mysql_unix_port, - 0, opt_ssl_required))) + 0, opt_ssl_mode == SSL_MODE_REQUIRED))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); exit(1); diff --git a/client/mysqlslap.c b/client/mysqlslap.c index eb2b577948c..aa312339e87 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -357,7 +357,8 @@ int main(int argc, char **argv) { if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, NULL, opt_mysql_port, opt_mysql_unix_port, - connect_flags, opt_ssl_required))) + connect_flags, + opt_ssl_mode == SSL_MODE_REQUIRED))) { fprintf(stderr,"%s: Error when connecting to server: %s\n", my_progname,mysql_error(&mysql)); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 79d448cf811..e5f9b11fe76 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5283,7 +5283,7 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, host, port, sock, user, name, failed_attempts); while(!mysql_connect_ssl_check(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { /* Connect failed @@ -5385,7 +5385,7 @@ int connect_n_handle_errors(struct st_command *command, while (!mysql_connect_ssl_check(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { /* If we have used up all our connections check whether this diff --git a/include/mysql.h b/include/mysql.h index da29cb342cc..7ebf2f725a2 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -167,7 +167,7 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN + MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE }; /** @@ -224,6 +224,11 @@ enum mysql_protocol_type MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY }; +enum mysql_ssl_mode +{ + SSL_MODE_REQUIRED= 3 +}; + typedef struct character_set { unsigned int number; /* character set number */ diff --git a/include/mysql.h.pp b/include/mysql.h.pp index c2c5ba35044..0f292d921ee 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -263,7 +263,7 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN + MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE }; struct st_mysql_options_extention; struct st_mysql_options { @@ -307,6 +307,10 @@ enum mysql_protocol_type MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY }; +enum mysql_ssl_mode +{ + SSL_MODE_REQUIRED= 3 +}; typedef struct character_set { unsigned int number; diff --git a/include/sql_common.h b/include/sql_common.h index a2ea3ac45e7..05bbb5a4f53 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -1,7 +1,7 @@ #ifndef SQL_COMMON_INCLUDED #define SQL_COMMON_INCLUDED -/* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ struct st_mysql_options_extention { char *plugin_dir; char *default_auth; my_bool enable_cleartext_plugin; + unsigned int ssl_mode; }; typedef struct st_mysql_methods diff --git a/include/sslopt-case.h b/include/sslopt-case.h index 57702b3b352..0fddafc4fa9 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_CASE_INCLUDED #define SSLOPT_CASE_INCLUDED -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ exit(1); } else - opt_ssl_required= 1; + opt_ssl_mode= SSL_MODE_REQUIRED; break; #endif /* MYSQL_CLIENT */ #endif diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 6c9bd4296ef..a037538f693 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_VARS_INCLUDED #define SSLOPT_VARS_INCLUDED -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,11 +31,11 @@ SSL_STATIC char *opt_ssl_key = 0; #ifdef MYSQL_CLIENT SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; -SSL_STATIC my_bool opt_ssl_required= 0; +SSL_STATIC uint opt_ssl_mode= 0; #endif /* MYSQL_CLIENT */ #else /* HAVE_OPENSSL */ -#define opt_ssl_required 0 +#define opt_ssl_mode 0 #endif /* HAVE_OPENSSL */ #endif /* SSLOPT_VARS_INCLUDED */ diff --git a/mysql-test/r/ssl_mode.result b/mysql-test/r/ssl_mode.result index 38fc4e1dca2..c02a50bdcbd 100644 --- a/mysql-test/r/ssl_mode.result +++ b/mysql-test/r/ssl_mode.result @@ -37,8 +37,8 @@ DROP TABLE t1; # mysql Unknown value to --ssl-mode: ''. Use --ssl-mode=REQUIRED Unknown value to --ssl-mode: 'DERIUQER'. Use --ssl-mode=REQUIRED -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL End of tests diff --git a/mysql-test/r/ssl_mode_no_ssl.result b/mysql-test/r/ssl_mode_no_ssl.result index 409b7a0fa1b..831bb3b71ab 100644 --- a/mysql-test/r/ssl_mode_no_ssl.result +++ b/mysql-test/r/ssl_mode_no_ssl.result @@ -1,22 +1,22 @@ # negative client tests # mysql -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL # mysqldump -mysqldump: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +mysqldump: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect # mysqladmin -mysqladmin: error: '--ssl-mode=REQUIRED option forbids non SSL connections' +mysqladmin: error: 'SSL connection error: Server doesn't support SSL' # mysqlcheck -mysqlcheck: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +mysqlcheck: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect # mysqlimport -mysqlimport: Error: 2026 --ssl-mode=REQUIRED option forbids non SSL connections +mysqlimport: Error: 2026 SSL connection error: Server doesn't support SSL # mysqlshow -mysqlshow: --ssl-mode=REQUIRED option forbids non SSL connections +mysqlshow: SSL connection error: Server doesn't support SSL # mysqlslap -mysqlslap: Error when connecting to server: --ssl-mode=REQUIRED option forbids non SSL connections +mysqlslap: Error when connecting to server: SSL connection error: Server doesn't support SSL # mysqltest -mysqltest: Could not open connection 'default': 2026 --ssl-mode=REQUIRED option forbids non SSL connections +mysqltest: Could not open connection 'default': 2026 SSL connection error: Server doesn't support SSL End of tests diff --git a/sql-common/client.c b/sql-common/client.c index 3a6e205d384..759d95117cb 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1137,7 +1137,7 @@ static const char *default_options[]= "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "multi-results", "multi-statements", "multi-queries", "secure-auth", "report-data-truncation", "plugin-dir", "default-auth", - "enable-cleartext-plugin", + "enable-cleartext-plugin", "ssl-mode", NullS }; enum option_id { @@ -1149,7 +1149,7 @@ enum option_id { OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name, OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth, OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, - OPT_enable_cleartext_plugin, + OPT_enable_cleartext_plugin, OPT_ssl_mode, OPT_keep_this_one_last }; @@ -1338,12 +1338,26 @@ void mysql_read_default_options(struct st_mysql_options *options, my_free(options->ssl_cipher); options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME)); break; + case OPT_ssl_mode: + if (opt_arg && + !my_strcasecmp(&my_charset_latin1, opt_arg, "required")) + { + ENSURE_EXTENSIONS_PRESENT(options); + options->extension->ssl_mode= SSL_MODE_REQUIRED; + } + else + { + fprintf(stderr, "Unknown option to ssl-mode: %s\n", opt_arg); + exit(1); + } + break; #else case OPT_ssl_key: case OPT_ssl_cert: case OPT_ssl_ca: case OPT_ssl_capath: case OPT_ssl_cipher: + case OPT_ssl_mode: break; #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ case OPT_character_sets_dir: @@ -1850,6 +1864,10 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) mysql->options.ssl_capath = 0; mysql->options.ssl_cipher= 0; mysql->options.use_ssl = FALSE; + if (mysql->options.extension) + { + mysql->options.extension->ssl_mode= 0; + } mysql->connector_fd = 0; DBUG_VOID_RETURN; } @@ -2596,6 +2614,31 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, end= buff+5; } #ifdef HAVE_OPENSSL + /* + If SSL connection is required we'll: + 1. check if the server supports SSL; + 2. check if the client is properly configured; + 3. try to use SSL no matter the other options given. + */ + if (mysql->options.extension && + mysql->options.extension->ssl_mode == SSL_MODE_REQUIRED) + { + if (!(mysql->server_capabilities & CLIENT_SSL)) + { + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + "Server doesn't support SSL"); + goto error; + } + if (!mysql->options.use_ssl) + { + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + "Client is not configured to use SSL"); + goto error; + } + mysql->client_flag|= CLIENT_SSL; + } if (mysql->client_flag & CLIENT_SSL) { /* Do the SSL layering. */ @@ -4242,6 +4285,13 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql->options.extension->enable_cleartext_plugin= (*(my_bool*) arg) ? TRUE : FALSE; break; + case MYSQL_OPT_SSL_MODE: + if (*(uint *) arg == SSL_MODE_REQUIRED) + { + ENSURE_EXTENSIONS_PRESENT(&mysql->options); + mysql->options.extension->ssl_mode= SSL_MODE_REQUIRED; + } + break; default: DBUG_RETURN(1); } From 87e37ee06b32dda19f8c17a888586dd03191eeec Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Mon, 13 Mar 2017 17:01:59 +0400 Subject: [PATCH 2/3] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS CREDENTIALS BEFORE VERIFYING SSL CONNECTION Changed MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility). (cherry picked from commit 47bb4eb5df1629b5d5e30aebfa9d7a6d74388a5d) --- include/mysql.h | 4 +++- include/mysql.h.pp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 7ebf2f725a2..3a27ab4128c 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -167,7 +167,9 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + /* Set MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility). */ + MYSQL_OPT_SSL_MODE= 38 }; /** diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 0f292d921ee..774bf2d0301 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -263,7 +263,8 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + MYSQL_OPT_SSL_MODE= 38 }; struct st_mysql_options_extention; struct st_mysql_options { From 6fa5e0814662d691be1a29bf88332348ec7c50c9 Mon Sep 17 00:00:00 2001 From: Bharathy Satish Date: Fri, 17 Mar 2017 08:41:31 +0100 Subject: [PATCH 3/3] Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY While writing comments if database object names has a new line character, then next line is considered a command, rather than a comment. This patch fixes the way comments are constructed in mysqldump. (cherry picked from commit 1099f9d17b1c697c2760f86556f5bae7d202b444) --- client/mysqldump.c | 54 +++++++++++++++++++++++------- mysql-test/r/mysqldump.result | 63 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 50 +++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 12 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index fcd29e26fe3..2775769fe52 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -549,6 +549,7 @@ static int dump_tablespaces_for_databases(char** databases); static int dump_tablespaces(char* ts_where); static void print_comment(FILE *sql_file, my_bool is_error, const char *format, ...); +static const char* fix_identifier_with_newline(char*); /* @@ -649,7 +650,7 @@ static void write_header(FILE *sql_file, char *db_name) MACHINE_TYPE); print_comment(sql_file, 0, "-- Host: %s Database: %s\n", current_host ? current_host : "localhost", - db_name ? db_name : ""); + db_name ? fix_identifier_with_newline(db_name) : ""); print_comment(sql_file, 0, "-- ------------------------------------------------------\n" ); @@ -1981,6 +1982,30 @@ static void print_comment(FILE *sql_file, my_bool is_error, const char *format, print_xml_comment(sql_file, strlen(comment_buff), comment_buff); } +/* + This function accepts object names and prefixes -- wherever \n + character is found. + + @param[in] object_name + + @return + @retval fixed object name. +*/ + +static const char* fix_identifier_with_newline(char* object_name) +{ + static char buff[COMMENT_LENGTH]= {0}; + char *ptr= buff; + memset(buff, 0, 255); + while(*object_name) + { + *ptr++ = *object_name; + if (*object_name == '\n') + ptr= strmov(ptr, "-- "); + object_name++; + } + return buff; +} /* create_delimiter @@ -2049,7 +2074,8 @@ static uint dump_events_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, - "\n--\n-- Dumping events for database '%s'\n--\n", db); + "\n--\n-- Dumping events for database '%s'\n--\n", + fix_identifier_with_newline(db)); /* not using "mysql_query_with_error_report" because we may have not @@ -2266,7 +2292,8 @@ static uint dump_routines_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, - "\n--\n-- Dumping routines for database '%s'\n--\n", db); + "\n--\n-- Dumping routines for database '%s'\n--\n", + fix_identifier_with_newline(db)); /* not using "mysql_query_with_error_report" because we may have not @@ -2325,7 +2352,7 @@ static uint dump_routines_for_db(char *db) query_buff); print_comment(sql_file, 1, "-- does %s have permissions on mysql.proc?\n\n", - current_user); + fix_identifier_with_newline(current_user)); maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); } else if (strlen(row[2])) @@ -2539,11 +2566,11 @@ static uint get_table_structure(char *table, char *db, char *table_type, if (strcmp (table_type, "VIEW") == 0) /* view */ print_comment(sql_file, 0, "\n--\n-- Temporary table structure for view %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); else print_comment(sql_file, 0, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); if (opt_drop) { @@ -2785,7 +2812,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, print_comment(sql_file, 0, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table); if (!opt_xml) @@ -3490,21 +3517,23 @@ static void dump_table(char *table, char *db) { print_comment(md_result_file, 0, "\n--\n-- Dumping data for table %s\n--\n", - result_table); + fix_identifier_with_newline(result_table)); dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "); dynstr_append_checked(&query_string, result_table); if (where) { - print_comment(md_result_file, 0, "-- WHERE: %s\n", where); + print_comment(md_result_file, 0, "-- WHERE: %s\n", + fix_identifier_with_newline(where)); dynstr_append_checked(&query_string, " WHERE "); dynstr_append_checked(&query_string, where); } if (order_by) { - print_comment(md_result_file, 0, "-- ORDER BY: %s\n", order_by); + print_comment(md_result_file, 0, "-- ORDER BY: %s\n", + fix_identifier_with_newline(order_by)); dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); @@ -4275,7 +4304,8 @@ static int init_dumping(char *database, int init_func(char*)) char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); print_comment(md_result_file, 0, - "\n--\n-- Current Database: %s\n--\n", qdatabase); + "\n--\n-- Current Database: %s\n--\n", + fix_identifier_with_newline(qdatabase)); /* Call the view or table specific function */ init_func(qdatabase); @@ -5281,7 +5311,7 @@ static my_bool get_view_structure(char *table, char* db) print_comment(sql_file, 0, "\n--\n-- Final view structure for view %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); /* Table might not exist if this view was dumped with --tab. */ fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", opt_quoted_table); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index c578f9e8df6..24746a3a51d 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -5283,3 +5283,66 @@ a DROP TABLE t1; DROP TABLE t2; DROP DATABASE db_20772273; +# +# Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY +# +CREATE DATABASE bug25717383; +use bug25717383; +CREATE TABLE `tab +one` (a int); +CREATE VIEW `view +one` as SELECT * FROM `tab +one`; +CREATE PROCEDURE `proc +one`() SELECT * from `tab +one`; +CREATE TEMPORARY TABLE `temp +one` (id INT); +CREATE TRIGGER `trig +one` BEFORE INSERT ON `tab +one` FOR EACH ROW SET NEW.a = 1; +CREATE EVENT `event +one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5; +SHOW TABLES FROM bug25717383; +Tables_in_bug25717383 +tab +one +view +one +SHOW TRIGGERS FROM bug25717383; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +trig +one INSERT tab +one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci +SHOW EVENTS FROM bug25717383; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +bug25717383 event +one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; +ROUTINE_NAME +proc +one +SHOW TABLES FROM bug25717383; +Tables_in_bug25717383 +tab +one +view +one +SHOW TRIGGERS FROM bug25717383; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +trig +one INSERT tab +one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci +SHOW EVENTS FROM bug25717383; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +bug25717383 event +one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; +ROUTINE_NAME +proc +one +DROP DATABASE bug25717383; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 11d766c3293..da958f83c48 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2425,3 +2425,53 @@ SELECT * FROM t2; DROP TABLE t1; DROP TABLE t2; DROP DATABASE db_20772273; + +--echo # +--echo # Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY +--echo # + + +CREATE DATABASE bug25717383; +use bug25717383; + +CREATE TABLE `tab +one` (a int); +CREATE VIEW `view +one` as SELECT * FROM `tab +one`; + +CREATE PROCEDURE `proc +one`() SELECT * from `tab +one`; + +CREATE TEMPORARY TABLE `temp +one` (id INT); + +CREATE TRIGGER `trig +one` BEFORE INSERT ON `tab +one` FOR EACH ROW SET NEW.a = 1; + +CREATE EVENT `event +one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5; + +SHOW TABLES FROM bug25717383; +SHOW TRIGGERS FROM bug25717383; +--replace_column 6 # +SHOW EVENTS FROM bug25717383; + +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; + +--exec $MYSQL_DUMP --triggers --events --routines --add-drop-database --databases bug25717383 > $MYSQLTEST_VARDIR/tmp/bug25717383.sql + +SHOW TABLES FROM bug25717383; +SHOW TRIGGERS FROM bug25717383; +--replace_column 6 # +SHOW EVENTS FROM bug25717383; + +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; + +DROP DATABASE bug25717383;