You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
Follow up of ffbdaaac2b
commit ffbdaaac2b
was incomplete, changes from ma_pvio.c
were missing. Beside this fix, this commit also contains necessary changes for GnuTLS.
This commit is contained in:
@@ -540,8 +540,7 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
|
||||
2. verify CN (requires option ssl_verify_check)
|
||||
3. verrify finger print
|
||||
*/
|
||||
if ((pvio->mysql->options.ssl_ca || pvio->mysql->options.ssl_capath) &&
|
||||
(pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
if ((pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
ma_pvio_tls_verify_server_cert(pvio->ctls))
|
||||
return 1;
|
||||
|
||||
|
@@ -1080,6 +1080,23 @@ static int ma_tls_set_certs(MYSQL *mysql,
|
||||
if (ssl_error < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mysql->options.ssl_capath)
|
||||
{
|
||||
ssl_error= gnutls_certificate_set_x509_trust_dir(ctx,
|
||||
mysql->options.ssl_capath,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
if (ssl_error < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
|
||||
{
|
||||
ssl_error= gnutls_certificate_set_x509_system_trust(ctx);
|
||||
if (ssl_error < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
gnutls_certificate_set_verify_function(ctx,
|
||||
my_verify_callback);
|
||||
|
||||
@@ -1211,7 +1228,11 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ma_tls_set_error(mysql, ssl, ret);
|
||||
/* If error message was not set while calling certification callback function,
|
||||
use default error message (which is not very descriptive */
|
||||
if (!mysql_errno(mysql))
|
||||
ma_tls_set_error(mysql, ssl, ret);
|
||||
|
||||
/* restore blocking mode */
|
||||
gnutls_deinit((gnutls_session_t )ctls->ssl);
|
||||
free_gnutls_data(data);
|
||||
@@ -1330,7 +1351,7 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
|
||||
|
||||
int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused)))
|
||||
{
|
||||
/* server verification is already handled before */
|
||||
/* server verification is already handled before during handshake */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1352,77 +1373,44 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
|
||||
static int my_verify_callback(gnutls_session_t ssl)
|
||||
{
|
||||
unsigned int status= 0;
|
||||
const gnutls_datum_t *cert_list;
|
||||
unsigned int cert_list_size;
|
||||
struct st_gnutls_data *data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl);
|
||||
MYSQL *mysql;
|
||||
MARIADB_PVIO *pvio;
|
||||
|
||||
gnutls_x509_crt_t cert;
|
||||
const char *hostname;
|
||||
|
||||
mysql= data->mysql;
|
||||
pvio= mysql->net.pvio;
|
||||
|
||||
/* read hostname */
|
||||
hostname = mysql->host;
|
||||
|
||||
/* This verification function uses the trusted CAs in the credentials
|
||||
* structure. So you must have installed one or more CA certificates.
|
||||
*/
|
||||
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
gnutls_certificate_verify_peers2 (ssl, &status) < 0)
|
||||
{
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CA verification failed");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
|
||||
if (status & GNUTLS_CERT_INVALID)
|
||||
{
|
||||
char errbuf[100];
|
||||
snprintf(errbuf, 99, "CA Verification failed (Status: %d)", status);
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, errbuf);
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
/* Up to here the process is the same for X.509 certificates and
|
||||
* OpenPGP keys. From now on X.509 certificates are assumed. This can
|
||||
* be easily extended to work with openpgp keys as well.
|
||||
*/
|
||||
if (gnutls_certificate_type_get (ssl) != GNUTLS_CRT_X509)
|
||||
{
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Expected X509 certificate");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
if (gnutls_x509_crt_init (&cert) < 0)
|
||||
{
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Error during certificate initialization");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
cert_list = gnutls_certificate_get_peers (ssl, &cert_list_size);
|
||||
if (cert_list == NULL)
|
||||
{
|
||||
gnutls_x509_crt_deinit (cert);
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "No certificate found");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
|
||||
{
|
||||
gnutls_x509_crt_deinit (cert);
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
|
||||
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
!gnutls_x509_crt_check_hostname (cert, hostname))
|
||||
{
|
||||
gnutls_x509_crt_deinit (cert);
|
||||
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
gnutls_x509_crt_deinit (cert);
|
||||
/* notify gnutls to continue handshake normally */
|
||||
|
||||
CLEAR_CLIENT_ERROR(mysql);
|
||||
|
||||
if ((mysql->client_flag & CLIENT_SSL_VERIFY_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;
|
||||
/* accept self signed certificates if we don't have to verify server cert */
|
||||
if (!(mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
(status & GNUTLS_CERT_SIGNER_NOT_FOUND))
|
||||
return 0;
|
||||
|
||||
/* gnutls default error mesage "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;
|
||||
}
|
||||
|
||||
|
@@ -530,9 +530,7 @@ static int ma_tls_set_certs(MYSQL *mysql, SSL *ssl)
|
||||
X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
|
||||
}
|
||||
}
|
||||
SSL_CTX_set_verify(ctx, (mysql->options.ssl_ca || mysql->options.ssl_capath) ||
|
||||
(mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ?
|
||||
SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@@ -648,7 +646,8 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
||||
pvio->methods->blocking(pvio, FALSE, 0);
|
||||
return 1;
|
||||
}
|
||||
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
|
||||
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ||
|
||||
(mysql->options.ssl_ca || mysql->options.ssl_capath))
|
||||
{
|
||||
rc= SSL_get_verify_result(ssl);
|
||||
if (rc != X509_V_OK)
|
||||
|
@@ -1329,7 +1329,7 @@ static int test_conc386(MYSQL *mysql)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#ifndef HAVE_SCHANNEL
|
||||
static int test_ssl_verify(MYSQL *my __attribute__((unused)))
|
||||
{
|
||||
MYSQL *mysql;
|
||||
@@ -1355,13 +1355,20 @@ static int test_ssl_verify(MYSQL *my __attribute__((unused)))
|
||||
port, socketname, 0), mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce);
|
||||
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0), mysql_error(mysql));
|
||||
|
||||
diag("cipher: %s", mysql_get_ssl_cipher(mysql));
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#ifdef HAVE_OPENSSL
|
||||
#ifndef HAVE_SCHANNEL
|
||||
{"test_ssl_verify", test_ssl_verify, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#endif
|
||||
{"test_mdev14101", test_mdev14101, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
|
Reference in New Issue
Block a user