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

@@ -7,6 +7,16 @@ cache:
directories:
- $HOME/docker
before_install:
- |-
if [ -z "$server_branch" ] ; then
case $TRAVIS_OS_NAME in
windows)
choco install python --version=3.12.0
;;
esac
fi
env:
global: local=0 DB=testc CLEAR_TEXT=0

View File

@@ -37,7 +37,7 @@ SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(CPACK_PACKAGE_VERSION_MAJOR 3)
SET(CPACK_PACKAGE_VERSION_MINOR 4)
SET(CPACK_PACKAGE_VERSION_PATCH 0)
SET(CPACK_PACKAGE_VERSION_PATCH 1)
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 +
${CPACK_PACKAGE_VERSION_MINOR} * 100 +

View File

@@ -131,15 +131,9 @@ typedef struct st_mariadb_field_extension
MARIADB_CONST_STRING metadata[MARIADB_FIELD_ATTR_LAST+1]; /* 10.5 */
} MA_FIELD_EXTENSION;
#if defined(HAVE_SCHANNEL) || defined(HAVE_GNUTLS)
#define reset_tls_self_signed_error(mysql) \
#ifdef HAVE_TLS
#define reset_tls_error(mysql) \
do { \
free((char*)mysql->net.tls_self_signed_error); \
mysql->net.tls_self_signed_error= 0; \
} while(0)
#else
#define reset_tls_self_signed_error(mysql) \
do { \
mysql->net.tls_self_signed_error= 0; \
mysql->net.tls_verify_status= 0; \
} while(0)
#endif

View File

@@ -21,6 +21,12 @@ enum enum_pvio_tls_type {
#define PROTOCOL_MAX PROTOCOL_TLS_1_3
#define TLS_VERSION_LENGTH 64
#define have_fingerprint(m) \
((m)->options.extension) && \
(((m)->options.extension->tls_fp && (m)->options.extension->tls_fp[0]) ||\
((m)->options.extension->tls_fp_list && (m)->options.extension->tls_fp_list[0]))
extern char tls_library_version[TLS_VERSION_LENGTH];
typedef struct st_ma_pvio_tls {
@@ -111,11 +117,12 @@ my_bool ma_tls_close(MARIADB_TLS *ctls);
validation check of server certificate
Parameter:
MARIADB_TLS MariaDB SSL container
flags verification flags
Returns:
ß success
0 success
1 error
*/
int ma_tls_verify_server_cert(MARIADB_TLS *ctls);
int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags);
/* ma_tls_get_cipher
returns cipher for current ssl connection
@@ -134,6 +141,7 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ssl);
hash_type hash_type as defined in ma_hash.h
fp buffer for fingerprint
fp_len buffer length
my_bool verify_period
Returns:
actual size of finger print
@@ -150,7 +158,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp
int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls);
int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls);
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls);
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls, unsigned int size);
void ma_tls_set_connection(MYSQL *mysql);
/* Function prototypes */
@@ -159,12 +167,12 @@ my_bool ma_pvio_tls_connect(MARIADB_TLS *ctls);
ssize_t ma_pvio_tls_read(MARIADB_TLS *ctls, const uchar *buffer, size_t length);
ssize_t ma_pvio_tls_write(MARIADB_TLS *ctls, const uchar *buffer, size_t length);
my_bool ma_pvio_tls_close(MARIADB_TLS *ctls);
int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls);
int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags);
const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls);
my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list);
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
void ma_pvio_tls_set_connection(MYSQL *mysql);
void ma_pvio_tls_end();
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls);
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls, unsigned int size);
#endif /* _ma_tls_h_ */

View File

@@ -297,10 +297,10 @@ typedef struct st_net {
unsigned char reading_or_writing;
char save_char;
char unused_1;
my_bool unused_2;
my_bool tls_verify_status;
my_bool compress;
my_bool unused_3;
const char *tls_self_signed_error;
my_bool unused_2;
char *unused_3;
unsigned int last_errno;
unsigned char error;
my_bool unused_5;

View File

@@ -300,6 +300,7 @@ extern const char *SQLSTATE_UNKNOWN;
MARIADB_CONNECTION_BYTES_READ,
MARIADB_CONNECTION_BYTES_SENT,
MARIADB_TLS_PEER_CERT_INFO,
MARIADB_TLS_VERIFY_STATUS
};
enum mysql_status { MYSQL_STATUS_READY,
@@ -448,6 +449,16 @@ typedef struct st_mysql_time
#define MYSQL_WAIT_EXCEPT 4
#define MYSQL_WAIT_TIMEOUT 8
#define MARIADB_TLS_VERIFY_OK 0
#define MARIADB_TLS_VERIFY_TRUST 1
#define MARIADB_TLS_VERIFY_HOST 2
#define MARIADB_TLS_VERIFY_PERIOD 4
#define MARIADB_TLS_VERIFY_FINGERPRINT 8
#define MARIADB_TLS_VERIFY_REVOKED 16
#define MARIADB_TLS_VERIFY_UNKNOWN 32
#define MARIADB_TLS_VERIFY_ERROR 128 /* last */
typedef struct character_set
{
unsigned int number; /* character set number */
@@ -497,7 +508,7 @@ typedef struct
int version;
char *issuer;
char *subject;
char fingerprint[65];
char fingerprint[129];
struct tm not_before;
struct tm not_after;
} MARIADB_X509_INFO;

View File

@@ -522,47 +522,6 @@ my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
/* }}} */
#ifdef HAVE_TLS
/**
Checks if self-signed certificate error should be ignored.
*/
static my_bool ignore_self_signed_cert_error(MARIADB_PVIO *pvio)
{
const char *hostname= pvio->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 (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;
}
/* {{{ my_bool ma_pvio_start_ssl */
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
@@ -580,32 +539,6 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
pvio->ctls= NULL;
return 1;
}
/* default behaviour:
1. peer certificate verification
2. verify CN (requires option ssl_verify_check)
3. verrify finger print
*/
if (!pvio->mysql->options.extension->tls_allow_invalid_server_cert &&
!pvio->mysql->net.tls_self_signed_error &&
ma_pvio_tls_verify_server_cert(pvio->ctls))
return 1;
if (pvio->mysql->options.extension &&
((pvio->mysql->options.extension->tls_fp && pvio->mysql->options.extension->tls_fp[0]) ||
(pvio->mysql->options.extension->tls_fp_list && pvio->mysql->options.extension->tls_fp_list[0])))
{
if (ma_pvio_tls_check_fp(pvio->ctls,
pvio->mysql->options.extension->tls_fp,
pvio->mysql->options.extension->tls_fp_list))
return 1;
reset_tls_self_signed_error(pvio->mysql); // validated
return 0;
}
if (pvio->mysql->net.tls_self_signed_error && ignore_self_signed_cert_error(pvio))
reset_tls_self_signed_error(pvio->mysql);
return 0;
}
/* }}} */

View File

@@ -103,9 +103,54 @@ my_bool ma_pvio_tls_close(MARIADB_TLS *ctls)
return ma_tls_close(ctls);
}
int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls)
int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
{
return ma_tls_verify_server_cert(ctls);
MYSQL *mysql;
int rc;
if (!ctls || !ctls->pvio || !ctls->pvio->mysql)
return 0;
mysql= ctls->pvio->mysql;
/* Skip peer certificate verification */
if (ctls->pvio->mysql->options.extension->tls_allow_invalid_server_cert)
{
return 0;
}
rc= ma_tls_verify_server_cert(ctls, flags);
/* Set error messages */
if (!mysql->net.last_errno)
{
if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_PERIOD)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Certificate not yet valid or expired");
else if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_FINGERPRINT)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Fingerprint validation of peer certificate failed");
else if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_REVOKED)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Certificate revoked");
else if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_HOST)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Hostname verification failed");
else if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_UNKNOWN)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Peer certificate verification failed");
else if (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_TRUST)
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Peer certificate is not trusted");
}
return rc;
}
const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls)
@@ -150,8 +195,7 @@ static signed char ma_hex2int(char c)
static my_bool ma_pvio_tls_compare_fp(MARIADB_TLS *ctls,
const char *cert_fp,
unsigned int cert_fp_len
)
unsigned int cert_fp_len)
{
const char fp[EVP_MAX_MD_SIZE];
unsigned int fp_len= EVP_MAX_MD_SIZE;
@@ -206,8 +250,6 @@ static my_bool ma_pvio_tls_compare_fp(MARIADB_TLS *ctls,
signed char d1, d2;
if (*p == ':')
p++;
if (p - cert_fp > (int)fp_len - 1)
return 1;
if ((d1 = ma_hex2int(*p)) == -1 ||
(d2 = ma_hex2int(*(p + 1))) == -1 ||
(char)(d1 * 16 + d2) != *c)
@@ -270,8 +312,8 @@ void ma_pvio_tls_set_connection(MYSQL *mysql)
ma_tls_set_connection(mysql);
}
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls)
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls, unsigned int size)
{
return ma_tls_get_peer_cert_info(ctls);
return ma_tls_get_peer_cert_info(ctls, size);
}
#endif /* HAVE_TLS */

View File

