1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-08 14:02:17 +03:00

Merge branch '3.1' into 3.3

This commit is contained in:
Georg Richter
2022-07-18 11:48:33 +02:00
8 changed files with 76 additions and 69 deletions

View File

@@ -145,6 +145,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int f
int ma_tls_get_protocol_version(MARIADB_TLS *ctls); int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
const char *ma_pvio_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); int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls);
void ma_tls_set_connection(MYSQL *mysql);
/* Function prototypes */ /* Function prototypes */
MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql); MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql);
@@ -156,6 +157,7 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls);
const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls); 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_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list);
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio); my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
void ma_pvio_tls_set_connection(MYSQL *mysql);
void ma_pvio_tls_end(); void ma_pvio_tls_end();
#endif /* _ma_tls_h_ */ #endif /* _ma_tls_h_ */

View File

@@ -229,4 +229,9 @@ end:
} }
return rc; return rc;
} }
void ma_pvio_tls_set_connection(MYSQL *mysql)
{
return ma_tls_set_connection(mysql);
}
#endif /* HAVE_TLS */ #endif /* HAVE_TLS */

View File

@@ -2098,6 +2098,11 @@ my_bool STDCALL mariadb_reconnect(MYSQL *mysql)
mysql_close(mysql); mysql_close(mysql);
*mysql=tmp_mysql; *mysql=tmp_mysql;
mysql->net.pvio->mysql= mysql; mysql->net.pvio->mysql= mysql;
#ifdef HAVE_TLS
/* CONC-604: Set new connection handle */
if (mysql_get_ssl_cipher(mysql))
ma_pvio_tls_set_connection(mysql);
#endif
ma_net_clear(&mysql->net); ma_net_clear(&mysql->net);
mysql->affected_rows= ~(unsigned long long) 0; mysql->affected_rows= ~(unsigned long long) 0;
mysql->info= 0; mysql->info= 0;

View File

