From bac0f8999d59dd5dd719408f4dcf8627c72cd1d1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 1 Sep 2023 10:25:53 +0200 Subject: [PATCH] client support for --ssl-fp and --ssl--fplist implement --ssl-fp and --ssl-fplist for all clients. --ssl-fp takes one certificate fingerprint, for example, 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 --ssl-fplist takes a path to a file with one fingerprint per line. if the server's certificate fingerprint matches ssl-fp or is found in the file - the certificate is considered verified. If the fingerprint is specified but doesn't match - the connection is aborted independently from the --ssl-verify-server-cert --- client/client_priv.h | 1 + extra/mariabackup/xtrabackup.cc | 2 +- include/sslopt-case.h | 5 +++++ include/sslopt-longopts.h | 5 +++++ include/sslopt-vars.h | 4 ++++ mysql-test/main/ssl_fp.result | 12 ++++++++++++ mysql-test/main/ssl_fp.test | 27 +++++++++++++++++++++++++++ 7 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 mysql-test/main/ssl_fp.result create mode 100644 mysql-test/main/ssl_fp.test diff --git a/client/client_priv.h b/client/client_priv.h index 597c074c9c2..882323badd5 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -111,6 +111,7 @@ enum options_client OPT_DO_DOMAIN_IDS, OPT_IGNORE_SERVER_IDS, OPT_DO_SERVER_IDS, + OPT_SSL_FP, OPT_SSL_FPLIST, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index a1ec7fb5f8f..f930e052a8b 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -217,10 +217,10 @@ static ulong max_buf_pool_modified_pct; /* Ignored option (--log) for MySQL option compatibility */ static char* log_ignored_opt; - extern my_bool opt_use_ssl; extern char *opt_tls_version; my_bool opt_ssl_verify_server_cert; +char *opt_ssl_fp, *opt_ssl_fplist; my_bool opt_extended_validation; my_bool opt_encrypted_backup; diff --git a/include/sslopt-case.h b/include/sslopt-case.h index 11351247cd7..c06796467ab 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -24,6 +24,11 @@ case OPT_SSL_CIPHER: case OPT_SSL_CRL: case OPT_SSL_CRLPATH: + case OPT_TLS_VERSION: +#ifdef MYSQL_CLIENT + case OPT_SSL_FP: + case OPT_SSL_FPLIST: +#endif /* Enable use of SSL if we are using any ssl option One can disable SSL later by using --skip-ssl or --ssl=0 diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index 15f4730b7d8..72315fec911 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -52,6 +52,11 @@ 0, 0, 0, 0, 0, 0}, #ifdef MYSQL_CLIENT + {"ssl-fp", OPT_SSL_FP, "Server certificate fingerprint (implies --ssl).", + &opt_ssl_fp, &opt_ssl_fp, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"ssl-fplist", OPT_SSL_FPLIST, "File with accepted server certificate " + "fingerprints, one per line (implies --ssl).", + &opt_ssl_fplist, &opt_ssl_fplist, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, "Verify server's certificate to prevent man-in-the-middle attacks", &opt_ssl_verify_server_cert, &opt_ssl_verify_server_cert, diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index c3b7d3efceb..f8708f8dcab 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -32,6 +32,8 @@ 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 char *opt_ssl_fp = 0; +SSL_STATIC char *opt_ssl_fplist = 0; SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; #define SET_SSL_OPTS(M) \ @@ -43,6 +45,8 @@ SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; mysql_options((M), MYSQL_OPT_SSL_CRL, opt_ssl_crl); \ mysql_options((M), MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); \ mysql_options((M), MARIADB_OPT_TLS_VERSION, opt_tls_version); \ + mysql_options((M), MARIADB_OPT_TLS_PEER_FP, opt_ssl_fp); \ + mysql_options((M), MARIADB_OPT_TLS_PEER_FP_LIST, opt_ssl_fplist); \ } \ mysql_options((M),MYSQL_OPT_SSL_VERIFY_SERVER_CERT, \ &opt_ssl_verify_server_cert); \ diff --git a/mysql-test/main/ssl_fp.result b/mysql-test/main/ssl_fp.result new file mode 100644 index 00000000000..fe15e5f5a13 --- /dev/null +++ b/mysql-test/main/ssl_fp.result @@ -0,0 +1,12 @@ +create function have_ssl() returns char(3) +return (select if(variable_value > '','yes','no') as 'have_ssl' + from information_schema.session_status +where variable_name='ssl_cipher'); +# mysql --protocol tcp -uroot --ssl-verify-server-cert -e "select test.have_ssl()" +ERROR 2026 (HY000): TLS/SSL error: Failed to verify the server certificate +# mysql --protocol tcp -uroot --ssl-fp=F1:D0:08:AF:A1:D2:F4:15:79:B4:39:06:41:F4:20:96:F1:90:A9:65 --ssl-verify-server-cert -e "select test.have_ssl()" +test.have_ssl() +yes +# mysql --protocol tcp -uroot --ssl-fp=00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 --disable-ssl-verify-server-cert -e "select test.have_ssl()" +ERROR 2026 (HY000): TLS/SSL error: Fingerprint verification of server certificate failed +drop function have_ssl; diff --git a/mysql-test/main/ssl_fp.test b/mysql-test/main/ssl_fp.test new file mode 100644 index 00000000000..b3c50ff9508 --- /dev/null +++ b/mysql-test/main/ssl_fp.test @@ -0,0 +1,27 @@ +source include/not_embedded.inc; + +create function have_ssl() returns char(3) + return (select if(variable_value > '','yes','no') as 'have_ssl' + from information_schema.session_status + where variable_name='ssl_cipher'); + +# +# passwordless root cannot connect w/o fingerprint: +# +--echo # mysql --protocol tcp -uroot --ssl-verify-server-cert -e "select test.have_ssl()" +--replace_regex /TLS\/SSL error.*certificate[^\n]*/TLS\/SSL error: Failed to verify the server certificate/ +--error 1 +--exec $MYSQL --protocol tcp -uroot --ssl-verify-server-cert -e "select test.have_ssl()" 2>&1 +# +# fingerprint based cert verification: +# +--echo # mysql --protocol tcp -uroot --ssl-fp=F1:D0:08:AF:A1:D2:F4:15:79:B4:39:06:41:F4:20:96:F1:90:A9:65 --ssl-verify-server-cert -e "select test.have_ssl()" +--exec $MYSQL --protocol tcp -uroot --ssl-fp=F1:D0:08:AF:A1:D2:F4:15:79:B4:39:06:41:F4:20:96:F1:90:A9:65 --ssl-verify-server-cert -e "select test.have_ssl()" 2>&1 +# +# wrong fingerprint fails even with --disable-ssl-verify-server-cert +# +--echo # mysql --protocol tcp -uroot --ssl-fp=00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 --disable-ssl-verify-server-cert -e "select test.have_ssl()" +--error 1 +--exec $MYSQL --protocol tcp -uroot --ssl-fp=00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 --disable-ssl-verify-server-cert -e "select test.have_ssl()" 2>&1 + +drop function have_ssl;