@@ -1295,7 +1295,7 @@ mysql_init(MYSQL *mysql)
}
else
{
memset((char*) (mysql), 0, sizeof(*(mysql)));
memset(mysql, 0, sizeof(MYSQL));
mysql->net.pvio= 0;
mysql->free_me= 0;
mysql->net.extension= 0;
@@ -1462,7 +1462,7 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
if (!mysql->options.extension || !mysql->options.extension->status_callback)
mysql_optionsv(mysql, MARIADB_OPT_STATUS_CALLBACK, NULL, NULL);
reset_tls_self_signed_error(mysql);
reset_tls_error(mysql);
/* if host contains a semicolon, we need to parse connection string */
if (host && strchr(host, ';'))
@@ -2468,7 +2468,7 @@ mysql_close(MYSQL *mysql)
mysql_close_memory(mysql);
mysql_close_options(mysql);
ma_clear_session_state(mysql);
reset_tls_self_signed_error(mysql);
reset_tls_error(mysql);
if (mysql->net.extension)
{
@@ -4542,12 +4542,18 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...
case MARIADB_TLS_PEER_CERT_INFO:
if (mysql->net.pvio->ctls)
{
if (!ma_pvio_tls_get_peer_cert_info(mysql->net.pvio->ctls))
unsigned int size;
size= va_arg(ap, unsigned int);
if (!ma_pvio_tls_get_peer_cert_info(mysql->net.pvio->ctls, size))
*((MARIADB_X509_INFO **)arg)= (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info;
return 0;
}
*((MARIADB_X509_INFO **)arg)= NULL;
break;
case MARIADB_TLS_VERIFY_STATUS:
*((unsigned int *)arg)= (unsigned int)mysql->net.tls_verify_status;
break;
#endif
case MARIADB_MAX_ALLOWED_PACKET:
*((size_t *)arg)= (size_t)max_allowed_packet;

View File

@@ -33,6 +33,7 @@
#include <ma_tls.h>
#include <mariadb_async.h>
#include <ma_context.h>
#include <ma_crypt.h>
pthread_mutex_t LOCK_gnutls_config;
@@ -46,8 +47,6 @@ enum ma_pem_type {
MA_TLS_PEM_CRL
};
static int my_verify_callback(gnutls_session_t ssl);
char tls_library_version[TLS_VERSION_LENGTH];
struct st_cipher_map {
@@ -1069,8 +1068,10 @@ static int ma_tls_set_certs(MYSQL *mysql,
ssl_error= gnutls_certificate_set_x509_crl_file(ctx,
mysql->options.extension->ssl_crl, GNUTLS_X509_FMT_PEM);
if (ssl_error < 0)
{
goto error;
}
}
if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
{
@@ -1079,9 +1080,6 @@ static int ma_tls_set_certs(MYSQL *mysql,
goto error;
}
gnutls_certificate_set_verify_function(ctx,
my_verify_callback);
if (mysql->options.ssl_key || mysql->options.ssl_cert)
{
char *keyfile= mysql->options.ssl_key;
@@ -1242,11 +1240,56 @@ ssize_t ma_tls_write_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t lengt
}
}
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
static gnutls_x509_crt_t ma_get_cert(MARIADB_TLS *ctls)
{
MYSQL *mysql;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
gnutls_x509_crt_t cert;
if (!ctls || !ctls->ssl)
return 0;
mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
if (cert_list == NULL)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Unable to get server certificate");
return NULL;
}
/* Check expiration */
gnutls_x509_crt_init(&cert);
if (!gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER))
return cert;
return NULL;
}
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls, uint hash_size)
{
gnutls_session_t ssl;
unsigned int list_size= 0;
unsigned int hash_alg;
char fp[129];
switch (hash_size) {
case 0:
case 256:
hash_alg= MA_HASH_SHA256;
break;
case 384:
hash_alg= MA_HASH_SHA384;
break;
case 512:
hash_alg= MA_HASH_SHA512;
break;
default:
return 1;
}
if (!ctls || !ctls->ssl)
return 1;
@@ -1254,21 +1297,14 @@ unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
if (!(ssl = (gnutls_session_t)ctls->ssl))
return 1;
if (ctls->cert_info.version)
return 0; /* already loaded */
/* retrieve peer certificate information */
if ((cert_list= gnutls_certificate_get_peers(ssl, &list_size)))
if (!ctls->cert_info.version)
{
gnutls_x509_crt_t cert;
gnutls_x509_crt_init(&cert);
memset(&ctls->cert_info, 0, sizeof(MARIADB_X509_INFO));
if (!gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER))
if ((cert = ma_get_cert(ctls)))
{
size_t len= 0;
char fp[33];
time_t notBefore, notAfter;
ctls->cert_info.version= gnutls_x509_crt_get_version(cert);
@@ -1287,13 +1323,12 @@ unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
notAfter= gnutls_x509_crt_get_expiration_time(cert);
memcpy(&ctls->cert_info.not_after, gmtime(&notAfter), sizeof(struct tm));
ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, sizeof(fp));
mysql_hex_string(ctls->cert_info.fingerprint, fp, 32);
}
gnutls_x509_crt_deinit(cert);
return 0;
}
return 1;
}
ma_tls_get_finger_print(ctls, hash_alg, fp, sizeof(fp));
mysql_hex_string(ctls->cert_info.fingerprint, fp, ma_hash_digest_size(hash_alg));
return 0;
}
@@ -1383,10 +1418,84 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
return 0;
}
int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused)))
static void set_verification_error(MYSQL *mysql, int status)
{
/* server verification is already handled before during handshake */
return 0;
gnutls_session_t ssl;
gnutls_datum_t out;
int type;
if (!(ssl = (gnutls_session_t)mysql->net.pvio->ctls->ssl))
return;
type= gnutls_certificate_type_get(ssl);
gnutls_certificate_verification_status_print(status, type, &out, 0);
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), out.data);
gnutls_free(out.data);
}
int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
{
unsigned int status= 0;
gnutls_session_t ssl;
MYSQL *mysql;
if (!ctls || !(ssl= ctls->ssl) || !(mysql= (MYSQL *)gnutls_session_get_ptr(ssl)))
return 1;
CLEAR_CLIENT_ERROR(mysql);
if (flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_FINGERPRINT;
goto end;
}
}
if (gnutls_certificate_verify_peers2(ssl, &status))
return GNUTLS_E_CERTIFICATE_ERROR;
if (status)
{
set_verification_error(mysql, status);
if (status & GNUTLS_CERT_REVOKED)
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_REVOKED;
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
if (flags & MARIADB_TLS_VERIFY_TRUST)
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_TRUST;
if ((status & GNUTLS_CERT_NOT_ACTIVATED) || (status & GNUTLS_CERT_EXPIRED))
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_PERIOD;
}
if (!status && (flags & MARIADB_TLS_VERIFY_HOST))
{
gnutls_x509_crt_t cert= ma_get_cert(ctls);
int rc;
if (!cert)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Can't access peer certificate");
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto end;
}
rc= gnutls_x509_crt_check_hostname2(cert, mysql->host, flags);
gnutls_x509_crt_deinit(cert);
if (!rc)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Certificate subject name doesn't match specified hostname");
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
}
}
end:
return (mysql->net.tls_verify_status > 0);
}
const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
@@ -1404,65 +1513,13 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
return openssl_cipher_name(kx, cipher, mac);
}
static int my_verify_callback(gnutls_session_t ssl)
{
unsigned int status= 0;
MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
CLEAR_CLIENT_ERROR(mysql);
if (!mysql->options.extension->tls_allow_invalid_server_cert)
{
const char *hostname= mysql->host;
if (gnutls_certificate_verify_peers3 (ssl, hostname, &status) < 0)
return GNUTLS_E_CERTIFICATE_ERROR;
} else {
if (gnutls_certificate_verify_peers2 (ssl, &status) < 0)
return GNUTLS_E_CERTIFICATE_ERROR;
}
if (status & GNUTLS_CERT_INVALID)
{
gnutls_datum_t out;
int type;
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
{
/* accept self signed certificates if we don't have to verify server cert */
if (mysql->options.extension->tls_allow_invalid_server_cert)
return 0;
/* postpone the error for self signed certificates if CA isn't set */
if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
{
type= gnutls_certificate_type_get(ssl);
gnutls_certificate_verification_status_print(status, type, &out, 0);
mysql->net.tls_self_signed_error= (char*)out.data;
return 0;
}
}
/* gnutls default error message "certificate validation failed" isn't very
descriptive, so we provide more information about the error here */
type= gnutls_certificate_type_get(ssl);
gnutls_certificate_verification_status_print(status, type, &out, 0);
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), out.data);
gnutls_free(out.data);
return GNUTLS_E_CERTIFICATE_ERROR;
}
return 0;
}
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
{
MYSQL *mysql;
size_t fp_len= len;
gnutls_digest_algorithm_t hash_alg;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
gnutls_digest_algorithm_t hash_alg;
if (!ctls || !ctls->ssl)
return 0;
@@ -1471,12 +1528,14 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp
switch (hash_type)
{
#ifdef WEAK_HASH
case MA_HASH_SHA1:
hash_alg = GNUTLS_DIG_SHA1;
break;
case MA_HASH_SHA224:
hash_alg = GNUTLS_DIG_SHA224;
break;
#endif
case MA_HASH_SHA256:
hash_alg = GNUTLS_DIG_SHA256;
break;

View File

@@ -482,10 +482,10 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
}
/* }}} */
#include "win32_errmsg.h"
my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
unsigned int ma_schannel_verify_certs(MARIADB_TLS *ctls, unsigned int verify_flags)
{
SECURITY_STATUS status;
unsigned int verify_status = MARIADB_TLS_VERIFY_ERROR;
MARIADB_PVIO *pvio= ctls->pvio;
MYSQL *mysql= pvio->mysql;
SC_CTX *sctx = (SC_CTX *)ctls->ssl;
@@ -498,6 +498,12 @@ my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
HCERTSTORE store= NULL;
int ret= 0;
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
return MARIADB_TLS_VERIFY_FINGERPRINT;
}
status = schannel_create_store(ca_file, ca_path, crl_file, crl_path, &store, errmsg, sizeof(errmsg));
if(status)
goto end;
@@ -513,33 +519,48 @@ my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
status = schannel_verify_server_certificate(
pServerCert,
store,
crl_file != 0 || crl_path != 0,
mysql->host,
verify_server_name,
verify_flags,
errmsg, sizeof(errmsg));
if (status)
goto end;
verify_status= MARIADB_TLS_VERIFY_OK;
ret= 1;
end:
if (!ret)
{
/* postpone the error for self signed certificates if CA isn't set */
if (status == CERT_E_UNTRUSTEDROOT && !ca_file && !ca_path)
switch (status) {
case CERT_E_UNTRUSTEDROOT:
if ((verify_flags & MARIADB_TLS_VERIFY_TRUST))
{
mysql->net.tls_self_signed_error= strdup(errmsg);
ret= 1;
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_TRUST;
}
break;
case CERT_E_EXPIRED:
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_PERIOD;
break;
case CRYPT_E_REVOKED:
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_REVOKED;
break;
case CERT_E_INVALID_NAME:
case CERT_E_CN_NO_MATCH:
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
break;
default:
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_ERROR;
break;
}
else
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, errmsg);
}
if (pServerCert)
CertFreeCertificateContext(pServerCert);
if(store)
schannel_free_store(store);
return ret;
return verify_status;
}

View File

@@ -43,6 +43,11 @@
#include <windows.h>
#include <sspi.h>
#include <ma_global.h>
#include <ma_sys.h>
#include <ma_pvio.h>
#include <ma_tls.h>
#define SC_IO_BUFFER_SIZE 0x4000
@@ -75,7 +80,7 @@ extern my_bool ca_Check, crl_Check;
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls);
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData);
my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name);
unsigned int ma_schannel_verify_certs(MARIADB_TLS *ctls, unsigned int verify_flags);
ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
uchar *WriteBuffer,
size_t WriteBufferSize);

View File

@@ -33,6 +33,7 @@
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <time.h>
#endif
#include <ma_crypt.h>
#if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C)
#include <openssl/applink.c>
@@ -87,6 +88,7 @@ static int ma_bio_write(BIO *h, const char *buf, int size);
static BIO_METHOD ma_BIO_method;
#endif
static int ma_verification_callback(int preverify_ok, X509_STORE_CTX *ctx);
static long ma_tls_version_options(const char *version)
{
@@ -459,24 +461,38 @@ error:
return NULL;
}
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls, uint hash_size)
{
X509 *cert;
unsigned int hash_alg;
SSL *ssl;
char fp[129];
switch (hash_size) {
case 0:
case 256:
hash_alg= MA_HASH_SHA256;
break;
case 384:
hash_alg= MA_HASH_SHA384;
break;
case 512:
hash_alg= MA_HASH_SHA512;
break;
default:
return 1;
}
if (!ctls || !ctls->ssl)
return 1;
/* Did we already read peer cert information ? */
if (ctls->cert_info.version)
return 0;
ssl= (SSL *)ctls->ssl;
/* Store peer certificate information */
if (!ctls->cert_info.version)
{
if ((cert= SSL_get_peer_certificate(ssl)))
{
char fp[33];
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
const ASN1_TIME *not_before= X509_get0_notBefore(cert),
*not_after= X509_get0_notAfter(cert);
@@ -500,15 +516,16 @@ unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
ctls->cert_info.version= X509_get_version(cert) + 1;
ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33);
mysql_hex_string(ctls->cert_info.fingerprint, fp, 32);
X509_free(cert);
return 0;
}
else
return 1;
}
ma_tls_get_finger_print(ctls, hash_alg, fp, sizeof(fp));
mysql_hex_string(ctls->cert_info.fingerprint, fp, (unsigned long)ma_hash_digest_size(hash_alg));
return 0;
}
my_bool ma_tls_connect(MARIADB_TLS *ctls)
{
@@ -539,6 +556,8 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
#else
SSL_set_fd(ssl, (int)mysql_get_socket(mysql));
#endif
if (!mysql->options.extension->tls_allow_invalid_server_cert)
SSL_set_verify(ssl, SSL_VERIFY_PEER, ma_verification_callback);
while (try_connect && (rc= SSL_connect(ssl)) == -1)
{
@@ -556,31 +575,12 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
}
}
/* In case handshake failed or if a root certificate (ca) was specified,
we need to check the result code of X509 verification. A detailed check
of the peer certificate (hostname checking will follow later) */
if (rc != 1 || !mysql->options.extension->tls_allow_invalid_server_cert ||
mysql->options.ssl_ca || mysql->options.ssl_capath)
if (rc != 1)
{
long x509_err= SSL_get_verify_result(ssl);
if ((x509_err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
x509_err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && rc == 1 &&
!mysql->options.ssl_ca && !mysql->options.ssl_capath)
mysql->net.tls_self_signed_error= X509_verify_cert_error_string(x509_err);
else if (x509_err != X509_V_OK)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(x509_err));
/* restore blocking mode */
if (!blocking)
pvio->methods->blocking(pvio, FALSE, 0);
return 1;
} else if (rc != 1) {
ma_tls_set_error(mysql);
return 1;
}
}
pvio->ctls->ssl= ctls->ssl= (void *)ssl;
return 0;
@@ -714,9 +714,40 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
return rc;
}
int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
/** Check for possible errors, and store the result in net.tls_verify_status.
verification will happen after handshake by ma_tls_verify_server_cert().
To retrieve all errors, this callback function returns always true.
(By default OpenSSL stops verification after first error
*/
static int ma_verification_callback(int preverify_ok __attribute__((unused)), X509_STORE_CTX *ctx)
{
X509 *cert;
SSL *ssl;
int x509_err= X509_STORE_CTX_get_error(ctx);
if ((ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())))
{
MYSQL *mysql= (MYSQL *)SSL_get_app_data(ssl);
if ((x509_err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
x509_err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN))
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_TRUST;
else if (x509_err == X509_V_ERR_CERT_REVOKED)
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_REVOKED;
else if (x509_err == X509_V_ERR_CERT_NOT_YET_VALID ||
x509_err == X509_V_ERR_CERT_HAS_EXPIRED)
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_PERIOD;
else if (x509_err != X509_V_OK)
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_UNKNOWN;
}
/* continue verification */
return 1;
}
int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
{
X509 *cert= NULL;
MYSQL *mysql;
SSL *ssl;
MARIADB_PVIO *pvio;
@@ -734,52 +765,97 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
mysql= (MYSQL *)SSL_get_app_data(ssl);
pvio= mysql->net.pvio;
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
return 1;
}
/* if certificates are valid and no revocation error occured,
we can return */
if (!(mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_PERIOD) &&
!(mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_REVOKED))
{
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK;
return 0;
}
}
if (mysql->net.tls_verify_status & verify_flags)
{
return 1;
}
if (verify_flags & MARIADB_TLS_VERIFY_HOST)
{
if (!mysql->host)
{
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), "Invalid (empty) hostname");
return 1;
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
return MARIADB_TLS_VERIFY_ERROR;
}
if (!(cert= SSL_get_peer_certificate(ssl)))
{
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate");
return 1;
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
return MARIADB_TLS_VERIFY_ERROR;
}
#ifdef HAVE_OPENSSL_CHECK_HOST
if (X509_check_host(cert, mysql->host, strlen(mysql->host), 0, 0) != 1
&& X509_check_ip_asc(cert, mysql->host, 0) != 1)
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
#else
x509sn= X509_get_subject_name(cert);
if ((cn_pos= X509_NAME_get_index_by_NID(x509sn, NID_commonName, -1)) < 0)
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
if (!(cn_entry= X509_NAME_get_entry(x509sn, cn_pos)))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
if (!(cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry)))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
cn_str = (char *)ASN1_STRING_data(cn_asn1);
/* Make sure there is no embedded \0 in the CN */
if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn_str))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
if (strcmp(cn_str, mysql->host))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST;
goto error;
}
#endif
X509_free(cert);
}
return 0;
error:
if (cert)
X509_free(cert);
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), "Validation of SSL server certificate failed");
return 1;
}

