1
0
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:
Georg Richter
2024-07-16 13:12:26 +02:00
parent 5386f1a3f2
commit 1287c901dc
33 changed files with 1950 additions and 431 deletions

View 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());
}