You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
TLS/SSL changes (major rework)
Peer certificate validation: Since version 3.4 peer certificate verification is enabled by default. It can be disabled via `mysql_optionsv`, using option MYSQL_OPT_SSL_VERIFY_SERVER_CERT: my_bool verify= 0; mysql_options(mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify); Self signed certificates If the client obtained a self signed peer certificate from MariaDB server the verification will fail, with the following exceptions: * If the connection between client and server is considered to be secure:, e.g. * a unix_socket is used for client server communication * hostname is localhost (Windows operating system), 127.0.0.1 or ::1 * a specified fingerprint matches the fingerprint of the peer certificate (see below) * a client can verify the certificate using account password, it's possible if * account has a password * authentication plugin is "secure without TLS", that is, one of mysql_native_password, ed25519 or parsec. Fingerprint verification of the peer certificate A fingerprint is a cryptographic hash (SHA-256, SHA-384 or SHA-512) of the peer certificate's binary data. Even if the fingerprint matches, an expired or revoked certificate will not be accepted. For security reasons support for MD5 and SHA1 has been removed. Technical details: ================== - Peer certificate verification call was removed from ma_tls_connect, instead it will be called directly after the handshake succeeded (my_auth.c) - mysql->net.tls_self_signed_error was replaced by mysql->net.tls_verify_status which contains the result of the peer certfificate verification: The verification status can be obtained with mariadb_get_infov using new parameter MARIADB_TLS_VERIFY_STATUS. unsigned int tls_verify_status; mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &tls_verify_status); The result is a combination of the following flags: MARIADB_TLS_VERIFY_OK 0 MARIADB_TLS_VERIFY_TRUST 1 MARIADB_TLS_VERIFY_HOST 2 MARIADB_TLS_VERIFY_PERIOD 4 MARIADB_TLS_VERIFY_FINGERPRINT 8 MARIADB_TLS_VERIFY_REVOKED 16 MARIADB_TLS_VERIFY_UNKNOWN 32 - GnuTLS peer certificate verification callback was removed and replaced by gnutls_verify_peers2() api function, so the peer certificate validation will happen after handshake. - OpenSSL implementation will no longer use SSL_verify_result to check the validity of the peer certificate. Instead a callback function will be called during the handshake, which collects all certificate validation errors. - If the peer certificate is not trusted, hostname verification will be skipped. - Testing Added new test tls, which implements a python based dummy server, which allows to set different certificates and TLS options. Please note. that tests are expected to fail, since the server doesn't support further steps like user authentication etc. after the handshake. Prerequisite for running the tls test is Python3.
This commit is contained in:
718
unittest/libmariadb/tls.c.in
Normal file
718
unittest/libmariadb/tls.c.in
Normal file
@@ -0,0 +1,718 @@
|
||||
/*
|
||||
Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
The MySQL Connector/C is licensed under the terms of the GPLv2
|
||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
||||
MySQL Connectors. There are special exceptions to the terms and
|
||||
conditions of the GPLv2 as it is applied to this software, see the
|
||||
FLOSS License Exception
|
||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "my_test.h"
|
||||
#include "ma_common.h"
|
||||
#include "ma_pvio.h"
|
||||
|
||||
#include <mysql/client_plugin.h>
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
#include <gnutls/abstract.h>
|
||||
#elif HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#define CHECK_TLS_FLAGS(m, flag, text) \
|
||||
{\
|
||||
unsigned int status;\
|
||||
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);\
|
||||
FAIL_IF(!(status & (flag)), (text));\
|
||||
}
|
||||
|
||||
#define CHECK_NO_TLS_FLAGS(m)\
|
||||
{\
|
||||
unsigned int status;\
|
||||
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);\
|
||||
FAIL_IF(status), "Expected MARIADB_TLS_VERIFY_OK");\
|
||||
}
|
||||
|
||||
my_bool auto_generated_cert= 0;
|
||||
my_bool ignore_self_signed= 0;
|
||||
|
||||
static char *tls_dummy_host= NULL;
|
||||
static int tls_dummy_port= 0;
|
||||
|
||||
static my_bool ignore_self_signed_cert_error(MYSQL *mysql)
|
||||
{
|
||||
const char *hostname= mysql->host;
|
||||
const char *local_host_names[]= {
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
On Unix, we consider TCP connections with "localhost"
|
||||
an insecure transport, for the single reason to run tests for
|
||||
insecure transport on CI.This is artificial, but should be ok.
|
||||
Default client connections use unix sockets anyway, so it
|
||||
would not hurt much.
|
||||
|
||||
On Windows, the situation is quite different.
|
||||
Default connections type is TCP, default host name is "localhost",
|
||||
non-password plugin gssapi is common (every installation)
|
||||
In this environment, there would be a lot of faux/disruptive
|
||||
"self-signed certificates" errors there. Thus, "localhost" TCP
|
||||
needs to be considered secure transport.
|
||||
*/
|
||||
"localhost",
|
||||
#endif
|
||||
"127.0.0.1", "::1", NULL};
|
||||
int i;
|
||||
|
||||
/* if CA or CAPath was specified, we don't ignore self signed
|
||||
certificates */
|
||||
if (mysql->options.ssl_ca ||
|
||||
mysql->options.ssl_capath)
|
||||
return FALSE;
|
||||
|
||||
if (mysql->net.pvio->type != PVIO_TYPE_SOCKET)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (!hostname)
|
||||
return FALSE;
|
||||
for (i= 0; local_host_names[i]; i++)
|
||||
{
|
||||
if (strcmp(hostname, local_host_names[i]) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int test_start_tls_server(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
#ifdef WIN32
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
char szCmdline[1024];
|
||||
|
||||
snprintf(szCmdline, sizeof(szCmdline), "%s tls_server.py --host=%s --port=%d", "@Python3_EXECUTABLE@", tls_dummy_host, tls_dummy_port);
|
||||
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
GetStartupInfo(&si);
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.wShowWindow = SW_SHOWDEFAULT;
|
||||
|
||||
if( !CreateProcessA(NULL,
|
||||
szCmdline,
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
CREATE_NEW_CONSOLE,
|
||||
NULL,
|
||||
NULL,
|
||||
&si,
|
||||
&pi)
|
||||
)
|
||||
{
|
||||
diag("couldn't start tls_server. Error %d", GetLastError());
|
||||
return FAIL;
|
||||
}
|
||||
#else
|
||||
pid_t tls_server_pid;
|
||||
|
||||
if (!(tls_server_pid= fork()))
|
||||
{
|
||||
char hostname[1024], port[128];
|
||||
|
||||
snprintf(hostname, sizeof(hostname), "--host=%s", tls_dummy_host);
|
||||
snprintf(port, sizeof(port), "--port=%d", tls_dummy_port);
|
||||
execlp("@Python3_EXECUTABLE@", "@Python3_EXECUTABLE@", "tls_server.py", hostname, port, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
sleep(10);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int set_tls_dummy_options(const char *options)
|
||||
{
|
||||
MA_PVIO_CINFO cinfo;
|
||||
MARIADB_PVIO *pvio;
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
char buffer[1024];
|
||||
size_t len;
|
||||
|
||||
cinfo.type= PVIO_TYPE_SOCKET;
|
||||
cinfo.host= tls_dummy_host;
|
||||
cinfo.port= tls_dummy_port;
|
||||
cinfo.mysql = mysql;
|
||||
|
||||
if (!(pvio= ma_pvio_init(&cinfo)))
|
||||
{
|
||||
diag("pvio_init failed");
|
||||
return 1;
|
||||
}
|
||||
if (ma_pvio_connect(pvio, &cinfo))
|
||||
{
|
||||
diag("connect failed: %s", mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(len= ma_pvio_read(pvio, (uchar *)buffer, sizeof(buffer))))
|
||||
{
|
||||
diag("Error reading server packet");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!ma_pvio_write(pvio, (uchar *)options, strlen(options)))
|
||||
{
|
||||
diag("Error writing configuration");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ma_pvio_close(pvio);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int test_init(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
my_bool verify= 0;
|
||||
int rc;
|
||||
int ret= FAIL;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
char query[1024];
|
||||
|
||||
diag("test_init");
|
||||
|
||||
/* Force use of TLS */
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Don't verify peer certificate */
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
|
||||
|
||||
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
rc= mysql_query(mysql, "SELECT @@ssl_cert");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
if ((result= mysql_store_result(mysql)))
|
||||
{
|
||||
row= mysql_fetch_row(result);
|
||||
auto_generated_cert = (row[0] == NULL);
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
diag("autogenerated: %d", auto_generated_cert);
|
||||
ignore_self_signed= ignore_self_signed_cert_error(mysql);
|
||||
diag("ignore self signed certificates: %d", ignore_self_signed);
|
||||
|
||||
ret= OK;
|
||||
|
||||
sprintf(query, "CREATE OR REPLACE USER 'tls_user1'@'%s' IDENTIFIED BY 'tls_password'", hostname);
|
||||
rc= mysql_query(mysql, query);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
sprintf(query, "CREATE OR REPLACE USER 'tls_user2'@'%s'", hostname);
|
||||
rc= mysql_query(mysql, query);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
mysql_close(mysql);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_no_cert_check(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
my_bool verify= 0;
|
||||
|
||||
/* Force use of TLS */
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Don't verify peer certificate */
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
|
||||
|
||||
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
FAIL_IF(!mysql_get_ssl_cipher(mysql), "No TLS connection");
|
||||
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_ca_cert_check(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
int rc= FAIL;
|
||||
|
||||
#ifdef HAVE_SCHANNEL
|
||||
diag("Not supported by schannel");
|
||||
return SKIP;
|
||||
#endif
|
||||
|
||||
if (ignore_self_signed)
|
||||
{
|
||||
diag("Test doesn't work on trusted connection");
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
/* Force use of TLS with faked ca, which contains the server
|
||||
certificate */
|
||||
mysql_ssl_set(mysql, NULL, NULL, "./ca_cert.pem", NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0))
|
||||
{
|
||||
if (auto_generated_cert)
|
||||
{
|
||||
diag("expected hostname mismatch for autogenerated certificate");
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (auto_generated_cert)
|
||||
{
|
||||
rc= OK;
|
||||
goto end;
|
||||
}
|
||||
diag("Error: %s", mysql_error(mysql));
|
||||
goto end;
|
||||
}
|
||||
|
||||
FAIL_IF(!mysql_get_ssl_cipher(mysql), "No TLS connection");
|
||||
rc= OK;
|
||||
end:
|
||||
mysql_close(mysql);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_fp(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
unsigned int hash_size[3] = {256, 384, 512};
|
||||
int i;
|
||||
my_bool verify= 0;
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
|
||||
|
||||
/* Force use of TLS */
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Don't verify peer certificate */
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
|
||||
|
||||
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 1), mysql_error(my));
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
MYSQL *mysql1= mysql_init(NULL);
|
||||
MARIADB_X509_INFO *info;
|
||||
|
||||
diag("testing SHA%d fingerprint", hash_size[i]);
|
||||
|
||||
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info, hash_size[i]);
|
||||
|
||||
mysql_optionsv(mysql1, MARIADB_OPT_SSL_FP, info->fingerprint);
|
||||
FAIL_IF(!my_test_connect(mysql1, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
FAIL_IF(!mysql_get_ssl_cipher(mysql), "No TLS connection");
|
||||
mysql_close(mysql1);
|
||||
}
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_fp_colon(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
unsigned int hash_size[3] = {256, 384, 512};
|
||||
int i;
|
||||
my_bool verify= 0;
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
char fp[200];
|
||||
|
||||
|
||||
/* Force use of TLS */
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Don't verify peer certificate */
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
|
||||
|
||||
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
MYSQL *mysql1= mysql_init(NULL);
|
||||
MARIADB_X509_INFO *info;
|
||||
char *p= &fp[0];
|
||||
size_t j;
|
||||
|
||||
diag("testing SHA%d fingerprint with colons", hash_size[i]);
|
||||
|
||||
memset(fp, 0, sizeof(fp));
|
||||
|
||||
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info, hash_size[i]);
|
||||
|
||||
for (j=0; j < strlen(info->fingerprint) / 2; j++)
|
||||
{
|
||||
memcpy(p, info->fingerprint + j * 2, 2);
|
||||
p+= 2;
|
||||
*p++= ':';
|
||||
}
|
||||
p--;
|
||||
*p= 0;
|
||||
|
||||
|
||||
diag ("fp: %s", fp);
|
||||
mysql_optionsv(mysql1, MARIADB_OPT_SSL_FP, fp);
|
||||
FAIL_IF(!my_test_connect(mysql1, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
FAIL_IF(!mysql_get_ssl_cipher(mysql), "No TLS connection");
|
||||
mysql_close(mysql1);
|
||||
}
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int test_peer_cert_info_fp(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
my_bool verify= 0;
|
||||
MARIADB_X509_INFO *info;
|
||||
char old_fp[129] = {0};
|
||||
int i;
|
||||
unsigned int hash_size[3] = {256, 384, 512};
|
||||
|
||||
/* Force use of TLS */
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Don't verify peer certificate */
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
|
||||
|
||||
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0), mysql_error(my));
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info, hash_size[i]);
|
||||
FAIL_IF(!info->version, "Wrong certificate version=0");
|
||||
|
||||
FAIL_IF(!strcmp(old_fp, info->fingerprint), "Fingerprint was not updated");
|
||||
if (strlen(info->fingerprint) != hash_size[i] / 4)
|
||||
{
|
||||
diag("Got fingerprint length %zu, expected %u", strlen(info->fingerprint), hash_size[i] / 4);
|
||||
return FAIL;
|
||||
}
|
||||
strcpy(old_fp, info->fingerprint);
|
||||
}
|
||||
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_fp_garbage(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
char fp[129];
|
||||
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* 1) use non hex chars */
|
||||
strcpy(fp, "IJKLMNOPQRSTUVWXYZABCDEXXXXXX67IJKLMNOPQRSTUVWXYZABCDEXXXXXX679X");
|
||||
if (mysql_optionsv(mysql, MARIADB_OPT_SSL_FP, fp))
|
||||
return FAIL;
|
||||
|
||||
if (my_test_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0, 0))
|
||||
{
|
||||
diag("Error expected");
|
||||
diag("%s", mysql_get_ssl_cipher(mysql));
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_FINGERPRINT, "Fingerprint verification flag not set");
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_pw_check(MYSQL *my)
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
int rc;
|
||||
my_bool local_safe_connection= ignore_self_signed_cert_error(my);
|
||||
char query[1024];
|
||||
int ret= FAIL;
|
||||
|
||||
/* connect with pasword */
|
||||
sprintf(query, "CREATE OR REPLACE USER '%s'@'%s' IDENTIFIED BY '%s'", "tlsuser", this_host, "mypw");
|
||||
rc= mysql_query(my, query);
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
diag("expected to pass with self signed");
|
||||
if (!my_test_connect(mysql, hostname, "tlsuser", "mypw", NULL, 0, NULL, 0, 0))
|
||||
{
|
||||
diag("Error (password + self signed)");
|
||||
goto end;
|
||||
}
|
||||
diag("ok");
|
||||
|
||||
mysql_close(mysql);
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
/* connect without pasword */
|
||||
if (!local_safe_connection)
|
||||
{
|
||||
sprintf(query, "CREATE OR REPLACE USER '%s'@'%s'", "tlsuser", this_host);
|
||||
rc= mysql_query(my, query);
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
if (my_test_connect(mysql, hostname, "tlsuser", NULL, NULL, 0, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since no password was specified");
|
||||
goto end;
|
||||
}
|
||||
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Not trusted flag not set")
|
||||
|
||||
mysql_close(mysql);
|
||||
mysql = mysql_init(NULL);
|
||||
mysql_optionsv(mysql, MARIADB_OPT_RESTRICTED_AUTH, "mysql_native_password, mysql_old_password");
|
||||
|
||||
diag("expected to fail with old_password plugin");
|
||||
/* Test with an authentication plugin, which doesn't support hashing */
|
||||
sprintf(query, "CREATE OR REPLACE USER '%s'@'%s' IDENTIFIED VIA mysql_old_password USING '7c786c222596437b'", "tlsuser", this_host);
|
||||
rc= mysql_query(my, query);
|
||||
check_mysql_rc(rc, my);
|
||||
rc= mysql_query(my, "SET GLOBAL secure_auth=0");
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
if (my_test_connect(mysql, hostname, "tlsuser", "foo", NULL, 0, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since old_password was specified");
|
||||
goto end;
|
||||
}
|
||||
diag("ok");
|
||||
}
|
||||
|
||||
ret= OK;
|
||||
end:
|
||||
mysql_close(mysql);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_cert_expired(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
int ret= OK;
|
||||
MYSQL *mysql;
|
||||
|
||||
/* Set validity in future */
|
||||
if (set_tls_dummy_options("CMD:create_new=True validityStartInSeconds=10000 validityEndInSeconds=2000"))
|
||||
{
|
||||
diag("Error when setting TLS options");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since cert is not valid yet");
|
||||
return FAIL;
|
||||
}
|
||||
mysql_close(mysql);
|
||||
|
||||
/* Set cert expired */
|
||||
if (set_tls_dummy_options("CMD:create_new=True validityStartInSeconds=-20000 validityEndInSeconds=-10000"))
|
||||
{
|
||||
diag("Error when setting TLS options");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since cert is not valid yet");
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_PERIOD, "NotBefore/NotAfter flag not set")
|
||||
mysql_close(mysql);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_wrong_ca(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
|
||||
mysql_ssl_set(mysql, NULL, NULL, "selfsigned.pem", NULL, NULL);
|
||||
if (my_test_connect(mysql, hostname, "tlsuser", "foo", NULL, 0, NULL, 0, 0))
|
||||
{
|
||||
diag("self signed error expected");
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Not trusted flag not set")
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_crl(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql;
|
||||
|
||||
/* Set validity in future */
|
||||
if (set_tls_dummy_options("CMD:KEY_FILE='./certs/server-key.pem' CERT_FILE='./certs/server-cert.pem'"))
|
||||
{
|
||||
diag("Error when setting TLS options");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_CRL, "./certs/server-cert.crl");
|
||||
mysql_ssl_set(mysql, NULL, NULL, "./certs/cacert.pem", NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since cert revoked");
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_REVOKED, "Revocation flag not set")
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_crl_with_fp(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql;
|
||||
/* hardcoded: openssl x509 -noout -fingerprint -sha256 -inform pem -in certs/server-cert.pem */
|
||||
const char *fp= "4B:EE:BB:12:6D:30:1A:B2:2A:4A:F8:6D:82:7F:63:44:1F:8F:F4:6B:D3:F2:CA:68:0B:D5:E3:5D:1C:47:A7:16";
|
||||
|
||||
/* Set validity in future */
|
||||
if (set_tls_dummy_options("CMD:KEY_FILE='./certs/server-key.pem' CERT_FILE='./certs/server-cert.pem'"))
|
||||
{
|
||||
diag("Error when setting TLS options");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
mysql_optionsv(mysql, MARIADB_OPT_SSL_FP, fp);
|
||||
|
||||
mysql_optionsv(mysql, MYSQL_OPT_SSL_CRL, "./certs/server-cert.crl");
|
||||
mysql_ssl_set(mysql, NULL, NULL, "./certs/cacert.pem", NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since cert revoked");
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_REVOKED, "Revocation flag not set")
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int test_wrong_hostname(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql;
|
||||
|
||||
/* Set validity in future */
|
||||
if (set_tls_dummy_options("CMD:create_new=True"))
|
||||
{
|
||||
diag("Error when setting TLS options");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
mysql_ssl_set(mysql, NULL, NULL, "./selfsigned.pem", NULL, NULL);
|
||||
|
||||
if (my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||
{
|
||||
diag("Error expected since hostname doesn't match");
|
||||
return FAIL;
|
||||
}
|
||||
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_HOST, "Host name validation flag not set")
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int stop_tls_server(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
if (set_tls_dummy_options("QUIT"))
|
||||
{
|
||||
diag("Error when shutting down tls dummy server");
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
/* Don't add test above, test_init needs to be run first */
|
||||
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
/* Here you can add more tests */
|
||||
{"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_ca_cert_check", test_ca_cert_check, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_fp_garbage", test_fp_garbage, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_peer_cert_info_fp", test_peer_cert_info_fp, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_no_cert_check", test_no_cert_check, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_fp", test_fp, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_fp_colon", test_fp_colon, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_wrong_ca", test_wrong_ca, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_wrong_hostname", test_wrong_hostname, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_crl", test_crl, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_crl_with_fp", test_crl_with_fp, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"stop_tls_server", stop_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{NULL, NULL, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *dummy_port;
|
||||
|
||||
if (argc > 1)
|
||||
get_options(argc, argv);
|
||||
|
||||
get_envvars();
|
||||
|
||||
if (!(tls_dummy_host= getenv("MARIADB_TLS_DUMMY_HOST")))
|
||||
tls_dummy_host= (char *)"127.0.0.1";
|
||||
if ((dummy_port= getenv("MARIADB_TLS_DUMMY_PORT")))
|
||||
tls_dummy_port= atoi(dummy_port);
|
||||
if (!tls_dummy_port)
|
||||
tls_dummy_port= 50000;
|
||||
|
||||
|
||||
run_tests(my_tests);
|
||||
|
||||
return(exit_status());
|
||||
}
|
Reference in New Issue
Block a user