View File

@@ -32,6 +32,8 @@ char tls_library_version[] = "Schannel";
#define PROT_TLS1_2 4
#define PROT_TLS1_3 8
static int ma_check_peer_cert_time(MARIADB_TLS *ctls);
static struct
{
DWORD cipher_id;
@@ -374,7 +376,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
ALG_ID AlgId[MAX_ALG_ID];
size_t i;
DWORD protocol = 0;
int verify_certs;
const CERT_CONTEXT* cert_context = NULL;
if (!ctls)
@@ -448,14 +449,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
goto end;
verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
!mysql->options.extension->tls_allow_invalid_server_cert;
if (verify_certs)
{
if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert))
goto end;
}
rc = 0;
end:
@@ -516,10 +509,34 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
}
/* }}} */
int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
{
/* Done elsewhere */
return 0;
MYSQL *mysql;
SC_CTX *sctx;
if (!ctls || !ctls->ssl || !ctls->pvio || !ctls->pvio->mysql)
return 1;
sctx= (SC_CTX *)ctls->ssl;
mysql= ctls->pvio->mysql;
if (verify_flags & MARIADB_TLS_VERIFY_PERIOD)
{
if (ma_check_peer_cert_time(ctls))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_PERIOD;
return 1;
}
}
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
return 1;
}
}
return ma_schannel_verify_certs(ctls, verify_flags);
}
static const char *cipher_name(const SecPkgContext_CipherInfo *CipherInfo)
@@ -566,6 +583,34 @@ unsigned char *ma_cert_blob_to_str(PCERT_NAME_BLOB cnblob)
return str;
}
static int ma_check_peer_cert_time(MARIADB_TLS *ctls)
{
PCCERT_CONTEXT pCertCtx= NULL;
SC_CTX *sctx;
PCERT_INFO pci= NULL;
FILETIME ft;
SYSTEMTIME st;
if (!ctls || !ctls->ssl || !ctls->pvio || !ctls->pvio->mysql)
return 1;
sctx= (SC_CTX *)ctls->ssl;
if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK)
return 1;
pci= pCertCtx->pCertInfo;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
if (CompareFileTime(&ft, &pci->NotBefore) == -1 ||
CompareFileTime(&pci->NotAfter, &ft) == -1)
return 1;
return 0;
}
static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm)
{
memset(tm, 0, sizeof(struct tm));
@@ -576,22 +621,42 @@ static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm)
tm->tm_min = sys_tm.wMinute;
}
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls, unsigned int hash_size)
{
PCCERT_CONTEXT pCertCtx= NULL;
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
SC_CTX *sctx;
PCERT_INFO pci= NULL;
DWORD size´= 0;
SYSTEMTIME tm;
char fp[33];
char fp[129];
unsigned int hash_alg;
if (!ctls || !sctx)
if (!ctls || !ctls->ssl || !ctls->pvio || !ctls->pvio->mysql)
return 1;
/* Did we already read peer cert information ? */
if (ctls->cert_info.version)
return 0;
sctx= (SC_CTX *)ctls->ssl;
switch (hash_size) {
case 0:
case 256:
hash_alg= MA_HASH_SHA256;
break;
case 384:
hash_alg= MA_HASH_SHA384;
break;
case 512:
hash_alg= MA_HASH_SHA512;
break;
default:
my_set_error(ctls->pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Cannot detect hash algorithm for fingerprint verification");
return 1;
}
/* Did we already read peer cert information ? */
if (!ctls->cert_info.version)
{
if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK)
return 1;
@@ -605,9 +670,9 @@ unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
ma_systime_to_tm(tm, &ctls->cert_info.not_before);
FileTimeToSystemTime(&pci->NotAfter, &tm);
ma_systime_to_tm(tm, &ctls->cert_info.not_after);
ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33);
mysql_hex_string(ctls->cert_info.fingerprint, fp, 32);
}
ma_tls_get_finger_print(ctls, hash_alg, fp, sizeof(fp));
mysql_hex_string(ctls->cert_info.fingerprint, fp, (unsigned long)ma_hash_digest_size(hash_alg));
return 0;
}

View File

@@ -33,6 +33,7 @@
#define _WIN32_WINNT 0x0601
#endif
#include "schannel_certs.h"
#include "ma_schannel.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
@@ -594,9 +595,8 @@ Verify server certificate against a wincrypt store
SECURITY_STATUS schannel_verify_server_certificate(
const CERT_CONTEXT* cert,
HCERTSTORE store,
BOOL check_revocation,
const char *server_name,
BOOL check_server_name,
unsigned int verify_flags,
char* errmsg,
size_t errmsg_len)
{
@@ -605,7 +605,7 @@ SECURITY_STATUS schannel_verify_server_certificate(
DWORD dwVerifyFlags;
DWORD dwRevocationFlags;
if (check_server_name)
if (verify_flags & MARIADB_TLS_VERIFY_HOST)
{
int cchServerName = (int)strlen(server_name) + 1;
wserver_name = (wchar_t*)LocalAlloc(0,sizeof(wchar_t) * cchServerName);
@@ -621,10 +621,14 @@ SECURITY_STATUS schannel_verify_server_certificate(
dwVerifyFlags = 0;
dwRevocationFlags = 0;
if (check_revocation)
if (verify_flags & MARIADB_TLS_VERIFY_REVOKED)
dwRevocationFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
if (!check_server_name)
if (!(verify_flags & MARIADB_TLS_VERIFY_HOST))
dwVerifyFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
/* Period was already checked before */
dwVerifyFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
if (!(verify_flags & MARIADB_TLS_VERIFY_TRUST))
dwVerifyFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
status = VerifyServerCertificate(cert, store, wserver_name ? wserver_name : L"SERVER_NAME",
dwRevocationFlags, dwVerifyFlags, errmsg, errmsg_len);

View File

@@ -35,9 +35,8 @@ extern SECURITY_STATUS schannel_create_store(
extern SECURITY_STATUS schannel_verify_server_certificate(
const CERT_CONTEXT* cert,
HCERTSTORE store,
BOOL check_revocation,
const char* server_name,
BOOL check_server_name,
unsigned int verify_flags,
char* errmsg,
size_t errmsg_len);

View File

@@ -18,14 +18,7 @@ extern unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong le
extern const char *disabled_plugins;
#define hashing(p) (p->interface_version >= 0x0101 && p->hash_password_bin)
static int set_error_from_tls_self_signed_error(MYSQL *mysql)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), mysql->net.tls_self_signed_error);
reset_tls_self_signed_error(mysql);
return 1;
}
#define password_and_hashing(m,p) ((m)->passwd && (m)->passwd[0] && hashing((p)))
typedef struct {
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
@@ -67,6 +60,49 @@ auth_plugin_t mysql_native_password_client_plugin=
native_password_hash
};
/**
Checks if self-signed certificate error should be ignored.
*/
static my_bool is_local_connection(MARIADB_PVIO *pvio)
{
const char *hostname= pvio->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 (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 native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
@@ -370,6 +406,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mysql->options.use_ssl &&
(mysql->client_flag & CLIENT_SSL))
{
unsigned int verify_flags= 0;
/*
Send mysql->client_flag, max_packet_size - unencrypted otherwise
the server does not know we want to do SSL
@@ -382,13 +419,29 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
errno);
goto error;
}
mysql->net.tls_verify_status = 0;
if (ma_pvio_start_ssl(mysql->net.pvio))
goto error;
if (mysql->net.tls_self_signed_error &&
(!mysql->passwd || !mysql->passwd[0] || !hashing(mpvio->plugin)))
verify_flags= MARIADB_TLS_VERIFY_PERIOD | MARIADB_TLS_VERIFY_REVOKED;
if (have_fingerprint(mysql))
{
/* cannot use auth to validate the cert */
set_error_from_tls_self_signed_error(mysql);
verify_flags|= MARIADB_TLS_VERIFY_FINGERPRINT;
} else {
verify_flags|= MARIADB_TLS_VERIFY_TRUST | MARIADB_TLS_VERIFY_HOST;
}
if (ma_pvio_tls_verify_server_cert(mysql->net.pvio->ctls, verify_flags) > MARIADB_TLS_VERIFY_OK)
{
if (mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_TRUST ||
(mysql->options.ssl_ca || mysql->options.ssl_capath))
goto error;
if (is_local_connection(mysql->net.pvio))
{
CLEAR_CLIENT_ERROR(mysql);
}
else if (!password_and_hashing(mysql, mpvio->plugin))
goto error;
}
}
@@ -769,8 +822,14 @@ retry:
auth_plugin= &dummy_fallback_client_plugin;
/* can we use this plugin with this tls server cert ? */
if (mysql->net.tls_self_signed_error && !hashing(auth_plugin))
return set_error_from_tls_self_signed_error(mysql);
if ((mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_TRUST) &&
!password_and_hashing(mysql, auth_plugin))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Certificate verification failure: The certificate is NOT trusted.");
return 1;
}
goto retry;
}
/*
@@ -782,7 +841,9 @@ retry:
if (ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length))
return -1;
if (!mysql->net.tls_self_signed_error)
if (!mysql->net.tls_verify_status ||
((mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_TRUST) &&
is_local_connection(mysql->net.pvio)))
return 0;
assert(mysql->options.use_ssl);
@@ -824,6 +885,9 @@ retry:
return 0; /* phew. self-signed certificate is validated! */
}
return set_error_from_tls_self_signed_error(mysql);
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Certificate verification failure: The certificate is NOT trusted.");
return 1;
}