@@ -50,12 +50,6 @@ static int my_verify_callback(gnutls_session_t ssl);
char tls_library_version[TLS_VERSION_LENGTH]; char tls_library_version[TLS_VERSION_LENGTH];
struct st_gnutls_data {
MYSQL *mysql;
gnutls_privkey_t key;
gnutls_pcert_st cert;
};
struct st_cipher_map { struct st_cipher_map {
unsigned char sid[2]; unsigned char sid[2];
const char *iana_name; const char *iana_name;
@@ -799,18 +793,6 @@ const struct st_cipher_map tls_ciphers[]=
NULL} NULL}
}; };
/* free data assigned to the connection */
static void free_gnutls_data(struct st_gnutls_data *data)
{
if (data)
{
if (data->key)
gnutls_privkey_deinit(data->key);
gnutls_pcert_deinit(&data->cert);
free(data);
}
}
/* map the gnutls cipher suite (defined by key exchange algorithm, cipher /* map the gnutls cipher suite (defined by key exchange algorithm, cipher
and mac algorithm) to the corresponding OpenSSL cipher name */ and mac algorithm) to the corresponding OpenSSL cipher name */
static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx, static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx,
@@ -912,20 +894,19 @@ static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno)
alert_name= gnutls_alert_get_name(alert_desc); alert_name= gnutls_alert_get_name(alert_desc);
snprintf(ssl_error, MAX_SSL_ERR_LEN, "fatal alert received: %s", snprintf(ssl_error, MAX_SSL_ERR_LEN, "fatal alert received: %s",
alert_name); alert_name);
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ssl_error);
ssl_error);
return; return;
} }
if ((ssl_error_reason= gnutls_strerror(ssl_errno))) if ((ssl_error_reason= gnutls_strerror(ssl_errno)))
{ {
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ssl_error_reason); ssl_error_reason);
return; return;
} }
snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%d", ssl_errno); snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%d", ssl_errno);
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ssl_error); ssl_error);
} }
@@ -1134,7 +1115,6 @@ void *ma_tls_init(MYSQL *mysql)
gnutls_session_t ssl= NULL; gnutls_session_t ssl= NULL;
gnutls_certificate_credentials_t ctx; gnutls_certificate_credentials_t ctx;
int ssl_error= 0; int ssl_error= 0;
struct st_gnutls_data *data= NULL;
pthread_mutex_lock(&LOCK_gnutls_config); pthread_mutex_lock(&LOCK_gnutls_config);
@@ -1144,15 +1124,13 @@ void *ma_tls_init(MYSQL *mysql)
if ((ssl_error= ma_tls_set_certs(mysql, ctx)) < 0) if ((ssl_error= ma_tls_set_certs(mysql, ctx)) < 0)
goto error; goto error;
if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT & GNUTLS_NONBLOCK)) < 0) if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT | GNUTLS_NONBLOCK | GNUTLS_NO_SIGNAL)) < 0)
goto error; goto error;
if (!(data= (struct st_gnutls_data *)calloc(1, sizeof(struct st_gnutls_data)))) gnutls_session_set_ptr(ssl, (void *)mysql);
goto error; /*
gnutls_certificate_set_retrieve_function2(GNUTLS_xcred, client_cert_callback);
data->mysql= mysql; */
gnutls_session_set_ptr(ssl, (void *)data);
ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher, mysql->options.extension ? mysql->options.extension->tls_version : NULL); ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher, mysql->options.extension ? mysql->options.extension->tls_version : NULL);
if (ssl_error < 0) if (ssl_error < 0)
goto error; goto error;
@@ -1165,7 +1143,6 @@ void *ma_tls_init(MYSQL *mysql)
pthread_mutex_unlock(&LOCK_gnutls_config); pthread_mutex_unlock(&LOCK_gnutls_config);
return (void *)ssl; return (void *)ssl;
error: error:
free_gnutls_data(data);
ma_tls_set_error(mysql, ssl, ssl_error); ma_tls_set_error(mysql, ssl, ssl_error);
gnutls_certificate_free_credentials(ctx); gnutls_certificate_free_credentials(ctx);
if (ssl) if (ssl)
@@ -1200,12 +1177,9 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
{ {
gnutls_session_t ssl = (gnutls_session_t)ctls->ssl; gnutls_session_t ssl = (gnutls_session_t)ctls->ssl;
my_bool blocking; my_bool blocking;
MYSQL *mysql; MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
MARIADB_PVIO *pvio; MARIADB_PVIO *pvio;
int ret; int ret;
struct st_gnutls_data *data;
data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl);
mysql= data->mysql;
if (!mysql) if (!mysql)
return 1; return 1;
@@ -1307,9 +1281,13 @@ ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
while ((rc= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0) while ((rc= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
{ {
if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED) if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
return rc; break;
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1) if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
return rc; break;
}
if (rc <= 0) {
MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
ma_tls_set_error(mysql, ctls->ssl, rc);
} }
return rc; return rc;
} }
@@ -1322,9 +1300,13 @@ ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
while ((rc= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0) while ((rc= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
{ {
if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED) if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
return rc; break;
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1) if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
return rc; break;
}
if (rc <= 0) {
MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
ma_tls_set_error(mysql, ctls->ssl, rc);
} }
return rc; return rc;
} }
@@ -1334,14 +1316,11 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
if (ctls->ssl) if (ctls->ssl)
{ {
gnutls_certificate_credentials_t ctx; gnutls_certificate_credentials_t ctx;
struct st_gnutls_data *data=
(struct st_gnutls_data *)gnutls_session_get_ptr(ctls->ssl);
/* this would be the correct way, however can't detect afterwards /* this would be the correct way, however can't detect afterwards
if the socket is closed or not, so we don't send encrypted if the socket is closed or not, so we don't send encrypted
finish alert. finish alert.
rc= gnutls_bye((gnutls_session_t )ctls->ssl, GNUTLS_SHUT_WR); rc= gnutls_bye((gnutls_session_t )ctls->ssl, GNUTLS_SHUT_WR);
*/ */
free_gnutls_data(data);
gnutls_credentials_get(ctls->ssl, GNUTLS_CRD_CERTIFICATE, (void **)&ctx); gnutls_credentials_get(ctls->ssl, GNUTLS_CRD_CERTIFICATE, (void **)&ctx);
gnutls_certificate_free_keys(ctx); gnutls_certificate_free_keys(ctx);
gnutls_certificate_free_cas(ctx); gnutls_certificate_free_cas(ctx);
@@ -1378,10 +1357,7 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
static int my_verify_callback(gnutls_session_t ssl) static int my_verify_callback(gnutls_session_t ssl)
{ {
unsigned int status= 0; unsigned int status= 0;
struct st_gnutls_data *data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl); MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
MYSQL *mysql;
mysql= data->mysql;
CLEAR_CLIENT_ERROR(mysql); CLEAR_CLIENT_ERROR(mysql);
@@ -1425,13 +1401,11 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int l
size_t fp_len= len; size_t fp_len= len;
const gnutls_datum_t *cert_list; const gnutls_datum_t *cert_list;
unsigned int cert_list_size; unsigned int cert_list_size;
struct st_gnutls_data *data;
if (!ctls || !ctls->ssl) if (!ctls || !ctls->ssl)
return 0; return 0;
data= (struct st_gnutls_data *)gnutls_session_get_ptr(ctls->ssl); mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
mysql= (MYSQL *)data->mysql;
cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size); cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
if (cert_list == NULL) if (cert_list == NULL)
@@ -1460,4 +1434,9 @@ int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
return gnutls_protocol_get_version(ctls->ssl) - 1; return gnutls_protocol_get_version(ctls->ssl) - 1;
} }
void ma_tls_set_connection(MYSQL *mysql)
{
(void)gnutls_session_set_ptr(mysql->net.pvio->ctls->ssl, (void *)mysql);
}
#endif /* HAVE_GNUTLS */ #endif /* HAVE_GNUTLS */

