diff options
-rw-r--r-- | client/client_priv.h | 1 | ||||
-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 | 15 | ||||
-rw-r--r-- | mysql-test/r/mysqld--help.result | 2 | ||||
-rw-r--r-- | mysql-test/r/ssl_cipher.result | 16 | ||||
-rw-r--r-- | mysql-test/t/mysqld--help.test | 5 | ||||
-rw-r--r-- | mysql-test/t/openssl_6975.test | 24 | ||||
-rw-r--r-- | mysql-test/t/ssl.test | 2 | ||||
-rw-r--r-- | mysql-test/t/ssl_cert_verify.test | 2 | ||||
-rw-r--r-- | mysql-test/t/ssl_cipher.test | 9 | ||||
-rw-r--r-- | sql/mysqld.cc | 63 | ||||
-rw-r--r-- | sql/mysqld.h | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 33 | ||||
-rw-r--r-- | vio/viosslfactories.c | 61 |
23 files changed, 157 insertions, 93 deletions
diff --git a/client/client_priv.h b/client/client_priv.h index ba1a1fddfae..f614ff80332 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -98,6 +98,7 @@ enum options_client OPT_REPORT_PROGRESS, OPT_SKIP_ANNOTATE_ROWS_EVENTS, OPT_SSL_CRL, OPT_SSL_CRLPATH, + OPT_TLS_VERSION, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/mysql.cc b/client/mysql.cc index e9a17a3f358..8f023ce7349 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1369,6 +1369,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, (void *)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 5e7fb80b2b5..a6301b32c61 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -361,6 +361,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, (void *)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 4c271b73b96..1e4ac8fa9bb 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2082,6 +2082,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, (void *)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 f64acb044f5..84e7372c35b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1686,6 +1686,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, (void *)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 02caf2df198..4844481110b 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -452,6 +452,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, (void *)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 65b915655a6..d72ebe18f01 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -125,6 +125,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, (void *)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 e805fc61a54..fd13fc71306 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6102,6 +6102,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, (void *)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 e627826b8c4..d1217d5a1f0 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 const char *opt_tls_version; my_bool opt_ssl_verify_server_cert; /* === metadata of backup === */ @@ -838,6 +839,7 @@ enum options_xtrabackup OPT_BACKUP_ROCKSDB }; + struct my_option xb_client_options[] = { {"verbose", 'V', "display verbose output", diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index e605d0134e7..e940e46816e 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 8e669760faf..9f0d9ecc439 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 5dcf27dbab1..182c80d04c2 100644 --- a/include/violite.h +++ b/include/violite.h @@ -51,6 +51,11 @@ enum enum_vio_io_event VIO_IO_EVENT_CONNECT }; +#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 */ @@ -143,7 +148,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); @@ -162,9 +168,10 @@ struct st_VioSSLFd const char *crl_file, const char *crl_path); 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 *ca_file,const char *ca_path, + const char *cipher, enum enum_ssl_init_error *error, + const char *crl_file, const char *crl_path, + long tls_version); void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); #endif /* HAVE_OPENSSL */ diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 51ece335908..4e5ab7e0d9f 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1169,6 +1169,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 --tmp-disk-table-size=# Max size for data for an internal temporary on-disk MyISAM or Aria table. diff --git a/mysql-test/r/ssl_cipher.result b/mysql-test/r/ssl_cipher.result index 79998dfca80..d94ffa4e04b 100644 --- a/mysql-test/r/ssl_cipher.result +++ b/mysql-test/r/ssl_cipher.result @@ -2,11 +2,15 @@ # BUG#11760210 - SSL_CIPHER_LIST NOT SET OR RETURNED FOR "SHOW STATUS LIKE 'SSL_CIPHER_LIST'" # connect ssl_con,localhost,root,,,,,SSL; -SHOW STATUS LIKE 'Ssl_cipher'; -Variable_name Value -Ssl_cipher AES128-SHA -SHOW STATUS LIKE 'Ssl_cipher_list'; -Variable_name Value -Ssl_cipher_list AES128-SHA +select variable_value into @a from information_schema.session_status where variable_name like 'SSL_CIPHER'; +select length(@a) > 0; +length(@a) > 0 +1 +select length(VARIABLE_VALUE) > 0 from information_schema.session_status where variable_name like 'SSL_CIPHER_LIST'; +length(VARIABLE_VALUE) > 0 +1 +select position(@a in VARIABLE_VALUE) > 0 from information_schema.session_status where variable_name like 'SSL_CIPHER_LIST'; +position(@a in VARIABLE_VALUE) > 0 +1 connection default; disconnect ssl_con; diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 1613f8e7a4f..4e71c86e506 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/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 @@ -54,6 +54,9 @@ perl; $skip=1 if / --($re2)\b/; y!\\!/!; s/[ ]+/ /; # squeeze spaces to remove table formatting + # fix tls_version + s/, TLSv1.2//; + s/, TLSv1.3//; # fixes for 32-bit s/\b4294967295\b/18446744073709551615/; s/\b2146435072\b/9223372036853727232/; diff --git a/mysql-test/t/openssl_6975.test b/mysql-test/t/openssl_6975.test index 6a82d013fb6..bfcb0d56681 100644 --- a/mysql-test/t/openssl_6975.test +++ b/mysql-test/t/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/t/ssl.test b/mysql-test/t/ssl.test index f2ac288db7a..6071e26a26f 100644 --- a/mysql-test/t/ssl.test +++ b/mysql-test/t/ssl.test @@ -34,7 +34,7 @@ disconnect ssl_con; create user mysqltest_1@localhost; grant usage on mysqltest.* to mysqltest_1@localhost require cipher "AES256-SHA"; ---exec $MYSQL -umysqltest_1 --ssl-cipher=AES256-SHA -e "show status like 'ssl_cipher'" 2>&1 +--exec $MYSQL -umysqltest_1 --tls_version=TLSv1.2 --ssl-cipher=AES256-SHA -e "show status like 'ssl_cipher'" 2>&1 drop user mysqltest_1@localhost; # Wait till all disconnects are completed diff --git a/mysql-test/t/ssl_cert_verify.test b/mysql-test/t/ssl_cert_verify.test index 83f621b7ca9..51b1612e45b 100644 --- a/mysql-test/t/ssl_cert_verify.test +++ b/mysql-test/t/ssl_cert_verify.test @@ -30,7 +30,7 @@ let $ssl_verify_pass_path = --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-veri --enable_reconnect --source include/wait_until_connected_again.inc ---replace_result TLSv1.2 TLS_VERSION TLSv1.1 TLS_VERSION TLSv1 TLS_VERSION +--replace_result TLSv1.3 TLS_VERSION TLSv1.2 TLS_VERSION TLSv1.1 TLS_VERSION TLSv1 TLS_VERSION --exec $MYSQL --protocol=tcp --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-verify-server-cert -e "SHOW STATUS like 'Ssl_version'" --echo # restart server using restart diff --git a/mysql-test/t/ssl_cipher.test b/mysql-test/t/ssl_cipher.test index cf249343324..82dbf817a1d 100644 --- a/mysql-test/t/ssl_cipher.test +++ b/mysql-test/t/ssl_cipher.test @@ -13,8 +13,13 @@ connect (ssl_con,localhost,root,,,,,SSL); # Check Cipher Name and Cipher List -SHOW STATUS LIKE 'Ssl_cipher'; -SHOW STATUS LIKE 'Ssl_cipher_list'; +select variable_value into @a from information_schema.session_status where variable_name like 'SSL_CIPHER'; +# Check if cipher is empty +select length(@a) > 0; +# check if cipher list is empty +select length(VARIABLE_VALUE) > 0 from information_schema.session_status where variable_name like 'SSL_CIPHER_LIST'; +# check if cipher is in list +select position(@a in VARIABLE_VALUE) > 0 from information_schema.session_status where variable_name like 'SSL_CIPHER_LIST'; connection default; disconnect ssl_con; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 77736607e22..3484ff87da3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1504,8 +1504,8 @@ HANDLE smem_event_connect_request= 0; 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; +long tls_version= 0; static scheduler_functions thread_scheduler_struct, extra_thread_scheduler_struct; scheduler_functions *thread_scheduler= &thread_scheduler_struct, @@ -4865,7 +4865,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) { @@ -7922,16 +7923,6 @@ static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context)); - return 0; -} - static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) @@ -7943,17 +7934,6 @@ static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, return 0; } -static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, - char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context)); - return 0; -} - static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) { @@ -8014,16 +7994,6 @@ static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)); - return 0; -} - static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) @@ -8035,26 +8005,6 @@ static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, return 0; } -static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)); - return 0; -} - static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) @@ -8542,13 +8492,8 @@ SHOW_VAR status_vars[]= { {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_SIMPLE_FUNC}, {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC}, {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC}, - {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_SIMPLE_FUNC}, - {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_SIMPLE_FUNC}, - {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_SIMPLE_FUNC}, - {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_SIMPLE_FUNC}, {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC}, {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_SIMPLE_FUNC}, - {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_SIMPLE_FUNC}, {"Ssl_server_not_after", (char*) &show_ssl_get_server_not_after, SHOW_SIMPLE_FUNC}, {"Ssl_server_not_before", (char*) &show_ssl_get_server_not_before, SHOW_SIMPLE_FUNC}, {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_SIMPLE_FUNC}, diff --git a/sql/mysqld.h b/sql/mysqld.h index b02bd9fb1f6..3a1109a69b2 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -588,6 +588,7 @@ extern int32 thread_count, service_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 long tls_version; extern MYSQL_PLUGIN_IMPORT pthread_key(THD*, THR_THD); @@ -650,6 +651,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 391772d1191..4b8e6eca8b8 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3198,6 +3198,39 @@ 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", +#ifdef TLS1_2_VERSION + "TLSv1.2", +#endif +#ifdef TLS1_3_VERSION + "TLSv1.3", +#endif + 0 +}; + +export bool tls_version_string_representation(THD *thd, sql_mode_t sql_mode, + LEX_STRING *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_0 | VIO_TLSv1_1 +#ifdef TLS1_2_VERSION + | VIO_TLSv1_2 +#endif +#ifdef TLS1_3_VERSION + | VIO_TLSv1_3 +#endif + )); + 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 fa02eb03caa..6b7e1341503 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -85,7 +85,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* @@ -166,21 +167,58 @@ static void check_ssl_init() } } +static long vio_tls_protocol_options(long tls_version) +{ + long tls_protocol_flags= +#ifdef TLS1_3_VERSION + SSL_OP_NO_TLSv1_3 | +#endif +#ifdef TLS1_2_VERSION + 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; +#ifdef TLS1_2_VERSION + 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, + long 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", @@ -203,6 +241,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); /* @@ -317,7 +363,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; } @@ -335,13 +381,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, + long 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; } |