View File

@@ -19,6 +19,7 @@ ENDIF()
ENABLE_TESTING()
find_package (Python3 COMPONENTS Interpreter)
INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
${CC_BINARY_DIR}/include
@@ -26,6 +27,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
${CC_SOURCE_DIR}/unittest/libmariadb)
ADD_DEFINITIONS(-DLIBMARIADB)
SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2")
IF(WITH_DYNCOL)
SET(API_TESTS ${API_TESTS} "dyncol")
@@ -50,6 +52,15 @@ ENDIF()
ADD_LIBRARY(ma_getopt ma_getopt.c)
IF(${Python3_FOUND})
CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/tls.c.in
${CC_BINARY_DIR}/unittest/libmariadb/tls.c)
ADD_EXECUTABLE(tls ${CC_BINARY_DIR}/unittest/libmariadb/tls.c)
TARGET_LINK_LIBRARIES(tls cctap ma_getopt mariadbclient)
ADD_TEST(tls ${EXECUTABLE_OUTPUT_PATH}/tls)
ENDIF()
FOREACH(API_TEST ${API_TESTS})
IF (NOT TARGET ${API_TEST})
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
@@ -63,7 +74,17 @@ FOREACH(API_TEST ${API_TESTS})
ENDIF()
ENDFOREACH(API_TEST)
FOREACH(API_TEST ${MANUAL_TESTS})
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
TARGET_LINK_LIBRARIES(${API_TEST} cctap ma_getopt mariadbclient)
ENDFOREACH()
SET(ADDITIONAL_FILES "tls_server.py" "certs/server-cert.pem"
"certs/server-cert.crl" "certs/server-key.pem" "certs/cacert.pem")
FOREACH(FILE ${ADDITIONAL_FILES})
CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/${FILE}
${CC_BINARY_DIR}/unittest/libmariadb/${FILE}
COPYONLY)
ENDFOREACH()

View File

@@ -44,7 +44,7 @@ static int test_conc75(MYSQL *my)
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS);
my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS, 1);
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
check_mysql_rc(rc, mysql);
@@ -85,7 +85,7 @@ static int test_conc74(MYSQL *unused __attribute__((unused)))
mysql= mysql_init(NULL);
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -128,7 +128,7 @@ static int test_conc71(MYSQL *my)
mysql_options(mysql, MYSQL_INIT_COMMAND, "/*!40101 set @@session.wait_timeout=28800 */");
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
diag("kill server");
@@ -161,7 +161,7 @@ static int test_conc70(MYSQL *my)
mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1);
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql);
@@ -223,7 +223,7 @@ static int test_conc68(MYSQL *my)
mysql_query(my, "SET global max_allowed_packet=1024*1024*22");
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql);
@@ -274,7 +274,7 @@ static int basic_connect(MYSQL *unused __attribute__((unused)))
FAIL_IF(!my, "mysql_init() failed");
FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
rc= mysql_query(my, "SELECT @@version");
check_mysql_rc(rc, my);
@@ -671,7 +671,7 @@ static int test_status(MYSQL *mysql)
static int bug_conc1(MYSQL *mysql)
{
my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0);
port, socketname, 0, 1);
diag("errno: %d", mysql_errno(mysql));
FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED,
"Expected errno=CR_ALREADY_CONNECTED");
@@ -688,7 +688,7 @@ static int test_options_initcmd(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_INIT_COMMAND, "INSERT INTO t1 VALUES (1),(2),(3)");
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS, 1), mysql_error(mysql));
rc= mysql_query(mysql, "SELECT a FROM t1");
check_mysql_rc(rc, mysql);
@@ -734,7 +734,7 @@ static int test_reconnect_maxpackage(MYSQL *unused __attribute__((unused)))
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS, 1), mysql_error(mysql));
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
rc= mysql_query(mysql, "SELECT @@max_allowed_packet");
@@ -792,7 +792,7 @@ static int test_compressed(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1);
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS, 1), mysql_error(mysql));
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
rc= mysql_query(mysql, "SHOW VARIABLES");

View File

@@ -1106,7 +1106,7 @@ static int bulk_with_unit_result_insert(MYSQL *my)
stmt= mysql_stmt_init(mysql);
mysql_options(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &unique_result);
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(mysql));
port, socketname, 0, 1), mysql_error(mysql));
mysql_get_option(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &bool_val);
FAIL_UNLESS(bool_val, "bool_val != true");
@@ -1223,7 +1223,7 @@ static int bulk_with_unit_result_delete(MYSQL *my)
stmt= mysql_stmt_init(mysql);
mysql_options(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &unique_result);
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(mysql));
port, socketname, 0, 1), mysql_error(mysql));
if (!bulk_enabled)
return SKIP;
@@ -1331,7 +1331,7 @@ static int bulk_with_unit_result_update(MYSQL *my)
mysql_options(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &unique_result);
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(mysql));
port, socketname, 0, 1), mysql_error(mysql));
if (!bulk_enabled)
return SKIP;

View File

@@ -0,0 +1,121 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
5c:81:fd:b9:82:69:e0:46:8d:99:ed:d0:95:4b:d3:d6:62:8a:69:97
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = cacert, C = FI, ST = Helsinki, L = Helsinki, O = MariaDB
Validity
Not Before: Mar 3 03:03:03 2020 GMT
Not After : Feb 27 03:03:03 2040 GMT
Subject: CN = cacert, C = FI, ST = Helsinki, L = Helsinki, O = MariaDB
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:bc:72:01:10:68:c1:df:fa:d1:77:55:7c:09:13:
19:51:41:cd:ed:4f:51:43:22:e7:97:0e:94:fc:0d:
1d:a9:c6:f3:17:79:31:6f:12:7a:9b:7f:87:e2:55:
16:d5:a4:dd:6a:d3:5e:4f:e2:e0:bc:c4:9f:c5:95:
1a:47:13:a5:cd:6d:f3:76:e2:9a:12:31:76:e4:f1:
01:94:37:45:10:32:18:9e:cc:d8:7f:04:ca:18:97:
bf:22:2e:51:ba:73:6f:46:50:36:fe:df:82:4c:8a:
9e:34:be:44:f4:12:61:72:18:b3:81:b5:d9:b2:69:
8f:7d:f4:8b:41:62:34:59:71:f7:e4:26:a6:cf:55:
4d:d4:52:a3:37:24:bd:82:21:9f:d1:db:cd:e9:12:
a9:cf:60:48:3d:da:ea:a0:a7:d0:57:16:68:49:e5:
b4:e8:dc:d0:b0:12:b3:c7:1c:f1:b3:b1:eb:12:8b:
c7:3e:3c:02:fe:f6:4c:a8:35:d8:cf:74:64:63:89:
84:3e:75:88:a0:0b:80:5c:ea:68:b2:9c:bb:e3:ae:
4f:cd:24:b9:97:89:95:4e:3f:78:48:ba:ad:97:4c:
bf:f8:8b:14:80:f4:78:03:11:4b:a7:e3:99:1c:82:
59:bf:b6:f3:3e:3e:db:db:38:73:91:8d:f0:6f:e5:
5d:02:e7:c0:a5:8b:ad:69:f1:17:29:2c:16:41:ad:
ac:0f:64:c8:f7:62:58:da:73:66:f7:91:2c:89:f7:
80:6b:d7:91:f1:c8:4a:5a:c4:2d:3d:0b:18:83:f1:
e9:74:2d:83:bb:09:46:bd:f0:40:ad:0b:dd:0c:45:
64:8d:9e:cf:a7:a0:6c:d2:cc:f1:f9:05:15:7a:e3:
02:15:b0:e6:99:cd:81:5b:dd:52:9b:c0:35:25:fa:
4c:88:47:1d:16:19:9f:9d:f0:54:01:6e:20:6a:10:
ab:4f:d2:a2:a7:31:db:6d:76:26:0d:35:9d:ac:1f:
4e:4d:37:87:2c:78:26:d4:1f:f0:87:fc:f4:e2:2a:
af:9a:a4:d6:69:93:16:4f:ed:fb:e0:78:99:36:49:
d2:2e:7d:44:15:94:58:bd:ba:bc:d3:b9:75:5c:58:
13:69:18:8e:5d:0e:c9:0c:dd:06:c4:7b:fc:34:3e:
df:51:46:8d:5e:33:40:ba:39:75:9a:29:a5:f0:be:
d3:a1:2c:72:88:85:4a:a0:2e:d9:71:15:30:49:57:
f4:1b:73:e4:b3:b1:9e:3e:e6:0b:30:0a:eb:e9:cc:
ec:98:4c:36:ea:58:8a:aa:b1:4b:b9:e1:5e:4a:d0:
81:65:f0:ba:2c:b0:a6:8e:02:f1:c6:e0:78:b9:49:
eb:8e:79
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
4D:FC:7A:19:F3:2B:0C:7D:F6:C0:7C:4D:F8:72:34:4C:8C:35:52:74
X509v3 Authority Key Identifier:
keyid:4D:FC:7A:19:F3:2B:0C:7D:F6:C0:7C:4D:F8:72:34:4C:8C:35:52:74
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
3c:e7:3a:e8:b6:d1:be:ca:27:ad:02:00:08:b7:1f:2d:e9:cd:
81:9f:98:f0:f0:a4:c5:dd:dc:94:a1:a6:bd:31:56:54:05:6a:
da:b1:1b:42:35:ef:f8:75:1c:0d:0f:00:77:24:a7:ef:5f:f1:
ce:38:3a:05:a7:22:a6:40:b6:6c:57:46:31:e8:ba:2f:b5:9e:
fb:7c:07:93:5c:cb:82:59:1a:2f:13:5b:6d:55:8d:d9:dd:ec:
44:b2:7f:89:26:37:da:fc:e8:aa:af:87:8b:5e:c3:3e:21:c2:
a0:ca:2a:49:78:fa:9d:10:5c:e8:2c:24:ac:e8:f3:61:25:cb:
86:6c:8f:1d:4c:2f:83:bd:d4:72:dc:54:1b:fa:3d:1a:d4:54:
a9:ac:87:70:ff:cf:53:26:1f:e7:11:bc:b3:89:d0:71:25:09:
d9:80:09:42:b1:5a:8d:01:a9:89:1e:2c:cc:89:e7:f8:c2:43:
4b:20:cd:ce:9c:2f:67:99:35:4f:e2:ec:00:07:3d:69:6e:9e:
48:93:d4:56:b1:0b:52:00:d9:86:05:1e:ea:64:68:a1:87:04:
0f:17:45:82:8e:f5:13:7a:90:79:c8:fd:42:e8:80:df:3b:46:
bc:39:c9:76:14:90:8e:cd:80:98:84:56:43:88:33:1e:ac:4a:
cb:48:8d:ff:35:d4:68:0e:ef:bf:1a:b5:34:17:7a:c8:c2:e8:
f0:18:f6:58:07:9b:09:9f:b5:e2:29:e2:5e:cb:b9:71:ce:13:
90:6d:b7:4e:23:31:bc:ab:17:b4:3d:96:17:4b:f8:01:49:b9:
0a:0c:73:1d:54:de:51:79:3a:fb:f0:b5:10:8d:38:ad:87:36:
0f:36:48:11:f7:1b:d6:2f:ed:a7:1d:73:74:45:19:69:1d:9f:
86:ec:a3:2b:8e:fd:5a:33:08:4d:17:41:df:57:8a:1e:99:c1:
bc:aa:15:a1:af:2c:23:67:4e:31:45:91:fb:8f:af:1e:19:a6:
0f:bb:d9:3a:55:cc:b0:a2:41:a5:99:20:cc:64:91:f7:8e:6b:
c4:ad:5a:c8:ca:3d:74:36:91:97:34:f1:f8:c5:22:87:6b:e3:
cf:9c:0a:75:5a:09:30:88:9d:07:99:2d:ef:87:75:45:ed:0f:
75:8a:88:6c:b0:7e:dc:c3:d4:50:c4:25:0c:de:f7:53:f6:12:
bd:5a:8b:81:3a:30:83:b7:66:5e:7e:8f:d8:65:ab:2a:fa:85:
d4:4b:61:fb:27:98:79:cb:d6:06:07:23:7f:d9:1d:79:3e:71:
a7:0c:c8:e8:0e:e0:40:66:4d:8d:0e:9c:41:c0:d2:2c:91:95:
63:d5:c4:12:cd:9b:bc:f4
-----BEGIN CERTIFICATE-----
MIIFjTCCA3WgAwIBAgIUXIH9uYJp4EaNme3QlUvT1mKKaZcwDQYJKoZIhvcNAQEL
BQAwVjEPMA0GA1UEAwwGY2FjZXJ0MQswCQYDVQQGEwJGSTERMA8GA1UECAwISGVs
c2lua2kxETAPBgNVBAcMCEhlbHNpbmtpMRAwDgYDVQQKDAdNYXJpYURCMB4XDTIw
MDMwMzAzMDMwM1oXDTQwMDIyNzAzMDMwM1owVjEPMA0GA1UEAwwGY2FjZXJ0MQsw
CQYDVQQGEwJGSTERMA8GA1UECAwISGVsc2lua2kxETAPBgNVBAcMCEhlbHNpbmtp
MRAwDgYDVQQKDAdNYXJpYURCMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEAvHIBEGjB3/rRd1V8CRMZUUHN7U9RQyLnlw6U/A0dqcbzF3kxbxJ6m3+H4lUW
1aTdatNeT+LgvMSfxZUaRxOlzW3zduKaEjF25PEBlDdFEDIYnszYfwTKGJe/Ii5R
unNvRlA2/t+CTIqeNL5E9BJhchizgbXZsmmPffSLQWI0WXH35Camz1VN1FKjNyS9
giGf0dvN6RKpz2BIPdrqoKfQVxZoSeW06NzQsBKzxxzxs7HrEovHPjwC/vZMqDXY
z3RkY4mEPnWIoAuAXOpospy7465PzSS5l4mVTj94SLqtl0y/+IsUgPR4AxFLp+OZ
HIJZv7bzPj7b2zhzkY3wb+VdAufApYutafEXKSwWQa2sD2TI92JY2nNm95EsifeA
a9eR8chKWsQtPQsYg/HpdC2DuwlGvfBArQvdDEVkjZ7Pp6Bs0szx+QUVeuMCFbDm
mc2BW91Sm8A1JfpMiEcdFhmfnfBUAW4gahCrT9KipzHbbXYmDTWdrB9OTTeHLHgm
1B/wh/z04iqvmqTWaZMWT+374HiZNknSLn1EFZRYvbq807l1XFgTaRiOXQ7JDN0G
xHv8ND7fUUaNXjNAujl1miml8L7ToSxyiIVKoC7ZcRUwSVf0G3Pks7GePuYLMArr
6czsmEw26liKqrFLueFeStCBZfC6LLCmjgLxxuB4uUnrjnkCAwEAAaNTMFEwHQYD
VR0OBBYEFE38ehnzKwx99sB8TfhyNEyMNVJ0MB8GA1UdIwQYMBaAFE38ehnzKwx9
9sB8TfhyNEyMNVJ0MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
ADznOui20b7KJ60CAAi3Hy3pzYGfmPDwpMXd3JShpr0xVlQFatqxG0I17/h1HA0P
AHckp+9f8c44OgWnIqZAtmxXRjHoui+1nvt8B5Ncy4JZGi8TW21Vjdnd7ESyf4km
N9r86Kqvh4tewz4hwqDKKkl4+p0QXOgsJKzo82Ely4Zsjx1ML4O91HLcVBv6PRrU
VKmsh3D/z1MmH+cRvLOJ0HElCdmACUKxWo0BqYkeLMyJ5/jCQ0sgzc6cL2eZNU/i
7AAHPWlunkiT1FaxC1IA2YYFHupkaKGHBA8XRYKO9RN6kHnI/ULogN87Rrw5yXYU
kI7NgJiEVkOIMx6sSstIjf811GgO778atTQXesjC6PAY9lgHmwmfteIp4l7LuXHO
E5Btt04jMbyrF7Q9lhdL+AFJuQoMcx1U3lF5OvvwtRCNOK2HNg82SBH3G9Yv7acd
c3RFGWkdn4bsoyuO/VozCE0XQd9Xih6ZwbyqFaGvLCNnTjFFkfuPrx4Zpg+72TpV
zLCiQaWZIMxkkfeOa8StWsjKPXQ2kZc08fjFIodr48+cCnVaCTCInQeZLe+HdUXt
D3WKiGywftzD1FDEJQze91P2Er1ai4E6MIO3Zl5+j9hlqyr6hdRLYfsnmHnL1gYH
I3/ZHXk+cacMyOgO4EBmTY0OnEHA0iyRlWPVxBLNm7z0
-----END CERTIFICATE-----