View File

@@ -591,16 +591,14 @@ ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
{ {
int error= SSL_get_error((SSL *)ctls->ssl, rc); int error= SSL_get_error((SSL *)ctls->ssl, rc);
if (error != SSL_ERROR_WANT_READ) if (error != SSL_ERROR_WANT_READ)
{ break;
if (error == SSL_ERROR_SSL || errno == 0)
{
MYSQL *mysql= SSL_get_app_data(ctls->ssl);
ma_tls_set_error(mysql);
}
return rc;
}
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1) if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
return rc; break;
}
if (rc <= 0)
{
MYSQL *mysql= SSL_get_app_data(ctls->ssl);
ma_tls_set_error(mysql);
} }
return rc; return rc;
} }
@@ -614,16 +612,14 @@ ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
{ {
int error= SSL_get_error((SSL *)ctls->ssl, rc); int error= SSL_get_error((SSL *)ctls->ssl, rc);
if (error != SSL_ERROR_WANT_WRITE) if (error != SSL_ERROR_WANT_WRITE)
{ break;
if (error == SSL_ERROR_SSL || errno == 0)
{
MYSQL *mysql= SSL_get_app_data(ctls->ssl);
ma_tls_set_error(mysql);
}
return rc;
}
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1) if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
return rc; break;
}
if (rc <= 0)
{
MYSQL *mysql= SSL_get_app_data(ctls->ssl);
ma_tls_set_error(mysql);
} }
return rc; return rc;
} }
@@ -782,3 +778,8 @@ int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
return SSL_version(ctls->ssl) & 0xFF; return SSL_version(ctls->ssl) & 0xFF;
} }
void ma_tls_set_connection(MYSQL *mysql)
{
(void)SSL_set_app_data(mysql->net.pvio->ctls->ssl, mysql);
}

View File

@@ -560,3 +560,8 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int l
CertFreeCertificateContext(pRemoteCertContext); CertFreeCertificateContext(pRemoteCertContext);
return len; return len;
} }
void ma_tls_set_connection(MYSQL *mysql __attribute__((unused)))
{
return;
}

View File

@@ -682,13 +682,16 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
SKIP_SKYSQL; SKIP_SKYSQL;
SKIP_MAXSCALE; SKIP_MAXSCALE;
// SKIP_TLS;
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout); mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(6)"); mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(7)");
start= time(NULL); start= time(NULL);
if (my_test_connect(mysql, hostname, username, password, schema, port, NULL, CLIENT_REMEMBER_OPTIONS)) if (my_test_connect(mysql, hostname, username, password, schema, port, NULL, CLIENT_REMEMBER_OPTIONS))
{ {
elapsed= time(NULL) - start;
diag("elapsed: %lu", (unsigned long)elapsed);
diag("timeout error expected"); diag("timeout error expected");
return FAIL; return FAIL;
} }

View File

@@ -73,6 +73,13 @@ if (IS_SKYSQL(hostname)) \
#define SKIP_NOTLS #define SKIP_NOTLS
#endif #endif
#define SKIP_TLS \
if (force_tls)\
{\
diag("Test doesn't work with TLS");\
return SKIP;\
}
MYSQL *mysql_default = NULL; /* default connection */ MYSQL *mysql_default = NULL; /* default connection */
#define IS_MAXSCALE()\ #define IS_MAXSCALE()\