MDEV-31855 validate ssl certificates using client password in the internal client
port the client-side implementation from C/C to the internal client. add the test.
This commit is contained in:
parent
386df8793b
commit
e0c30390a7
@ -289,8 +289,9 @@ typedef struct st_mysql
|
|||||||
/* session-wide random string */
|
/* session-wide random string */
|
||||||
char scramble[SCRAMBLE_LENGTH+1];
|
char scramble[SCRAMBLE_LENGTH+1];
|
||||||
my_bool auto_local_infile;
|
my_bool auto_local_infile;
|
||||||
void *unused2, *unused3, *unused4;
|
void *unused2, *unused3;
|
||||||
MYSQL_FIELD *fields;
|
MYSQL_FIELD *fields;
|
||||||
|
const char *tls_self_signed_error;
|
||||||
|
|
||||||
LIST *stmts; /* list of all statements */
|
LIST *stmts; /* list of all statements */
|
||||||
const struct st_mysql_methods *methods;
|
const struct st_mysql_methods *methods;
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
#define MYSQL_CLIENT_reserved2 1
|
#define MYSQL_CLIENT_reserved2 1
|
||||||
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
|
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
|
||||||
|
|
||||||
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
|
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0101
|
||||||
|
|
||||||
#define MYSQL_CLIENT_MAX_PLUGINS 3
|
#define MYSQL_CLIENT_MAX_PLUGINS 3
|
||||||
|
|
||||||
@ -96,6 +96,7 @@ struct st_mysql_client_plugin_AUTHENTICATION
|
|||||||
{
|
{
|
||||||
MYSQL_CLIENT_PLUGIN_HEADER
|
MYSQL_CLIENT_PLUGIN_HEADER
|
||||||
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
|
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
|
||||||
|
int (*hash_password_bin)(struct st_mysql *mysql, unsigned char *hash, size_t *hash_length);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <mysql/auth_dialog_client.h>
|
#include <mysql/auth_dialog_client.h>
|
||||||
|
@ -22,6 +22,7 @@ struct st_mysql_client_plugin_AUTHENTICATION
|
|||||||
{
|
{
|
||||||
int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *);
|
int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *);
|
||||||
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
|
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
|
||||||
|
int (*hash_password_bin)(struct st_mysql *mysql, unsigned char *hash, size_t *hash_length);
|
||||||
};
|
};
|
||||||
struct st_mysql;
|
struct st_mysql;
|
||||||
typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
|
typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
|
||||||
|
@ -7,3 +7,7 @@ FLUSH PRIVILEGES;
|
|||||||
# xtrabackup move back
|
# xtrabackup move back
|
||||||
# restart
|
# restart
|
||||||
DROP USER backup_user;
|
DROP USER backup_user;
|
||||||
|
#
|
||||||
|
# MDEV-31855 validate ssl certificates using client password in the internal client
|
||||||
|
#
|
||||||
|
# tcp ssl ssl-verify-server-cert
|
||||||
|
@ -14,3 +14,10 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
|||||||
DROP USER backup_user;
|
DROP USER backup_user;
|
||||||
rmdir $targetdir;
|
rmdir $targetdir;
|
||||||
|
|
||||||
|
echo #;
|
||||||
|
echo # MDEV-31855 validate ssl certificates using client password in the internal client;
|
||||||
|
echo #;
|
||||||
|
# fails to connect, passwordless root
|
||||||
|
echo # tcp ssl ssl-verify-server-cert;
|
||||||
|
error 1;
|
||||||
|
exec $XTRABACKUP --protocol=tcp --user=root --port=$MASTER_MYPORT --backup --target-dir=$targetdir;
|
||||||
|
4
mysql-test/suite/mariabackup/backup_ssl_not_win.result
Normal file
4
mysql-test/suite/mariabackup/backup_ssl_not_win.result
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
# MDEV-31855 validate ssl certificates using client password in the internal client
|
||||||
|
#
|
||||||
|
# socket ssl ssl-verify-server-cert
|
10
mysql-test/suite/mariabackup/backup_ssl_not_win.test
Normal file
10
mysql-test/suite/mariabackup/backup_ssl_not_win.test
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
source include/not_windows.inc;
|
||||||
|
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||||
|
|
||||||
|
echo #;
|
||||||
|
echo # MDEV-31855 validate ssl certificates using client password in the internal client;
|
||||||
|
echo #;
|
||||||
|
# connects fine, unix socket is a secure transport
|
||||||
|
echo # socket ssl ssl-verify-server-cert;
|
||||||
|
exec $XTRABACKUP --protocol=socket --user=root --socket=$MASTER_MYSOCK --backup --target-dir=$targetdir;
|
||||||
|
rmdir $targetdir;
|
@ -75,14 +75,42 @@ Master_SSL_Cert = 'MYSQL_TEST_DIR/std_data/client-cert.pem'
|
|||||||
Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem'
|
Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem'
|
||||||
include/check_slave_is_running.inc
|
include/check_slave_is_running.inc
|
||||||
connection master;
|
connection master;
|
||||||
|
create user replssl@127.0.0.1 identified by "sslrepl";
|
||||||
|
grant replication slave on *.* to replssl@127.0.0.1 require ssl;
|
||||||
|
connection slave;
|
||||||
|
stop slave;
|
||||||
|
include/wait_for_slave_to_stop.inc
|
||||||
|
change master to
|
||||||
|
master_host="127.0.0.1",
|
||||||
|
master_user='replssl',
|
||||||
|
master_password="sslrepl",
|
||||||
|
master_ssl=1,
|
||||||
|
master_ssl_verify_server_cert=1,
|
||||||
|
master_ssl_ca ='',
|
||||||
|
master_ssl_cert='',
|
||||||
|
master_ssl_key='';
|
||||||
|
start slave;
|
||||||
|
include/wait_for_slave_to_start.inc
|
||||||
|
show tables;
|
||||||
|
Tables_in_test
|
||||||
|
t1
|
||||||
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
connection slave;
|
connection slave;
|
||||||
|
show tables;
|
||||||
|
Tables_in_test
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
CHANGE MASTER TO
|
CHANGE MASTER TO
|
||||||
master_host="127.0.0.1",
|
master_host="127.0.0.1",
|
||||||
|
master_user='root',
|
||||||
|
master_password='',
|
||||||
master_ssl_ca ='',
|
master_ssl_ca ='',
|
||||||
master_ssl_cert='',
|
master_ssl_cert='',
|
||||||
master_ssl_key='',
|
master_ssl_key='',
|
||||||
master_ssl_verify_server_cert=0,
|
master_ssl_verify_server_cert=0,
|
||||||
master_ssl=0;
|
master_ssl=0;
|
||||||
|
connection master;
|
||||||
|
drop user replssl@127.0.0.1;
|
||||||
|
connection slave;
|
||||||
|
drop user replssl@127.0.0.1;
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
@ -95,19 +95,47 @@ select * from t1;
|
|||||||
source include/show_slave_status.inc;
|
source include/show_slave_status.inc;
|
||||||
--source include/check_slave_is_running.inc
|
--source include/check_slave_is_running.inc
|
||||||
|
|
||||||
# ==== Clean up ====
|
# MDEV-31855 validate with master_password
|
||||||
|
connection master;
|
||||||
|
create user replssl@127.0.0.1 identified by "sslrepl";
|
||||||
|
grant replication slave on *.* to replssl@127.0.0.1 require ssl;
|
||||||
|
|
||||||
|
connection slave;
|
||||||
|
stop slave;
|
||||||
|
--source include/wait_for_slave_to_stop.inc
|
||||||
|
eval change master to
|
||||||
|
master_host="127.0.0.1",
|
||||||
|
master_user='replssl',
|
||||||
|
master_password="sslrepl",
|
||||||
|
master_ssl=1,
|
||||||
|
master_ssl_verify_server_cert=1,
|
||||||
|
master_ssl_ca ='',
|
||||||
|
master_ssl_cert='',
|
||||||
|
master_ssl_key='';
|
||||||
|
start slave;
|
||||||
|
--source include/wait_for_slave_to_start.inc
|
||||||
|
|
||||||
|
show tables;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
|
show tables;
|
||||||
|
|
||||||
|
# ==== Clean up ====
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
CHANGE MASTER TO
|
CHANGE MASTER TO
|
||||||
master_host="127.0.0.1",
|
master_host="127.0.0.1",
|
||||||
|
master_user='root',
|
||||||
|
master_password='',
|
||||||
master_ssl_ca ='',
|
master_ssl_ca ='',
|
||||||
master_ssl_cert='',
|
master_ssl_cert='',
|
||||||
master_ssl_key='',
|
master_ssl_key='',
|
||||||
master_ssl_verify_server_cert=0,
|
master_ssl_verify_server_cert=0,
|
||||||
master_ssl=0;
|
master_ssl=0;
|
||||||
|
connection master;
|
||||||
|
drop user replssl@127.0.0.1;
|
||||||
|
connection slave;
|
||||||
|
drop user replssl@127.0.0.1;
|
||||||
|
|
||||||
--let $rpl_only_running_threads= 1
|
--let $rpl_only_running_threads= 1
|
||||||
--source include/rpl_end.inc
|
--source include/rpl_end.inc
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
#error see libmariadb/plugins/auth/ed25519.c instead
|
||||||
/************************** CLIENT *************************************/
|
/************************** CLIENT *************************************/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -113,5 +113,6 @@ mysql_declare_client_plugin(AUTHENTICATION)
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
test_plugin_client
|
test_plugin_client,
|
||||||
|
NULL
|
||||||
mysql_end_client_plugin;
|
mysql_end_client_plugin;
|
||||||
|
@ -250,5 +250,6 @@ mysql_declare_client_plugin(AUTHENTICATION)
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
test_plugin_client
|
test_plugin_client,
|
||||||
|
NULL
|
||||||
mysql_end_client_plugin;
|
mysql_end_client_plugin;
|
||||||
|
@ -230,5 +230,6 @@ mysql_declare_client_plugin(AUTHENTICATION)
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
test_plugin_client
|
test_plugin_client,
|
||||||
|
NULL
|
||||||
mysql_end_client_plugin;
|
mysql_end_client_plugin;
|
||||||
|
@ -167,6 +167,7 @@ static void mysql_close_free_options(MYSQL *mysql);
|
|||||||
static void mysql_close_free(MYSQL *mysql);
|
static void mysql_close_free(MYSQL *mysql);
|
||||||
static void mysql_prune_stmt_list(MYSQL *mysql);
|
static void mysql_prune_stmt_list(MYSQL *mysql);
|
||||||
static int cli_report_progress(MYSQL *mysql, char *packet, uint length);
|
static int cli_report_progress(MYSQL *mysql, char *packet, uint length);
|
||||||
|
static my_bool parse_ok_packet(MYSQL *mysql, ulong length);
|
||||||
|
|
||||||
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
|
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
|
||||||
|
|
||||||
@ -1571,8 +1572,7 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
ssl_verify_server_cert()
|
ssl_verify_server_cert()
|
||||||
vio pointer to a SSL connected vio
|
MYSQL mysql
|
||||||
server_hostname name of the server that we connected to
|
|
||||||
errptr if we fail, we'll return (a pointer to a string
|
errptr if we fail, we'll return (a pointer to a string
|
||||||
describing) the reason here
|
describing) the reason here
|
||||||
|
|
||||||
@ -1586,22 +1586,22 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
|
|||||||
|
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr)
|
static int ssl_verify_server_cert(MYSQL *mysql, const char **errptr)
|
||||||
{
|
{
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
X509 *server_cert= NULL;
|
X509 *server_cert= NULL;
|
||||||
int ret_validation= 1;
|
int ret_validation= 1;
|
||||||
|
|
||||||
DBUG_ENTER("ssl_verify_server_cert");
|
DBUG_ENTER("ssl_verify_server_cert");
|
||||||
DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
|
DBUG_PRINT("enter", ("server_hostname: %s", mysql->host));
|
||||||
|
|
||||||
if (!(ssl= (SSL*)vio->ssl_arg))
|
if (!(ssl= (SSL*)mysql->net.vio->ssl_arg))
|
||||||
{
|
{
|
||||||
*errptr= "No SSL pointer found";
|
*errptr= "No SSL pointer found";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!server_hostname)
|
if (!mysql->host)
|
||||||
{
|
{
|
||||||
*errptr= "No server hostname supplied";
|
*errptr= "No server hostname supplied";
|
||||||
goto error;
|
goto error;
|
||||||
@ -1613,21 +1613,29 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const c
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (X509_V_OK != SSL_get_verify_result(ssl))
|
switch (SSL_get_verify_result(ssl))
|
||||||
{
|
{
|
||||||
*errptr= "Failed to verify the server certificate";
|
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: /* OpenSSL */
|
||||||
goto error;
|
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* OpenSSL */
|
||||||
}
|
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: /* wolfSSL */
|
||||||
/*
|
/*
|
||||||
We already know that the certificate exchanged was valid; the SSL library
|
If the caller have specified CA - it'll define whether the
|
||||||
handled that. Now we need to verify that the contents of the certificate
|
cert is good. Otherwise we'll do more checks.
|
||||||
are what we expect.
|
|
||||||
*/
|
*/
|
||||||
|
ret_validation= (mysql->options.ssl_ca && mysql->options.ssl_ca[0]) ||
|
||||||
ret_validation= X509_check_host(server_cert, server_hostname,
|
(mysql->options.ssl_capath && mysql->options.ssl_capath[0]);
|
||||||
strlen(server_hostname), 0, 0) != 1 &&
|
mysql->tls_self_signed_error= *errptr= "SSL certificate is self-signed";
|
||||||
X509_check_ip_asc(server_cert, server_hostname, 0) != 1;
|
break;
|
||||||
|
case X509_V_OK:
|
||||||
|
ret_validation= X509_check_host(server_cert, mysql->host,
|
||||||
|
strlen(mysql->host), 0, 0) != 1 &&
|
||||||
|
X509_check_ip_asc(server_cert, mysql->host, 0) != 1;
|
||||||
*errptr= "SSL certificate validation failure";
|
*errptr= "SSL certificate validation failure";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*errptr= "Failed to verify the server certificate";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
X509_free(server_cert);
|
X509_free(server_cert);
|
||||||
@ -1759,6 +1767,7 @@ C_MODE_END
|
|||||||
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
|
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
|
||||||
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
|
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
|
||||||
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
|
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
|
||||||
|
static int native_password_auth_hash(MYSQL *mysql, uchar *out, size_t *outlen);
|
||||||
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
|
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
|
||||||
|
|
||||||
static auth_plugin_t native_password_client_plugin=
|
static auth_plugin_t native_password_client_plugin=
|
||||||
@ -1768,13 +1777,14 @@ static auth_plugin_t native_password_client_plugin=
|
|||||||
native_password_plugin_name,
|
native_password_plugin_name,
|
||||||
"R.J.Silk, Sergei Golubchik",
|
"R.J.Silk, Sergei Golubchik",
|
||||||
"Native MySQL authentication",
|
"Native MySQL authentication",
|
||||||
{1, 0, 0},
|
{1, 0, 1},
|
||||||
"GPL",
|
"GPL",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
native_password_auth_client
|
native_password_auth_client,
|
||||||
|
native_password_auth_hash
|
||||||
};
|
};
|
||||||
|
|
||||||
static auth_plugin_t old_password_client_plugin=
|
static auth_plugin_t old_password_client_plugin=
|
||||||
@ -1790,7 +1800,8 @@ static auth_plugin_t old_password_client_plugin=
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
old_password_auth_client
|
old_password_auth_client,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2018,6 +2029,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
{
|
{
|
||||||
MYSQL *mysql= mpvio->mysql;
|
MYSQL *mysql= mpvio->mysql;
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
|
enum enum_vio_type vio_type= net->vio->type;
|
||||||
char *buff, *end;
|
char *buff, *end;
|
||||||
size_t buff_size;
|
size_t buff_size;
|
||||||
size_t connect_attrs_len=
|
size_t connect_attrs_len=
|
||||||
@ -2052,7 +2064,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
if (mpvio->db)
|
if (mpvio->db)
|
||||||
mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
|
mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
|
||||||
|
|
||||||
if (mysql->net.vio->type == VIO_TYPE_NAMEDPIPE)
|
if (vio_type == VIO_TYPE_NAMEDPIPE)
|
||||||
{
|
{
|
||||||
mysql->server_capabilities&= ~CLIENT_SSL;
|
mysql->server_capabilities&= ~CLIENT_SSL;
|
||||||
mysql->options.use_ssl= 0;
|
mysql->options.use_ssl= 0;
|
||||||
@ -2141,7 +2153,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
ER(CR_SSL_CONNECTION_ERROR), sslGetErrString(ssl_init_error));
|
ER(CR_SSL_CONNECTION_ERROR), sslGetErrString(ssl_init_error));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
mysql->connector_fd= (unsigned char *) ssl_fd;
|
mysql->connector_fd= (uchar *) ssl_fd;
|
||||||
|
|
||||||
/* Connect to the server */
|
/* Connect to the server */
|
||||||
DBUG_PRINT("info", ("IO layer change in progress..."));
|
DBUG_PRINT("info", ("IO layer change in progress..."));
|
||||||
@ -2160,12 +2172,32 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
|
|
||||||
/* Verify server cert */
|
/* Verify server cert */
|
||||||
if ((mysql->options.extension && mysql->options.extension->tls_verify_server_cert) &&
|
if ((mysql->options.extension && mysql->options.extension->tls_verify_server_cert) &&
|
||||||
ssl_verify_server_cert(net->vio, mysql->host, &cert_error))
|
ssl_verify_server_cert(mysql, &cert_error))
|
||||||
{
|
{
|
||||||
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
|
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
|
||||||
ER(CR_SSL_CONNECTION_ERROR), cert_error);
|
ER(CR_SSL_CONNECTION_ERROR), cert_error);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (mysql->tls_self_signed_error)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If the transport is secure (see opt_require_secure_transport) we
|
||||||
|
allow a self-signed cert as we know it came from the server.
|
||||||
|
|
||||||
|
If no password or plugin uses insecure protocol - refuse the cert.
|
||||||
|
|
||||||
|
Otherwise one last cert check after auth.
|
||||||
|
*/
|
||||||
|
if (vio_type == VIO_TYPE_SOCKET)
|
||||||
|
mysql->tls_self_signed_error= 0;
|
||||||
|
else if (!mysql->passwd || !mysql->passwd[0] ||
|
||||||
|
!mpvio->plugin->hash_password_bin)
|
||||||
|
{
|
||||||
|
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
|
||||||
|
ER(CR_SSL_CONNECTION_ERROR), mysql->tls_self_signed_error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
|
|
||||||
@ -2520,6 +2552,14 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
|
|||||||
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
|
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
|
||||||
DBUG_RETURN (1);
|
DBUG_RETURN (1);
|
||||||
|
|
||||||
|
/* refuse insecure plugin if TLS is in doubt */
|
||||||
|
if (mysql->tls_self_signed_error && !auth_plugin->hash_password_bin)
|
||||||
|
{
|
||||||
|
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
|
||||||
|
ER(CR_SSL_CONNECTION_ERROR), mysql->tls_self_signed_error);
|
||||||
|
DBUG_RETURN (1);
|
||||||
|
}
|
||||||
|
|
||||||
mpvio.plugin= auth_plugin;
|
mpvio.plugin= auth_plugin;
|
||||||
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
|
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
|
||||||
|
|
||||||
@ -2541,7 +2581,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
|
|||||||
if (res != CR_OK_HANDSHAKE_COMPLETE)
|
if (res != CR_OK_HANDSHAKE_COMPLETE)
|
||||||
{
|
{
|
||||||
/* Read what server thinks about out new auth message report */
|
/* Read what server thinks about out new auth message report */
|
||||||
if (cli_safe_read(mysql) == packet_error)
|
if ((pkt_length= cli_safe_read(mysql)) == packet_error)
|
||||||
{
|
{
|
||||||
if (mysql->net.last_errno == CR_SERVER_LOST)
|
if (mysql->net.last_errno == CR_SERVER_LOST)
|
||||||
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
||||||
@ -2556,7 +2596,43 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
|
|||||||
net->read_pos[0] should always be 0 here if the server implements
|
net->read_pos[0] should always be 0 here if the server implements
|
||||||
the protocol correctly
|
the protocol correctly
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN (mysql->net.read_pos[0] != 0);
|
if (mysql->net.read_pos[0] != 0)
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
if (!mysql->tls_self_signed_error)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
/* Last attempt to validate the cert: compare cert info packet */
|
||||||
|
DBUG_ASSERT(mysql->options.use_ssl);
|
||||||
|
DBUG_ASSERT(mysql->net.vio->ssl_arg);
|
||||||
|
DBUG_ASSERT(mysql->options.extension->tls_verify_server_cert);
|
||||||
|
DBUG_ASSERT(!mysql->options.ssl_ca || !mysql->options.ssl_ca[0]);
|
||||||
|
DBUG_ASSERT(!mysql->options.ssl_capath || !mysql->options.ssl_capath[0]);
|
||||||
|
DBUG_ASSERT(auth_plugin->hash_password_bin);
|
||||||
|
DBUG_ASSERT(mysql->passwd[0]);
|
||||||
|
|
||||||
|
parse_ok_packet(mysql, pkt_length); /* set mysql->info */
|
||||||
|
if (mysql->info && mysql->info[0] == '\1')
|
||||||
|
{
|
||||||
|
uchar fp[128], buf[1024], digest[256/8];
|
||||||
|
size_t buflen= sizeof(buf);
|
||||||
|
uint fplen= sizeof(fp);
|
||||||
|
char *hexsig= mysql->info + 1, hexdigest[sizeof(digest)*2+1];
|
||||||
|
X509 *cert= SSL_get_peer_certificate((SSL*)mysql->net.vio->ssl_arg);
|
||||||
|
X509_digest(cert, EVP_sha256(), fp, &fplen);
|
||||||
|
X509_free(cert);
|
||||||
|
auth_plugin->hash_password_bin(mysql, buf, &buflen);
|
||||||
|
my_sha256_multi(digest, buf, buflen, mysql->scramble, SCRAMBLE_LENGTH,
|
||||||
|
fp, fplen, NULL);
|
||||||
|
mysql->info= NULL; /* no need to confuse the client with binary info */
|
||||||
|
|
||||||
|
octet2hex(hexdigest, digest, sizeof(digest));
|
||||||
|
if (strcmp(hexdigest, hexsig) == 0)
|
||||||
|
DBUG_RETURN(0); /* phew. self-signed certificate is validated! */
|
||||||
|
}
|
||||||
|
|
||||||
|
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
|
||||||
|
ER(CR_SSL_CONNECTION_ERROR), mysql->tls_self_signed_error);
|
||||||
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2647,6 +2723,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
|
|
||||||
mysql->methods= &client_methods;
|
mysql->methods= &client_methods;
|
||||||
mysql->client_flag=0; /* For handshake */
|
mysql->client_flag=0; /* For handshake */
|
||||||
|
mysql->tls_self_signed_error= 0;
|
||||||
|
|
||||||
/* use default options */
|
/* use default options */
|
||||||
if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
|
if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
|
||||||
@ -3401,6 +3478,29 @@ void STDCALL mysql_close(MYSQL *mysql)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static my_bool parse_ok_packet(MYSQL *mysql, ulong length)
|
||||||
|
{
|
||||||
|
uchar *pos= mysql->net.read_pos + 1;
|
||||||
|
DBUG_ASSERT(pos[-1] == 0);
|
||||||
|
|
||||||
|
mysql->affected_rows= net_field_length_ll(&pos);
|
||||||
|
mysql->insert_id= net_field_length_ll(&pos);
|
||||||
|
if (protocol_41(mysql))
|
||||||
|
{
|
||||||
|
mysql->server_status=uint2korr(pos); pos+=2;
|
||||||
|
mysql->warning_count=uint2korr(pos); pos+=2;
|
||||||
|
}
|
||||||
|
else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
|
||||||
|
{
|
||||||
|
mysql->server_status=uint2korr(pos); pos+=2;
|
||||||
|
mysql->warning_count= 0;
|
||||||
|
}
|
||||||
|
if (pos < mysql->net.read_pos + length && net_field_length(&pos))
|
||||||
|
mysql->info=(char*) pos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static my_bool cli_read_query_result(MYSQL *mysql)
|
static my_bool cli_read_query_result(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
uchar *pos;
|
uchar *pos;
|
||||||
@ -3421,31 +3521,10 @@ static my_bool cli_read_query_result(MYSQL *mysql)
|
|||||||
#ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/
|
#ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/
|
||||||
get_info:
|
get_info:
|
||||||
#endif
|
#endif
|
||||||
pos=(uchar*) mysql->net.read_pos;
|
pos= mysql->net.read_pos;
|
||||||
if ((field_count= net_field_length(&pos)) == 0)
|
if ((field_count= net_field_length(&pos)) == 0)
|
||||||
{
|
DBUG_RETURN(parse_ok_packet(mysql, length));
|
||||||
mysql->affected_rows= net_field_length_ll(&pos);
|
|
||||||
mysql->insert_id= net_field_length_ll(&pos);
|
|
||||||
DBUG_PRINT("info",("affected_rows: %lu insert_id: %lu",
|
|
||||||
(ulong) mysql->affected_rows,
|
|
||||||
(ulong) mysql->insert_id));
|
|
||||||
if (protocol_41(mysql))
|
|
||||||
{
|
|
||||||
mysql->server_status=uint2korr(pos); pos+=2;
|
|
||||||
mysql->warning_count=uint2korr(pos); pos+=2;
|
|
||||||
}
|
|
||||||
else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
|
|
||||||
{
|
|
||||||
/* MySQL 4.0 protocol */
|
|
||||||
mysql->server_status=uint2korr(pos); pos+=2;
|
|
||||||
mysql->warning_count= 0;
|
|
||||||
}
|
|
||||||
DBUG_PRINT("info",("status: %u warning_count: %u",
|
|
||||||
mysql->server_status, mysql->warning_count));
|
|
||||||
if (pos < mysql->net.read_pos+length && net_field_length(&pos))
|
|
||||||
mysql->info=(char*) pos;
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
#ifdef MYSQL_CLIENT
|
#ifdef MYSQL_CLIENT
|
||||||
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
|
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
|
||||||
{
|
{
|
||||||
@ -4123,6 +4202,22 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
|
|||||||
DBUG_RETURN(CR_OK);
|
DBUG_RETURN(CR_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int native_password_auth_hash(MYSQL *mysql, uchar *out, size_t *out_length)
|
||||||
|
{
|
||||||
|
uchar hash_stage1[MY_SHA1_HASH_SIZE];
|
||||||
|
|
||||||
|
if (*out_length < MY_SHA1_HASH_SIZE)
|
||||||
|
return 1;
|
||||||
|
*out_length= MY_SHA1_HASH_SIZE;
|
||||||
|
|
||||||
|
my_sha1(hash_stage1, mysql->passwd, strlen(mysql->passwd));
|
||||||
|
my_sha1(out, (char*)hash_stage1, MY_SHA1_HASH_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
client authentication plugin that does old MySQL authentication
|
client authentication plugin that does old MySQL authentication
|
||||||
using an 8-byte (4.0-) scramble
|
using an 8-byte (4.0-) scramble
|
||||||
|
@ -171,9 +171,7 @@ add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
|
|||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin->interface_version < plugin_version[plugin->type] ||
|
if (plugin->interface_version >> 8 != plugin_version[plugin->type] >> 8)
|
||||||
(plugin->interface_version >> 8) >
|
|
||||||
(plugin_version[plugin->type] >> 8))
|
|
||||||
{
|
{
|
||||||
errmsg= "Incompatible client plugin interface";
|
errmsg= "Incompatible client plugin interface";
|
||||||
goto err1;
|
goto err1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user