View File

@@ -0,0 +1,17 @@
-----BEGIN X509 CRL-----
MIICxTCBrgIBATANBgkqhkiG9w0BAQsFADBWMQ8wDQYDVQQDDAZjYWNlcnQxCzAJ
BgNVBAYTAkZJMREwDwYDVQQIDAhIZWxzaW5raTERMA8GA1UEBwwISGVsc2lua2kx
EDAOBgNVBAoMB01hcmlhREIXDTIwMDMwMzAzMDMwM1oXDTQwMDIyNzAzMDMwM1ow
FDASAgEBFw0yMDAzMDMwMzAzMDNaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
AQsFAAOCAgEAFsQCul/9vZ1qSxnYoVVlHPspJ6JFgg0kEK5ZQsiGaAKyvV1d9xpT
uu1FxOEajbeOGdGk9kRqy928KFynPSTpWphl+bJ2E+uey4a9PTgAlxPEcdbnGf2f
1je7i0pOlOximKkeRb8GB4EwNvS9MPKd2pkJnGgIK6eyTtOnKgvmkA3vwXIqB1wJ
dbQMscQlWyCN7lz5A2D6T9xOYY5gKthBAdM73OgzivGKJekoCCirGqVjA7Kurpmt
zV+UbDrHqxsBB4BS+X4sFp7n9K4dqD/acR7aYsjpxKUzc43rEzuTE8flQw1Hzk/h
lGJKg0XfIs2ol7zSeADocZMQR8G0wpeFsz5abm5/oCQ007Rxn+2d/8ZPfOw75u2p
vdcOARoU1q1qF1lGL3x5PFpam693VxB07js3qi6sCqJjsVETAmz08Bvck0+HeHpr
nyQndk7EZPl7W+8Ls68kZZB+77DDNS9Gwb8BQxzazuvN4G6DQsZLYNhWyV6vPeOt
sJF7mdvr4PElbtNG1WQFySt7SJKaA21hG1qVUqto8ZTd+/KU5b7MMnTM7nxFXQ3a
WwHq79xK1xC4f87rrc423yYEjAQkb/1NSseGa/gfqo6wRcxXbRQETq2r9KIsLwAN
sK1gO7Cl0SW9PtrCF4lWNOES9iSZ3BaacOHT7kD8qoBAL83CIlDFgWg=
-----END X509 CRL-----

View File

