summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client_priv.h1
-rw-r--r--client/mysql.cc1
-rw-r--r--client/mysqladmin.cc1
-rw-r--r--client/mysqlbinlog.cc1
-rw-r--r--client/mysqldump.c1
-rw-r--r--client/mysqlimport.c1
-rw-r--r--client/mysqlshow.c1
-rw-r--r--client/mysqltest.cc1
-rw-r--r--extra/mariabackup/xtrabackup.cc2
-rw-r--r--include/sslopt-longopts.h5
-rw-r--r--include/sslopt-vars.h1
-rw-r--r--include/violite.h15
-rw-r--r--mysql-test/r/mysqld--help.result2
-rw-r--r--mysql-test/r/ssl_cipher.result16
-rw-r--r--mysql-test/t/mysqld--help.test5
-rw-r--r--mysql-test/t/openssl_6975.test24
-rw-r--r--mysql-test/t/ssl.test2
-rw-r--r--mysql-test/t/ssl_cert_verify.test2
-rw-r--r--mysql-test/t/ssl_cipher.test9
-rw-r--r--sql/mysqld.cc63
-rw-r--r--sql/mysqld.h2
-rw-r--r--sql/sys_vars.cc33
-rw-r--r--vio/viosslfactories.c61
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;
}