diff options
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysql.cc | 1 | ||||
-rw-r--r-- | client/mysqladmin.cc | 1 | ||||
-rw-r--r-- | client/mysqlbinlog.cc | 1 | ||||
-rw-r--r-- | client/mysqldump.c | 1 | ||||
-rw-r--r-- | client/mysqlimport.c | 1 | ||||
-rw-r--r-- | client/mysqlshow.c | 1 | ||||
-rw-r--r-- | client/mysqltest.cc | 1 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 2 | ||||
-rw-r--r-- | include/sslopt-longopts.h | 5 | ||||
-rw-r--r-- | include/sslopt-vars.h | 1 | ||||
-rw-r--r-- | include/violite.h | 11 | ||||
-rw-r--r-- | mysql-test/main/mysqld--help.result | 2 | ||||
-rw-r--r-- | mysql-test/main/mysqld--help.test | 2 | ||||
-rw-r--r-- | mysql-test/main/openssl_6975.test | 24 | ||||
-rw-r--r-- | mysql-test/main/tls_version.opt | 1 | ||||
-rw-r--r-- | mysql-test/main/tls_version.result | 14 | ||||
-rw-r--r-- | mysql-test/main/tls_version.test | 24 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/inc/sysvars_server.inc | 2 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result | 12 | ||||
-rw-r--r-- | sql/mysqld.cc | 10 | ||||
-rw-r--r-- | sql/mysqld.h | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 23 | ||||
-rw-r--r-- | vio/viosslfactories.c | 60 |
25 files changed, 189 insertions, 27 deletions
diff --git a/client/client_priv.h b/client/client_priv.h index 5b6b31ccda9..3ad46cf4b9b 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -46,7 +46,7 @@ enum options_client OPT_MAX_ALLOWED_PACKET, OPT_NET_BUFFER_LENGTH, OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, - OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, + OPT_SSL_CIPHER, OPT_TLS_VERSION, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, OPT_DELETE_MASTER_LOGS, OPT_COMPACT, OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, OPT_FRM, OPT_SKIP_OPTIMIZATION, diff --git a/client/mysql.cc b/client/mysql.cc index f1311991afe..c38ce6bc962 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1363,6 +1363,7 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user, opt_ssl_capath, opt_ssl_cipher); mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 3ad6ae40ab2..10b56f10228 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -359,6 +359,7 @@ int main(int argc,char *argv[]) opt_ssl_capath, opt_ssl_cipher); mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(&mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 11566a8b628..d28de8aeda6 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2126,6 +2126,7 @@ static Exit_status safe_connect() opt_ssl_capath, opt_ssl_cipher); mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqldump.c b/client/mysqldump.c index f1d59b449af..38db869c7ac 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1709,6 +1709,7 @@ static int connect_to_db(char *host, char *user,char *passwd) opt_ssl_capath, opt_ssl_cipher); mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(&mysql_connection, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 3e250bdd9ed..619def5f123 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -448,6 +448,7 @@ static MYSQL *db_connect(char *host, char *database, opt_ssl_capath, opt_ssl_cipher); mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 54c2a6e39fa..9885b219171 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -122,6 +122,7 @@ int main(int argc, char **argv) opt_ssl_capath, opt_ssl_cipher); mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(&mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); } mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index be4080384c4..4b663ebd2cd 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6068,6 +6068,7 @@ void do_connect(struct st_command *command) opt_ssl_capath, ssl_cipher ? ssl_cipher : opt_ssl_cipher); mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + mysql_options(con_slot->mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version); #if MYSQL_VERSION_ID >= 50000 /* Turn on ssl_verify_server_cert only if host is "localhost" */ opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost"); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 24bc739ca57..f0388048cdd 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -199,6 +199,7 @@ static char* log_ignored_opt; extern my_bool opt_use_ssl; +extern char *opt_tls_version; my_bool opt_ssl_verify_server_cert; my_bool opt_extended_validation; my_bool opt_encrypted_backup; @@ -830,6 +831,7 @@ enum options_xtrabackup OPT_XTRA_CHECK_PRIVILEGES }; + struct my_option xb_client_options[] = { {"verbose", 'V', "display verbose output", diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index be64e7f6590..d0278a1645d 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -46,6 +46,11 @@ "Certificate revocation list path (implies --ssl).", &opt_ssl_crlpath, &opt_ssl_crlpath, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"tls-version", OPT_TLS_VERSION, + "TLS protocol version for secure connection.", + &opt_tls_version, &opt_tls_version, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + #ifdef MYSQL_CLIENT {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, "Verify server's \"Common Name\" in its cert against hostname used " diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index c65aa693b76..e28f19b919d 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -30,6 +30,7 @@ SSL_STATIC char *opt_ssl_cipher = 0; SSL_STATIC char *opt_ssl_key = 0; SSL_STATIC char *opt_ssl_crl = 0; SSL_STATIC char *opt_ssl_crlpath = 0; +SSL_STATIC char *opt_tls_version = 0; #ifdef MYSQL_CLIENT SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; #endif diff --git a/include/violite.h b/include/violite.h index 7ee00912837..4778c5521de 100644 --- a/include/violite.h +++ b/include/violite.h @@ -59,6 +59,11 @@ struct vio_keepalive_opts }; +#define VIO_TLSv1_0 1 +#define VIO_TLSv1_1 2 +#define VIO_TLSv1_2 4 +#define VIO_TLSv1_3 8 + #define VIO_LOCALHOST 1U /* a localhost connection */ #define VIO_BUFFERED_READ 2U /* use buffered read */ #define VIO_READ_BUFFER_SIZE 16384U /* size of read buffer */ @@ -148,7 +153,8 @@ enum enum_ssl_init_error { SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY, SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS, - SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_LASTERR + SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_PROTOCOL, + SSL_INITERR_LASTERR }; const char* sslGetErrString(enum enum_ssl_init_error err); @@ -169,7 +175,8 @@ struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file,const char *ca_path, const char *cipher, enum enum_ssl_init_error *error, - const char *crl_file, const char *crl_path); + const char *crl_file, const char *crl_path, + ulonglong tls_version); void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); #endif /* HAVE_OPENSSL */ diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 402d64445e6..c5630770eff 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1352,6 +1352,8 @@ The following specify which files/extra groups are read (specified before remain --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes. Deprecated, has no effect. + --tls-version=name TLS protocol version for secure connections.. Any + combination of: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3 --tmp-disk-table-size=# Max size for data for an internal temporary on-disk MyISAM or Aria table. diff --git a/mysql-test/main/mysqld--help.test b/mysql-test/main/mysqld--help.test index c2b6424599a..9e67764d765 100644 --- a/mysql-test/main/mysqld--help.test +++ b/mysql-test/main/mysqld--help.test @@ -23,7 +23,7 @@ perl; log-slow-queries pid-file slow-query-log-file log-basename datadir slave-load-tmpdir tmpdir socket thread-pool-size large-files-support lower-case-file-system system-time-zone - collation-server character-set-server log-tc-size version.*/; + collation-server character-set-server log-tc-size tls-version version.*/; # Plugins which may or may not be there: @plugins=qw/innodb archive blackhole federated partition diff --git a/mysql-test/main/openssl_6975.test b/mysql-test/main/openssl_6975.test index 6a82d013fb6..bfcb0d56681 100644 --- a/mysql-test/main/openssl_6975.test +++ b/mysql-test/main/openssl_6975.test @@ -18,25 +18,25 @@ let $mysql=$MYSQL --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$ disable_abort_on_error; echo TLS1.2 ciphers: user is ok with any cipher; -exec $mysql --ssl-cipher=AES128-SHA256; +exec $mysql --tls-version=TLSv1.2 --ssl-cipher=AES128-SHA256; --replace_result DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 -exec $mysql --ssl-cipher=TLSv1.2; +exec $mysql --tls-version=TLSv1.2 --ssl-cipher=TLSv1.2; echo TLS1.2 ciphers: user requires SSLv3 cipher AES128-SHA; -exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA256; -exec $mysql --user ssl_sslv3 --ssl-cipher=TLSv1.2; +exec $mysql --user ssl_sslv3 --tls-version=TLSv1.2 --ssl-cipher=AES128-SHA256; +exec $mysql --user ssl_sslv3 --tls-version=TLSv1.2 --ssl-cipher=TLSv1.2; echo TLS1.2 ciphers: user requires TLSv1.2 cipher AES128-SHA256; -exec $mysql --user ssl_tls12 --ssl-cipher=AES128-SHA256; -exec $mysql --user ssl_tls12 --ssl-cipher=TLSv1.2; +exec $mysql --user ssl_tls12 --tls-version=TLSv1.2 --ssl-cipher=AES128-SHA256; +exec $mysql --user ssl_tls12 --tls-version=TLSv1.2 --ssl-cipher=TLSv1.2; echo SSLv3 ciphers: user is ok with any cipher; -exec $mysql --ssl-cipher=AES256-SHA; -exec $mysql --ssl-cipher=SSLv3; +exec $mysql --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=AES256-SHA; +exec $mysql --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=SSLv3; echo SSLv3 ciphers: user requires SSLv3 cipher AES128-SHA; -exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA; -exec $mysql --user ssl_sslv3 --ssl-cipher=SSLv3; +exec $mysql --user ssl_sslv3 --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=AES128-SHA; +exec $mysql --user ssl_sslv3 --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=SSLv3; echo SSLv3 ciphers: user requires TLSv1.2 cipher AES128-SHA256; -exec $mysql --user ssl_tls12 --ssl-cipher=AES128-SHA; -exec $mysql --user ssl_tls12 --ssl-cipher=SSLv3; +exec $mysql --user ssl_tls12 --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=AES128-SHA; +exec $mysql --user ssl_tls12 --tls-version=TLSv1.0,TLSv1.1,TLSv1.2 --ssl-cipher=SSLv3; drop user ssl_sslv3@localhost; drop user ssl_tls12@localhost; diff --git a/mysql-test/main/tls_version.opt b/mysql-test/main/tls_version.opt new file mode 100644 index 00000000000..5f30e3749a4 --- /dev/null +++ b/mysql-test/main/tls_version.opt @@ -0,0 +1 @@ +--tls_version=TLSv1.1,TLSv1.2 diff --git a/mysql-test/main/tls_version.result b/mysql-test/main/tls_version.result new file mode 100644 index 00000000000..d1b20a121fe --- /dev/null +++ b/mysql-test/main/tls_version.result @@ -0,0 +1,14 @@ +Variable_name Value +Ssl_version TLSv1.2 +Variable_name Value +Ssl_version TLSv1.2 +Variable_name Value +Ssl_version TLSv1.1 +Variable_name Value +Ssl_version TLSv1.1 +Variable_name Value +Ssl_version TLSv1.2 +Variable_name Value +Ssl_version TLSv1.2 +@@tls_version +TLSv1.1,TLSv1.2 diff --git a/mysql-test/main/tls_version.test b/mysql-test/main/tls_version.test new file mode 100644 index 00000000000..875fed19821 --- /dev/null +++ b/mysql-test/main/tls_version.test @@ -0,0 +1,24 @@ +# Tests for SSL connections, only run if mysqld is compiled +# with support for SSL. + +-- source include/have_ssl_communication.inc +#default is highest available version: TLSv1.2 +--exec $MYSQL --host=localhost --ssl -e "show status like 'ssl_version';" +# TLSv1.2 +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.2 -e "show status like 'ssl_version';" +# TLSv1.1 +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.1 -e "show status like 'ssl_version';" +# if a gap is between TLS versions, lowest version number should be used (TLS1.1) +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.1,TLSv1.3 -e "show status like 'ssl_version';" +# TLSv1.3 is not enabled, so TLSv1.2 should be used +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.2,TLSv1.3 -e "show status like 'ssl_version';" +# Highest TLS version number should be used (TLSv1.2) +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.1,TLSv1.2 -e "show status like 'ssl_version';" +# Errors: +# TLS v1.0 is disabled on server, so we should get an error +--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/ +--error 1 +--exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.0 -e "show status like 'ssl_version';" +# finally list available protocols +--exec $MYSQL --host=localhost --ssl -e "select @@tls_version;" + diff --git a/mysql-test/suite/sys_vars/inc/sysvars_server.inc b/mysql-test/suite/sys_vars/inc/sysvars_server.inc index af1b0ce4563..56053449bae 100644 --- a/mysql-test/suite/sys_vars/inc/sysvars_server.inc +++ b/mysql-test/suite/sys_vars/inc/sysvars_server.inc @@ -31,6 +31,7 @@ select * from information_schema.system_variables 'rand_seed1', 'rand_seed2', 'system_time_zone', + 'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', @@ -55,6 +56,7 @@ select VARIABLE_NAME, VARIABLE_SCOPE, VARIABLE_TYPE, VARIABLE_COMMENT, 'rand_seed1', 'rand_seed2', 'system_time_zone', + 'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 509e098498d..0b587ab82c2 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -20,6 +20,7 @@ variable_name not in ( 'rand_seed1', 'rand_seed2', 'system_time_zone', +'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', @@ -4661,6 +4662,7 @@ where variable_name in ( 'rand_seed1', 'rand_seed2', 'system_time_zone', +'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', @@ -4767,6 +4769,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME TLS_VERSION +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE SET +VARIABLE_COMMENT TLS protocol version for secure connections. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST TLSv1.0,TLSv1.1,TLSv1.2,TLSv1.3 +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME VERSION VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index aa75bb6e2f1..134c457dd8d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -20,6 +20,7 @@ variable_name not in ( 'rand_seed1', 'rand_seed2', 'system_time_zone', +'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', @@ -5725,6 +5726,7 @@ where variable_name in ( 'rand_seed1', 'rand_seed2', 'system_time_zone', +'tls_version', 'version_comment', 'version_source_revision', 'version_compile_machine', 'version_compile_os', @@ -5831,6 +5833,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME TLS_VERSION +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE SET +VARIABLE_COMMENT TLS protocol version for secure connections. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST TLSv1.0,TLSv1.1,TLSv1.2,TLSv1.3 +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME VERSION VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ea49e28384b..289d45cddee 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1444,8 +1444,8 @@ Query_cache query_cache; my_bool opt_use_ssl = 0; char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL, - *opt_ssl_crlpath= NULL; - + *opt_ssl_crlpath= NULL, *opt_tls_version= NULL; +ulonglong tls_version= 0; static scheduler_functions thread_scheduler_struct, extra_thread_scheduler_struct; scheduler_functions *thread_scheduler= &thread_scheduler_struct, @@ -4722,7 +4722,8 @@ static void init_ssl() ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher, &error, - opt_ssl_crl, opt_ssl_crlpath); + opt_ssl_crl, opt_ssl_crlpath, + tls_version); DBUG_PRINT("info",("ssl_acceptor_fd: %p", ssl_acceptor_fd)); if (!ssl_acceptor_fd) { @@ -4761,7 +4762,8 @@ int reinit_ssl() enum enum_ssl_init_error error = SSL_INITERR_NOERROR; st_VioSSLFd *new_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert, - opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher, &error, opt_ssl_crl, opt_ssl_crlpath); + opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher, &error, opt_ssl_crl, + opt_ssl_crlpath, tls_version); if (!new_fd) { diff --git a/sql/mysqld.h b/sql/mysqld.h index a29ca9ef8fe..c5e7872262a 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -635,6 +635,7 @@ extern Atomic_counter<uint32_t> thread_count; extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key, *opt_ssl_crl, *opt_ssl_crlpath; +extern ulonglong tls_version; extern MYSQL_PLUGIN_IMPORT pthread_key(THD*, THR_THD); @@ -697,6 +698,7 @@ enum options_mysqld OPT_WSREP_SYNC_WAIT, #endif /* WITH_WSREP */ OPT_MYSQL_COMPATIBILITY, + OPT_TLS_VERSION, OPT_MYSQL_TO_BE_IMPLEMENTED, OPT_which_is_always_the_last }; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1160e936a2b..f2a6000843d 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3565,6 +3565,29 @@ static Sys_var_charptr Sys_ssl_crlpath( READ_ONLY GLOBAL_VAR(opt_ssl_crlpath), SSL_OPT(OPT_SSL_CRLPATH), IN_FS_CHARSET, DEFAULT(0)); +static const char *tls_version_names[]= +{ + "TLSv1.0", + "TLSv1.1", + "TLSv1.2", + "TLSv1.3", + 0 +}; + +export bool tls_version_string_representation(THD *thd, sql_mode_t sql_mode, + LEX_CSTRING *ls) +{ + set_to_string(thd, ls, tls_version, tls_version_names); + return ls->str == 0; +} + +static Sys_var_set Sys_tls_version( + "tls_version", + "TLS protocol version for secure connections.", + READ_ONLY GLOBAL_VAR(tls_version), CMD_LINE(REQUIRED_ARG), + tls_version_names, + DEFAULT(VIO_TLSv1_1 | VIO_TLSv1_2 | VIO_TLSv1_3)); + static Sys_var_mybool Sys_standard_compliant_cte( "standard_compliant_cte", "Allow only CTEs compliant to SQL standard", diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 033d71779ab..4a31ebd1798 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -83,7 +83,8 @@ ssl_error_string[] = "SSL_CTX_set_default_verify_paths failed", "Failed to set ciphers to use", "SSL_CTX_new failed", - "SSL_CTX_set_tmp_dh failed" + "SSL_CTX_set_tmp_dh failed", + "Unknown TLS version" }; const char* @@ -183,21 +184,57 @@ static int wolfssl_send(WOLFSSL* ssl, char* buf, int sz, void* vio) } #endif /* HAVE_WOLFSSL */ +static long vio_tls_protocol_options(ulonglong tls_version) +{ + long tls_protocol_flags= +#ifdef TLS1_3_VERSION + SSL_OP_NO_TLSv1_3 | +#endif +#if defined(TLS1_2_VERSION) || defined(HAVE_WOLFSSL) + SSL_OP_NO_TLSv1_2 | +#endif + SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1; + long disabled_tls_protocols= tls_protocol_flags, + disabled_ssl_protocols= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + + if (!tls_version) + return disabled_ssl_protocols; + + if (tls_version & VIO_TLSv1_0) + disabled_tls_protocols&= ~SSL_OP_NO_TLSv1; + if (tls_version & VIO_TLSv1_1) + disabled_tls_protocols&= ~SSL_OP_NO_TLSv1_1; +#if defined(TLS1_2_VERSION) || defined(HAVE_WOLFSSL) + if (tls_version & VIO_TLSv1_2) + disabled_tls_protocols&= ~SSL_OP_NO_TLSv1_2; +#endif +#ifdef TLS1_3_VERSION + if (tls_version & VIO_TLSv1_3) + disabled_tls_protocols&= ~SSL_OP_NO_TLSv1_3; +#endif + + /* some garbage was specified in tls_version option */ + if (tls_protocol_flags == disabled_tls_protocols) + return -1; + return (disabled_tls_protocols | disabled_ssl_protocols); +} + /************************ VioSSLFd **********************************/ static struct st_VioSSLFd * new_VioSSLFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, const char *cipher, my_bool is_client_method, enum enum_ssl_init_error *error, - const char *crl_file, const char *crl_path) + const char *crl_file, const char *crl_path, ulonglong tls_version) { DH *dh; struct st_VioSSLFd *ssl_fd; - long ssl_ctx_options= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + long ssl_ctx_options; DBUG_ENTER("new_VioSSLFd"); DBUG_PRINT("enter", ("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' " - "cipher: '%s' crl_file: '%s' crl_path: '%s' ", + "cipher: '%s' crl_file: '%s' crl_path: '%s'", key_file ? key_file : "NULL", cert_file ? cert_file : "NULL", ca_file ? ca_file : "NULL", @@ -220,6 +257,14 @@ new_VioSSLFd(const char *key_file, const char *cert_file, goto err1; } + ssl_ctx_options= vio_tls_protocol_options(tls_version); + if (ssl_ctx_options == -1) + { + *error= SSL_INITERR_PROTOCOL; + DBUG_PRINT("error", ("%s", sslGetErrString(*error))); + goto err1; + } + SSL_CTX_set_options(ssl_fd->ssl_context, ssl_ctx_options); /* @@ -342,7 +387,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, ca_path, cipher, TRUE, error, - crl_file, crl_path))) + crl_file, crl_path, 0))) { return 0; } @@ -360,13 +405,14 @@ struct st_VioSSLFd * new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, const char *cipher, enum enum_ssl_init_error* error, - const char *crl_file, const char *crl_path) + const char *crl_file, const char *crl_path, + ulonglong tls_version) { struct st_VioSSLFd *ssl_fd; int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, ca_path, cipher, FALSE, error, - crl_file, crl_path))) + crl_file, crl_path, tls_version))) { return 0; } |