@@ -0,0 +1,128 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=cacert, C=FI, ST=Helsinki, L=Helsinki, O=MariaDB
Validity
Not Before: Mar 3 03:03:03 2020 GMT
Not After : Feb 27 03:03:03 2040 GMT
Subject: C=FI, ST=state or province within country, in other certificates in this file it is the same as L, L=location, usually an address but often ambiguously used, O=organization name, typically a company name, OU=organizational unit name, a division name within an organization, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:c9:f9:46:27:69:68:4b:5a:26:dd:1f:98:0f:44:
ba:40:83:ca:82:c2:7a:53:cc:b9:30:f1:ca:3e:e2:
6d:de:3a:11:aa:ce:c5:90:27:e6:f3:4f:3b:e9:af:
1a:ec:21:d7:ca:14:1f:f1:9b:cb:cd:7e:57:b4:c8:
5d:6c:cd:5a:54:dd:8a:9a:a9:27:ef:49:d3:6c:ac:
99:2d:dc:e5:c0:1e:3c:05:9f:c5:04:c7:2d:81:66:
21:27:16:d6:c3:e4:97:53:db:21:a6:43:50:70:cb:
2e:95:fb:da:52:55:27:1b:17:ef:19:83:eb:ff:a1:
fc:62:63:ea:2f:fe:53:35:e6:d9:bc:03:2d:e5:c2:
18:b1:29:91:e4:a4:79:2c:f1:05:dd:d5:3f:ff:b1:
9e:64:8d:60:29:74:43:f0:3d:31:e7:78:ce:9f:17:
74:e5:9f:fb:7b:69:a9:45:3b:e8:76:03:c6:ca:52:
85:84:50:0d:2b:98:6f:ff:d8:41:66:6d:39:f6:1a:
a3:61:e2:82:5f:dc:ec:ca:97:dc:b2:dc:cf:aa:97:
ef:13:10:ea:fb:8f:99:91:bb:d9:e8:61:25:2d:68:
04:af:2f:89:56:0d:89:90:77:e0:ad:c2:25:eb:3c:
d2:4e:3d:ca:6e:ae:35:c8:f2:94:7a:09:74:d3:8e:
73:30:e6:39:fe:b6:9c:c7:4d:23:4e:b0:bf:90:97:
29:b2:b3:30:b2:bb:49:ae:47:09:fe:cd:23:3a:01:
a4:ac:cb:53:25:74:98:27:20:85:6b:18:74:bb:1c:
bf:ff:05:dc:06:7c:02:78:81:1e:96:ad:8f:c6:a2:
0d:b3:5c:8e:ad:d5:fd:af:c5:8d:8b:9f:31:b1:4f:
a7:1e:9b:cd:57:68:d5:ad:ed:4e:7b:5f:0d:0c:d2:
47:85:b4:65:4b:23:1c:5b:a5:ec:88:fa:42:80:73:
84:cb:75:05:a6:39:f1:e6:a9:4e:15:e6:2f:f7:61:
0b:f3:08:cc:a6:2b:2b:64:6e:04:a1:fc:da:5e:34:
ad:7c:54:be:85:e4:ed:64:74:31:30:2a:ed:ab:3e:
d2:cd:c7:3e:de:18:04:8a:a7:bd:ad:52:74:13:b1:
b0:7d:4d:7e:87:7b:cb:82:1f:29:11:e1:0e:4b:42:
2b:83:e8:88:7e:92:80:20:eb:ee:da:d4:dd:1e:9c:
54:5c:67:a7:00:5f:a1:b7:bf:5d:c0:5a:25:2a:c1:
1e:7c:93:32:dd:17:c8:02:6d:1a:42:26:f6:50:01:
4b:df:29:7f:72:f1:90:72:80:8a:ba:2f:8c:86:7d:
56:45:c5:0e:82:16:d8:29:03:57:87:ce:22:1c:7f:
31:a8:4f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
DB:DF:8B:BC:C2:EE:A9:2A:4E:FD:0E:7A:5F:15:CF:94:A3:0C:CA:CC
X509v3 Authority Key Identifier:
keyid:4D:FC:7A:19:F3:2B:0C:7D:F6:C0:7C:4D:F8:72:34:4C:8C:35:52:74
Signature Algorithm: sha256WithRSAEncryption
09:d1:af:0e:0b:e8:a2:5e:c8:ee:0a:9f:21:c3:2c:da:a4:38:
d5:cc:a6:ca:8e:ef:df:94:ab:32:5a:ec:32:84:01:7a:97:bb:
38:e0:a8:7d:20:d9:ca:51:3d:a3:74:f9:fe:85:14:26:95:37:
de:2d:74:7e:16:eb:14:14:1b:80:e9:12:54:de:cc:94:cc:38:
ca:df:9a:d0:ce:3e:6c:f1:de:e8:40:f5:3e:6e:c0:ee:05:50:
5a:38:4b:97:69:3c:7a:1f:a8:11:67:e5:9a:9e:50:2e:62:e8:
f8:bf:1a:54:84:ad:9d:0e:1e:ec:64:22:1b:38:85:87:0b:f3:
c7:47:80:aa:c1:99:72:a5:0d:fd:ce:2c:6e:0d:52:4d:d7:55:
2f:4e:52:6e:4a:b9:9a:61:34:08:59:d9:30:cc:30:4a:dc:35:
34:b9:b0:a4:97:a1:b8:d7:ce:ee:63:2d:3a:ad:73:9c:99:49:
11:0a:04:94:60:97:19:4f:4b:66:d4:fb:bf:14:46:39:27:da:
01:3f:d8:6a:46:cb:77:12:f2:77:86:3a:45:e1:f7:44:3d:2b:
3d:e6:26:06:5e:29:20:be:1f:aa:74:43:0c:85:79:e2:14:9c:
03:bf:49:21:64:7e:c3:4a:7b:a1:60:f6:ce:fb:7c:59:e4:65:
7c:fb:1e:84:38:53:ec:1f:80:c2:b5:f7:c2:0e:46:19:4b:4d:
a3:32:6e:59:40:32:9b:6b:2c:bb:fa:1a:89:2e:96:22:71:d5:
71:92:9b:0d:86:0e:60:60:19:ba:34:22:e1:f1:f3:c9:87:5c:
5c:f5:d3:52:1c:11:0d:d3:91:7a:6b:bd:6f:cc:ba:78:60:e0:
20:b4:c2:d1:91:70:5f:74:33:a1:bc:aa:db:d1:35:91:b5:cb:
46:a8:28:7a:26:fc:8c:6c:64:05:4d:73:f1:00:bb:eb:70:87:
fd:9f:04:55:8f:7b:00:b1:c0:50:09:3a:58:44:19:a7:bd:f1:
34:5b:4d:d9:10:6b:d5:38:fa:64:f5:d3:28:4f:c4:23:14:29:
98:3e:2f:c2:87:6f:69:a0:89:0e:ee:f7:c4:50:9e:33:b9:0a:
84:f0:c6:38:45:38:91:10:14:ac:c4:03:8e:4b:e2:61:f9:78:
85:02:b9:c6:d5:c2:9f:ba:ac:21:1a:3a:4e:1a:f8:a9:12:ae:
67:37:79:ce:ec:94:54:cf:28:c4:33:3b:45:23:d2:cb:37:3b:
09:ee:e2:c4:9f:12:dc:e3:8f:06:1d:d5:54:b7:73:2c:34:36:
97:41:91:81:30:06:2c:90:14:9b:aa:4e:33:2a:38:29:f5:3d:
f4:c7:f2:03:6d:d9:d7:3e
-----BEGIN CERTIFICATE-----
MIIGlTCCBH2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQ8wDQYDVQQDDAZjYWNl
cnQxCzAJBgNVBAYTAkZJMREwDwYDVQQIDAhIZWxzaW5raTERMA8GA1UEBwwISGVs
c2lua2kxEDAOBgNVBAoMB01hcmlhREIwHhcNMjAwMzAzMDMwMzAzWhcNNDAwMjI3
MDMwMzAzWjCCAUcxCzAJBgNVBAYTAkZJMWEwXwYDVQQIDFhzdGF0ZSBvciBwcm92
aW5jZSB3aXRoaW4gY291bnRyeSwgaW4gb3RoZXIgY2VydGlmaWNhdGVzIGluIHRo
aXMgZmlsZSBpdCBpcyB0aGUgc2FtZSBhcyBMMUAwPgYDVQQHDDdsb2NhdGlvbiwg
dXN1YWxseSBhbiBhZGRyZXNzIGJ1dCBvZnRlbiBhbWJpZ3VvdXNseSB1c2VkMTQw
MgYDVQQKDCtvcmdhbml6YXRpb24gbmFtZSwgdHlwaWNhbGx5IGEgY29tcGFueSBu
YW1lMUkwRwYDVQQLDEBvcmdhbml6YXRpb25hbCB1bml0IG5hbWUsIGEgZGl2aXNp
b24gbmFtZSB3aXRoaW4gYW4gb3JnYW5pemF0aW9uMRIwEAYDVQQDDAlsb2NhbGhv
c3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ+UYnaWhLWibdH5gP
RLpAg8qCwnpTzLkw8co+4m3eOhGqzsWQJ+bzTzvprxrsIdfKFB/xm8vNfle0yF1s
zVpU3YqaqSfvSdNsrJkt3OXAHjwFn8UExy2BZiEnFtbD5JdT2yGmQ1Bwyy6V+9pS
VScbF+8Zg+v/ofxiY+ov/lM15tm8Ay3lwhixKZHkpHks8QXd1T//sZ5kjWApdEPw
PTHneM6fF3Tln/t7aalFO+h2A8bKUoWEUA0rmG//2EFmbTn2GqNh4oJf3OzKl9yy
3M+ql+8TEOr7j5mRu9noYSUtaASvL4lWDYmQd+CtwiXrPNJOPcpurjXI8pR6CXTT
jnMw5jn+tpzHTSNOsL+QlymyszCyu0muRwn+zSM6AaSsy1MldJgnIIVrGHS7HL//
BdwGfAJ4gR6WrY/Gog2zXI6t1f2vxY2LnzGxT6cem81XaNWt7U57Xw0M0keFtGVL
IxxbpeyI+kKAc4TLdQWmOfHmqU4V5i/3YQvzCMymKytkbgSh/NpeNK18VL6F5O1k
dDEwKu2rPtLNxz7eGASKp72tUnQTsbB9TX6He8uCHykR4Q5LQiuD6Ih+koAg6+7a
1N0enFRcZ6cAX6G3v13AWiUqwR58kzLdF8gCbRpCJvZQAUvfKX9y8ZBygIq6L4yG
fVZFxQ6CFtgpA1eHziIcfzGoTwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG
+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
29+LvMLuqSpO/Q56XxXPlKMMyswwHwYDVR0jBBgwFoAUTfx6GfMrDH32wHxN+HI0
TIw1UnQwDQYJKoZIhvcNAQELBQADggIBAAnRrw4L6KJeyO4KnyHDLNqkONXMpsqO
79+UqzJa7DKEAXqXuzjgqH0g2cpRPaN0+f6FFCaVN94tdH4W6xQUG4DpElTezJTM
OMrfmtDOPmzx3uhA9T5uwO4FUFo4S5dpPHofqBFn5ZqeUC5i6Pi/GlSErZ0OHuxk
Ihs4hYcL88dHgKrBmXKlDf3OLG4NUk3XVS9OUm5KuZphNAhZ2TDMMErcNTS5sKSX
objXzu5jLTqtc5yZSREKBJRglxlPS2bU+78URjkn2gE/2GpGy3cS8neGOkXh90Q9
Kz3mJgZeKSC+H6p0QwyFeeIUnAO/SSFkfsNKe6Fg9s77fFnkZXz7HoQ4U+wfgMK1
98IORhlLTaMybllAMptrLLv6GokuliJx1XGSmw2GDmBgGbo0IuHx88mHXFz101Ic
EQ3TkXprvW/Munhg4CC0wtGRcF90M6G8qtvRNZG1y0aoKHom/IxsZAVNc/EAu+tw
h/2fBFWPewCxwFAJOlhEGae98TRbTdkQa9U4+mT10yhPxCMUKZg+L8KHb2mgiQ7u
98RQnjO5CoTwxjhFOJEQFKzEA45L4mH5eIUCucbVwp+6rCEaOk4a+KkSrmc3ec7s
lFTPKMQzO0Uj0ss3Ownu4sSfEtzjjwYd1VS3cyw0NpdBkYEwBiyQFJuqTjMqOCn1
PfTH8gNt2dc+
-----END CERTIFICATE-----

View File

@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKgIBAAKCAgEAyflGJ2loS1om3R+YD0S6QIPKgsJ6U8y5MPHKPuJt3joRqs7F
kCfm80876a8a7CHXyhQf8ZvLzX5XtMhdbM1aVN2Kmqkn70nTbKyZLdzlwB48BZ/F
BMctgWYhJxbWw+SXU9shpkNQcMsulfvaUlUnGxfvGYPr/6H8YmPqL/5TNebZvAMt
5cIYsSmR5KR5LPEF3dU//7GeZI1gKXRD8D0x53jOnxd05Z/7e2mpRTvodgPGylKF
hFANK5hv/9hBZm059hqjYeKCX9zsypfcstzPqpfvExDq+4+ZkbvZ6GElLWgEry+J
Vg2JkHfgrcIl6zzSTj3Kbq41yPKUegl0045zMOY5/racx00jTrC/kJcpsrMwsrtJ
rkcJ/s0jOgGkrMtTJXSYJyCFaxh0uxy//wXcBnwCeIEelq2PxqINs1yOrdX9r8WN
i58xsU+nHpvNV2jVre1Oe18NDNJHhbRlSyMcW6XsiPpCgHOEy3UFpjnx5qlOFeYv
92EL8wjMpisrZG4EofzaXjStfFS+heTtZHQxMCrtqz7Szcc+3hgEiqe9rVJ0E7Gw
fU1+h3vLgh8pEeEOS0Irg+iIfpKAIOvu2tTdHpxUXGenAF+ht79dwFolKsEefJMy
3RfIAm0aQib2UAFL3yl/cvGQcoCKui+Mhn1WRcUOghbYKQNXh84iHH8xqE8CAwEA
AQKCAgEAtn2LvKqJ+KOhP+R/ETSpEQfDX7h2rObqYWXmtkECwms3cVzYtzLGgwsR
eEimC7tcbZMXdceuMqM4ffkYKOm2970gsjOrCJNs++FLmlvgH2FyHCbK7lFFNYjg
5Z/GN0OA09zIH6Dsuq1rD0t7bS7RYbKTcDt5bgWftArRG8IwzyAhlbZNry5b/x8v
Wiad8lRoV5KJ++8xzWrL+0i45gV05M+L6cVY8u1FXbIPpqXFmXQ6Fq7PQsjNzZkz
gTiVhwWj/FD/VL9Dy3gjX74tRFMtM9eJxXFg0CFkwX+5GTVFUSyOJvfNoDolFKqs
EHO+rTjMULOWB8FSiZldPJL0wv4P5wEAZ+aqQ4mWsDHVDyACRlmLbOvMriiHrCMj
uDOWQwMsWOc/vCt6WPuNv3PlagACqOGQf0Pj62OcWTJGRzHoOXCw1OMgW3nNgg9X
f5UvXE8nn1hfJMePh6u1BXuOmoyOi2zTIng8ubfE8nw4pw35fkvfkY8BqllUw0XO
Kq5ICr1eqrHJNnicL+ITfiFm7yo0qUPlQnkBA7pCvrNDEdh6mLIEUE/NSqZd2XKB
TZeXLh6/0+djK1899sTsjr75yB1mVc6Jgo0OC4Em6T/u+VKw5LptxAoBnY7et2/7
6oJe8trQDEwBBE0ihwAvlElwG+kUyKS7P01Ow7ctmYzUuDoLgqECggEBAOV6LQ2H
/OfKfgyP/0pM3ngDUC0H49FLIXAKRdY/gLzecPauTleUX1aGOBkfscuHlKjKCllS
qUCHBLyE3bwAK5t0E3aHLtV9gGjNZvi7O6DZHwnMWP5AwN+eW1TASWUKfPVS6uUk
uMzkTkUowDK38EF7iabinSEYmpNxt0G7T4K9pV6O2HgMkKdIHvyxJ0dME3VOgG6m
miYTe2faRDaqRNY2Kn/r1NhSpRKb/iBovFcHLEQpffbtoJs4hzSUa8gk+iTk7WRX
k5a/74nJpB+v1m8ywHEmZ9wFBTCjoVNzBj0f7vZOrs6pP/3niJPEbyi1oK42I1GN
g6J16jgjVv+Q21ECggEBAOFRUVM61Yqz9mt34MqJgp0bqGEShDuFY4kvttAbtHK5
FLYc2Jxvn657jp1r2ksAb6UsDbp92UXmxxTw5H+PWsQ/nbNxmhPfjbjdvhoB4IHr
l3YxgWL9Ex0bi1vB8i/RYEOZs+Q9yyjB7rJqR6gw2jDJ0CQe/RsZUFh4RdzvrWoz
gqddlFUzfkS8KAjvmUA6rOrAgIdYhBRP85gXDtV+bc331q6NH8wu0hkJ0Q6gj0WZ
l/Nu1wWg8goHMuCU5GCDtrjQaXSECCo+XL4+VheGk8ZkDF+EkD4tW0oRKyao1rex
+aZ7IykGikXpMGtoQ+gUyiQzOzodFD5aycfJ+vO0IZ8CggEBANHXREWAWfM3xsYE
E2XFHxZNqU5UTa5AbqY+rpf5X+bV3iSlRfxuMDQ17iyDQBkmtPkYMBh4L09TaDBf
q0fUPAwePAICIgCVkAvF8Gh5BlDS2sAh/isZ2YVjEI9SeosL6TKIjUXWq6qpBy3U
0tROQUQQDNLvnNH75rX3oaVY/J9IfmUWaLp2evyNRdC6ynk3BwAZNfZ5ILK60/km
rYPzdZkQ1RI+/FaIVGzM+rh2LevDImZ+LrLTny7xpSmeo2TU820zbiV4s/yBLTEp
k4xqRcNPfIy7mvOmH5XXu5lMsKLKhcD0OIPAX0T2KX0+fouScwl7dhaIOpwgCXsm
TdLLitECggEAcJMYduUmXC6eKAO1JHyf7a8r6ZQ+zR5QJPLZ/BBbkBY46uRutXpv
5dWF49FHN8H4BiaElXDbZblwLl5NTA5r4zGFsWpI+TTwsjTYDlZxvXfgLQV/B945
9okUj7vPLWUHG79nydm17581i57ePoJqAYZToDh7bVawdgNhpIl7s1wZI1X2Druz
ktQPjKdpglXOn1ue3AC1vRBVPOAIYVLRud7iPEP2ZyXdgvUMpqpB6xxadx4iAIXx
aGFAYkUB9dbZLG20wqpVCgYugD7U9NwgaTcDl5W8G9S9j7wUOzSQUydw/GT5pD3I
SDXCI2fsxb/dX0jZhqeQvbbOqiuYXrrZMQKCAQEAqE3ZWDqhx4obUCkAiSnADnmh
v4/yzeHByCXH71uhou/C+y1f3RQLIZN8oAgnSKpFeAdue3Gwk6BA8FYBjSF2hhrM
LaYkzZ0fhFKhTbNmJ2LVJgFtOO8C/95UWY9tKuToRfndXv+99c1d1o85C97KE7C1
zREnTgIf990e5gx2KQCA5irELpKltu0g1wDfbD6hCxJhuvsg869Q0JcXcktg8c0D
sbJQWZrlr9i7TG6TEs7bWxH77hOdrpPyaRUiELt8ZfJJrrctYaY4ogd8NDctDbma
WJWdco8kyiWauoRBJuJJwRtTTMQ+JBiomOhDb1moQd19lNQiBjW5pTfr92NSVg==
-----END RSA PRIVATE KEY-----

View File

@@ -757,7 +757,7 @@ static int charset_auto(MYSQL *my __attribute__((unused)))
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "auto");
FAIL_IF(!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0),
password, schema, port, socketname, 0, 1),
mysql_error(mysql));
csname1= mysql_character_set_name(mysql);

View File

@@ -65,7 +65,7 @@ static int test_conc66(MYSQL *my)
rc= mysql_query(my, "FLUSH PRIVILEGES");
check_mysql_rc(rc, my);
if (!my_test_connect(mysql, hostname, NULL,
NULL, schema, port, socketname, 0))
NULL, schema, port, socketname, 0, 1))
{
diag("user: %s", mysql->options.user);
diag("Error: %s", mysql_error(mysql));
@@ -463,7 +463,7 @@ static int test_bug31669(MYSQL *mysql)
static int test_bug33831(MYSQL *mysql)
{
FAIL_IF(my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0),
password, schema, port, socketname, 0, 1),
"Error expected");
return OK;
@@ -493,7 +493,7 @@ static int test_opt_reconnect(MYSQL *mysql)
if (!(my_test_connect(mysql, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
mysql_close(mysql);
@@ -513,7 +513,7 @@ static int test_opt_reconnect(MYSQL *mysql)
if (!(my_test_connect(mysql, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
mysql_close(mysql);
@@ -544,7 +544,7 @@ static int test_compress(MYSQL *mysql)
if (!(my_test_connect(mysql, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
return FAIL;
@@ -583,7 +583,7 @@ static int test_reconnect(MYSQL *mysql)
if (!(my_test_connect(mysql1, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
return FAIL;
@@ -647,14 +647,14 @@ int test_conc26(MYSQL *unused __attribute__((unused)))
MYSQL *mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "ascii");
FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS),
FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1),
"Error expected");
FAIL_IF(!mysql->options.charset_name || strcmp(mysql->options.charset_name, "ascii") != 0,
"expected charsetname=ascii");
mysql_close(mysql);
mysql= mysql_init(NULL);
FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, 0),
FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, 0, 1),
"Error expected");
FAIL_IF(mysql->options.charset_name, "Error: options not freed");
mysql_close(mysql);
@@ -669,7 +669,7 @@ int test_connection_timeout(MYSQL *unused __attribute__((unused)))
MYSQL *mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
start= time(NULL);
if (my_test_connect(mysql, "192.168.1.101", "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (my_test_connect(mysql, "192.168.1.101", "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Error expected - maybe you have to change hostname");
return FAIL;
@@ -697,7 +697,7 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(7)");
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &no);
start= time(NULL);
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
elapsed= time(NULL) - start;
diag("elapsed: %lu", (unsigned long)elapsed);
@@ -723,7 +723,7 @@ int test_connection_timeout3(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(6)");
start= time(NULL);
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("timeout error expected");
elapsed= time(NULL) - start;
@@ -740,7 +740,7 @@ int test_connection_timeout3(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -801,7 +801,7 @@ static int test_wrong_bind_address(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_BIND, bind_addr);
if (my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error expected");
mysql_close(mysql);
@@ -848,7 +848,7 @@ static int test_bind_address(MYSQL *my)
mysql_options(mysql, MYSQL_OPT_BIND, bind_addr);
if (!my_test_connect(mysql, bind_addr, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s\n", mysql_error(mysql));
mysql_close(mysql);
@@ -1081,7 +1081,7 @@ static int test_unix_socket_close(MYSQL *unused __attribute__((unused)))
for (i=0; i < 10000; i++)
{
my_test_connect(mysql, "localhost", "user", "passwd", NULL, 0, "./dummy_sock", 0);
my_test_connect(mysql, "localhost", "user", "passwd", NULL, 0, "./dummy_sock", 0, 1);
/* check if we run out of sockets */
if (mysql_errno(mysql) == 2001)
{
@@ -1194,7 +1194,7 @@ static int test_auth256(MYSQL *my)
rc= mysql_query(my, query);
check_mysql_rc(rc, my);
if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0))
if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0, 1))
{
diag("error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -1204,7 +1204,7 @@ static int test_auth256(MYSQL *my)
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, "rsa_public_key.pem");
if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0))
if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0, 1))
{
diag("error: %s", mysql_error(mysql));
diag("host: %s", this_host);
@@ -1240,7 +1240,7 @@ static int test_mdev13100(MYSQL *my __attribute__((unused)))
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1265,7 +1265,7 @@ static int test_mdev13100(MYSQL *my __attribute__((unused)))
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1292,7 +1292,7 @@ if (!(fp= fopen("./mdev13100.cnf", "w")))
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1322,7 +1322,7 @@ if (!(fp= fopen("./mdev13100.cnf", "w")))
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1350,7 +1350,7 @@ if (!(fp= fopen("./mdev13100.cnf", "w")))
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1373,7 +1373,7 @@ static int test_conc276(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(mysql, MYSQL_OPT_RECONNECT, &val);
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0, 1))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -1423,7 +1423,7 @@ static int test_expired_pw(MYSQL *my)
mysql= mysql_init(NULL);
my_test_connect(mysql, hostname, "foo", "foo", schema,
port, socketname, 0);
port, socketname, 0, 1);
FAIL_IF(!mysql_errno(mysql), "Error expected");
mysql_close(mysql);
@@ -1432,7 +1432,7 @@ static int test_expired_pw(MYSQL *my)
mysql_optionsv(mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, &expire);
my_test_connect(mysql, hostname, "foo", "foo", schema,
port, socketname, 0);
port, socketname, 0, 1);
/* we should be in sandbox mode now, only set commands should be allowed */
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
@@ -1503,7 +1503,7 @@ static int test_conc317(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);
@@ -1551,7 +1551,7 @@ static int test_conc327(MYSQL *unused __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);
remove(cnf_file2);
@@ -1575,7 +1575,7 @@ static int test_conc327(MYSQL *unused __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file2);
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);
remove(cnf_file2);
@@ -1601,7 +1601,7 @@ static int test_conc332(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4");
my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0);
port, socketname, 0, 1);
FAIL_IF(mysql_errno(mysql), "Error during connect");
@@ -1640,7 +1640,7 @@ static int test_conc351(MYSQL *unused __attribute__((unused)))
ulong capabilities= 0;
my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0);
port, socketname, 0, 1);
FAIL_IF(mysql_errno(mysql), "Error during connect");
@@ -1690,7 +1690,7 @@ static int test_conc312(MYSQL *my)
check_mysql_rc(rc, my);
mysql= mysql_init(NULL);
if (!my_test_connect(mysql, hostname, "foo", "foo", schema, port, socketname, 0))
if (!my_test_connect(mysql, hostname, "foo", "foo", schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
return FAIL;
@@ -1749,7 +1749,7 @@ static int test_conc366(MYSQL *mysql)
my= mysql_init(NULL);
if (plugindir)
mysql_options(my, MYSQL_PLUGIN_DIR, plugindir);
if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0))
if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(my));
return FAIL;
@@ -1811,7 +1811,7 @@ static int test_conc443(MYSQL *my __attribute__((unused)))
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=3");
mysql_options(mysql, MYSQL_OPT_RECONNECT, &x);
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -1857,7 +1857,7 @@ static int test_default_auth(MYSQL *my __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_DEFAULT_AUTH, "mysql_clear_password");
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -1868,7 +1868,7 @@ static int test_default_auth(MYSQL *my __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_DEFAULT_AUTH, "caching_sha2_password");
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -1926,7 +1926,7 @@ static int test_conc490(MYSQL *my __attribute__((unused)))
MYSQL *mysql= mysql_init(NULL);
if (!my_test_connect(mysql, hostname, username,
password, NULL, port, socketname, CLIENT_CONNECT_WITH_DB))
password, NULL, port, socketname, CLIENT_CONNECT_WITH_DB, 1))
{
diag("error: %s\n", mysql_error(mysql));
return FAIL;
@@ -1961,7 +1961,7 @@ static int test_conc544(MYSQL *mysql)
check_mysql_rc(rc, mysql);
if (my_test_connect(my, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("error expected (restricted auth)");
return FAIL;
@@ -1984,7 +1984,7 @@ static int test_conc544(MYSQL *mysql)
if (plugindir)
mysql_optionsv(my, MYSQL_PLUGIN_DIR, plugindir);
mysql_optionsv(my, MARIADB_OPT_RESTRICTED_AUTH, "client_ed25519, mysql_native_password");
if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0))
if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(my));
return FAIL;
@@ -2059,7 +2059,7 @@ static int test_conn_str_1(MYSQL *my __attribute__((unused)))
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
check_mysql_rc(rc, mysql);
if (!my_test_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0))
if (!my_test_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
remove("./conc274.cnf");
@@ -2102,7 +2102,7 @@ static int test_conc365(MYSQL *my __attribute__((unused)))
mysql= mysql_init(NULL);
snprintf(tmp, sizeof(tmp) -1, "127.0.0.1:3300,%s:%d", hostname ? hostname : "localhost", port);
if (!my_test_connect(mysql, tmp, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
rc= FAIL;
@@ -2116,7 +2116,7 @@ static int test_conc365(MYSQL *my __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MARIADB_OPT_HOST, tmp);
if (!my_test_connect(mysql, NULL, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
rc= FAIL;
@@ -2151,13 +2151,14 @@ static int test_conc365_reconnect(MYSQL *my)
}
if (!my_test_connect(mysql, tmp, username,
password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Error: %s", mysql_error(mysql));
rc= FAIL;
}
sprintf(tmp, "KILL %ld", mysql_thread_id(mysql));
diag("KILL %ld", mysql_thread_id(mysql));
rc= mysql_query(my, tmp);
check_mysql_rc(rc, my);
@@ -2232,7 +2233,7 @@ static int test_status_callback(MYSQL *my __attribute__((unused)))
rc= mysql_optionsv(mysql, MARIADB_OPT_STATUS_CALLBACK, my_status_callback, &data);
if (!my_test_connect(mysql, hostname, username,
password, NULL, port, socketname, 0))
password, NULL, port, socketname, 0, 1))
{
diag("error1: %s", mysql_error(mysql));
return FAIL;
@@ -2278,7 +2279,7 @@ static int test_conc632(MYSQL *my __attribute__((unused)))
MYSQL *mysql= mysql_init(NULL);
int rc;
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -2329,7 +2330,7 @@ static int test_x509(MYSQL *my __attribute__((unused)))
mysql_options(mysql1, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
if (!(my_test_connect(mysql1, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
return FAIL;
@@ -2339,7 +2340,7 @@ static int test_x509(MYSQL *my __attribute__((unused)))
mysql_options(mysql2, MARIADB_OPT_TLS_PEER_FP, info->fingerprint);
if (!(my_test_connect(mysql2, hostname, username,
password, schema, port,
socketname, 0)))
socketname, 0, 1)))
{
diag("connection failed");
return FAIL;
@@ -2363,7 +2364,7 @@ static int test_conc505(MYSQL *my __attribute__((unused)))
#define CLIENT_DEPRECATE_EOF (1ULL << 24)
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_DEPRECATE_EOF))
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_DEPRECATE_EOF, 1))
{
diag("Error expected: Invalid client flag");
mysql_close(mysql);
@@ -2371,7 +2372,7 @@ static int test_conc505(MYSQL *my __attribute__((unused)))
}
diag("Error (expected): %s", mysql_error(mysql));
FAIL_IF(mysql_errno(mysql) != CR_INVALID_CLIENT_FLAG, "Wrong error number");
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS))
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);

View File

@@ -991,7 +991,7 @@ static int test_connect_attrs(MYSQL *my)
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo2", "bar2");
FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
if (!(mysql->server_capabilities & CLIENT_CONNECT_ATTRS))
{
@@ -1041,7 +1041,7 @@ static int test_conc117(MYSQL *unused __attribute__((unused)))
MYSQL *my= mysql_init(NULL);
SKIP_MAXSCALE;
FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
mysql_kill(my, mysql_thread_id(my));
@@ -1060,7 +1060,7 @@ static int test_read_timeout(MYSQL *unused __attribute__((unused)))
SKIP_MAXSCALE;
mysql_options(my, MYSQL_OPT_READ_TIMEOUT, &timeout);
FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
rc= mysql_query(my, "SELECT SLEEP(50)");
@@ -1136,7 +1136,7 @@ static int test_remote2(MYSQL *my)
mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "http://localhost/test.cnf");
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "test");
my_test_connect(mysql, hostname, username, password, schema,
0, socketname, 0), mysql_error(my);
0, socketname, 0, 1), mysql_error(my);
diag("port: %d", mysql->port);
mysql_close(mysql);
return OK;
@@ -1177,7 +1177,7 @@ static int test_mdev12965(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);
@@ -1461,7 +1461,7 @@ static int test_conc395(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);
@@ -1501,7 +1501,7 @@ static int test_sslenforce(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0);
schema, port, socketname, 0, 1);
remove(cnf_file1);

View File

@@ -219,12 +219,13 @@ MYSQL *my_test_connect(MYSQL *mysql,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long clientflag);
unsigned long clientflag,
my_bool auto_fingerprint);
static const char *schema = 0;
static char *hostname = 0;
static char *password = 0;
static char fingerprint[65]= {0};
static char fingerprint[129]= {0};
static unsigned int port = 0;
static unsigned int ssl_port = 0;
static char *socketname = 0;
@@ -542,7 +543,7 @@ MYSQL *test_connect(struct my_tests_st *test)
}
}
if (!(my_test_connect(mysql, hostname, username, password,
schema, port, socketname, (test) ? test->connect_flags:0)))
schema, port, socketname, (test) ? test->connect_flags:0, 1)))
{
diag("Couldn't establish connection to server %s. Error (%d): %s",
hostname, mysql_errno(mysql), mysql_error(mysql));
@@ -654,12 +655,18 @@ MYSQL *my_test_connect(MYSQL *mysql,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long clientflag)
unsigned long clientflag,
my_bool auto_fingerprint)
{
char *have_fp;
if (force_tls)
mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &force_tls);
if (fingerprint[0])
mysql_get_optionv(mysql, MARIADB_OPT_SSL_FP, &have_fp);
if (fingerprint[0] && auto_fingerprint)
{
printf("setting fingerprint\n");
mysql_options(mysql, MARIADB_OPT_SSL_FP, fingerprint);
}
if (!mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, clientflag))
{
diag("error: %s", mysql_error(mysql));
@@ -712,11 +719,12 @@ void run_tests(struct my_tests_st *test) {
mysql_free_result(res);
if (mysql_get_ssl_cipher(mysql))
diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info);
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info, 384);
if (info)
{
strcpy(fingerprint, info->fingerprint);
diag("Peer certificate fingerprint: %s", fingerprint);
diag("Subject: %s", info->subject);
diag("--------------------");
}
}

View File

@@ -63,7 +63,7 @@ static int test_conc83(MYSQL *unused __attribute__((unused)))
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_IF(!(my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0)), "my_test_connect failed");
schema, port, socketname, 0, 1)), "my_test_connect failed");
/* 1. Status is inited, so prepare should work */
@@ -845,7 +845,7 @@ static int test_prepare_alter(MYSQL *mysql)
mysql_new= mysql_init(NULL);
FAIL_IF(!mysql_new, "mysql_init failed");
FAIL_IF(!(my_test_connect(mysql_new, hostname, username, password,
schema, port, socketname, 0)), "my_test_connect failed");
schema, port, socketname, 0, 1)), "my_test_connect failed");
rc= mysql_query(mysql_new, "ALTER TABLE test_prep_alter change id id_new varchar(20)");
diag("Error: %d %s", mysql_errno(mysql_new), mysql_error(mysql_new));
check_mysql_rc(rc, mysql_new);

View File

@@ -44,7 +44,7 @@ static int test_rpl_async(MYSQL *my __attribute__((unused)))
return SKIP;
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -112,7 +112,7 @@ static int test_rpl_semisync(MYSQL *my __attribute__((unused)))
return SKIP;
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -189,7 +189,7 @@ static int test_conc467(MYSQL *my __attribute__((unused)))
return SKIP;
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -271,7 +271,7 @@ static int test_conc592(MYSQL *my __attribute__((unused)))
return SKIP;
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -279,7 +279,7 @@ static int test_conc592(MYSQL *my __attribute__((unused)))
}
if (!my_test_connect(mysql_check, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
@@ -356,7 +356,7 @@ static int test_conc689(MYSQL *my __attribute__((unused)))
return SKIP;
if (!my_test_connect(mysql, hostname, username,
password, schema, port, socketname, 0))
password, schema, port, socketname, 0, 1))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);

View File

@@ -15,7 +15,7 @@ static int basic_connect(MYSQL *unused __attribute__((unused)))
FAIL_IF(!my, "mysql_init() failed");
FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
port, socketname, 0), mysql_error(my));
port, socketname, 0, 1), mysql_error(my));
rc= mysql_query(my, "SELECT @@version");
check_mysql_rc(rc, my);
@@ -136,7 +136,7 @@ DWORD WINAPI thread_conc27(void)
mysql_thread_init();
mysql= mysql_init(NULL);
if(!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0))
port, socketname, 0, 1))
{
diag(">Error: %s", mysql_error(mysql));
mysql_close(mysql);

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

157
unittest/libmariadb/tls_server.py Executable file
View File

@@ -0,0 +1,157 @@
import socket
import ssl
import argparse
from ast import literal_eval
from OpenSSL import crypto, SSL
import os
class TlsServer():
def __init__(self, *args, **kwargs):
self.host= kwargs.pop("host", "127.0.0.1")
self.port= kwargs.pop("port", 50000)
self.server= None
self.end= False
try:
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
print("# tls dummy_server started: ", self.host, self.port)
self.server.listen()
except Exception as e:
print("Couldn't start tls_server")
print(e)
def check_server(self):
if not self.server:
raise Exception("Server not started")
def send_server_hello(self, conn):
self.check_server()
try:
conn.sendall(server_hello)
except Exception as e:
print("Couldn't send server_hello")
print(e)
return 0
return 1
def generate_cert(self,
create_new=False,
create_crl=False,
emailAddress="emailAddress",
commonName="commonName",
countryName="NT",
localityName="localityName",
stateOrProvinceName="stateOrProvinceName",
organizationName="organizationName",
organizationUnitName="organizationUnitName",
serialNumber=123,
validityStartInSeconds=0,
validityEndInSeconds=10*365*24*60*60,
KEY_FILE = "privkey.pem",
CRL_FILE = "selfsigned.crl",
CERT_FILE="selfsigned.pem"):
self.key_file= KEY_FILE
self.cert_file= CERT_FILE
self.crl_file = CRL_FILE
if create_new:
try:
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 4096)
# create a self-signed cert
cert = crypto.X509()
cert.get_subject().C = countryName
cert.get_subject().ST = stateOrProvinceName
cert.get_subject().L = localityName
cert.get_subject().O = organizationName
cert.get_subject().OU = organizationUnitName
cert.get_subject().CN = commonName
cert.get_subject().emailAddress = emailAddress
cert.set_serial_number(serialNumber)
cert.gmtime_adj_notBefore(validityStartInSeconds)
cert.gmtime_adj_notAfter(validityEndInSeconds)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, 'sha512')
with open(CERT_FILE, "wt") as f:
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
with open(KEY_FILE, "wt") as f:
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"))
return 1
except Exception as e:
return 0
return 1
def set_tls_context(self, reply):
kwargs= {}
if len(reply) > 0:
cmds= reply.decode()
kwargs= dict((k, literal_eval(v)) for k, v in (pair.split('=') for pair in cmds.split()))
print("# command: ", kwargs)
if self.generate_cert(**kwargs):
print("# loading certs", self.cert_file, self.key_file)
self.context= ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
self.context.load_cert_chain(self.cert_file, self.key_file)
return 1
return 0
def accept(self):
self.check_server()
conn, addr= self.server.accept()
return (conn, addr)
def run(self):
while not self.end:
connection, address= self.accept()
print("# new connection")
self.send_server_hello(connection)
reply= connection.recv(4096)
if reply[:4] == b'CMD:':
if self.set_tls_context(reply[4:]):
connection.sendall(b'OK')
elif reply[:4] == b'QUIT':
print("# exiting tls_dummy_server")
try:
connection.close()
except:
pass
return
else:
try:
tls_sock= self.context.wrap_socket(connection, server_side=True)
except Exception as e:
print("error occured")
print(e)
connection.close()
connection.close()
# Hardcoded server hello packet (captured from MariaDB Server 11.4.2)
server_hello = b'R\x00\x00\x00\n11.4.2-MariaDB\x00\xff\x01\x00\x00Nv\
*hQ;qK\x00\xfe\xff\x08\x02\x00\xff\x81\x15\x00\x00\x00\
\x00\x00\x00\x1d\x00\x00\x00`$-VIJyC!x[?\x00mysql_native_password\x00'
if __name__ == '__main__':
parser= argparse.ArgumentParser(
prog='tls_server',
description='Simple TLS dummy test server')
parser.add_argument('--host', help='Hostaddress of TLS test server (Default 127.0.0.1)')
parser.add_argument('--port', help='Port of TLS test server. (Default 50000)')
args= parser.parse_args()
if not (port := args.port):
port= 50000;
if not (host := args.host):
host= "127.0.0.1"
server= TlsServer(host=host, port=int(port))
print("# Starting tls_dummy_server")
server.run()