diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index 04cbeebf..4208828b 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -86,7 +86,11 @@ static long ma_tls_version_options(const char *version) SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | - SSL_OP_NO_TLSv1_2; + SSL_OP_NO_TLSv1_2 +#ifdef TLS1_3_VERSION + | SSL_OP_NO_TLSv1_3 +#endif + ; if (!version) return 0; @@ -97,6 +101,10 @@ static long ma_tls_version_options(const char *version) protocol_options&= ~SSL_OP_NO_TLSv1_1; if (strstr(version, "TLSv1.2")) protocol_options&= ~SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + if (strstr(version, "TLSv1.3")) + protocol_options&= ~SSL_OP_NO_TLSv1_3; +#endif if (protocol_options != disable_all_protocols) return protocol_options; @@ -443,9 +451,15 @@ static int ma_tls_set_certs(MYSQL *mysql, SSL *ssl) /* add cipher */ if ((mysql->options.ssl_cipher && - mysql->options.ssl_cipher[0] != 0) && + mysql->options.ssl_cipher[0] != 0)) + { + if( +#ifdef TLS1_3_VERSION + SSL_set_ciphersuites(ssl, mysql->options.ssl_cipher) == 0 && +#endif SSL_set_cipher_list(ssl, mysql->options.ssl_cipher) == 0) goto error; + } /* ca_file and ca_path */ if (!SSL_CTX_load_verify_locations(ctx, @@ -704,12 +718,36 @@ ssize_t ma_tls_write_async(MARIADB_PVIO *pvio, ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length) { - return SSL_read((SSL *)ctls->ssl, (void *)buffer, (int)length); + ssize_t rc; + MYSQL *mysql= (MYSQL *)SSL_get_app_data(ctls->ssl); + MARIADB_PVIO *pvio= mysql->net.pvio; + + while ((rc= SSL_read((SSL *)ctls->ssl, (void *)buffer, (int)length)) < 0) + { + int error= SSL_get_error((SSL *)ctls->ssl, rc); + if (error != SSL_ERROR_WANT_READ) + return rc; + if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.read_timeout) < 1) + return rc; + } + return rc; } ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length) { - return SSL_write((SSL *)ctls->ssl, (void *)buffer, (int)length); + ssize_t rc; + MYSQL *mysql= (MYSQL *)SSL_get_app_data(ctls->ssl); + MARIADB_PVIO *pvio= mysql->net.pvio; + + while ((rc= SSL_write((SSL *)ctls->ssl, (void *)buffer, (int)length)) <= 0) + { + int error= SSL_get_error((SSL *)ctls->ssl, rc); + if (error != SSL_ERROR_WANT_WRITE) + return rc; + if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.write_timeout) < 1) + return rc; + } + return rc; } my_bool ma_tls_close(MARIADB_TLS *ctls) diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index 33c1fa6b..b4314a27 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -21,12 +21,14 @@ #include #ifdef HAVE_OPENSSL #include +#include #endif #define FNLEN 4096 static int skip_ssl= 1; static uchar have_openssl= 1; +static unsigned char have_tls13= 0; const char *ssluser= "ssluser"; const char *sslpw= "sslpw"; @@ -107,9 +109,23 @@ static int create_ssl_user(const char *ssluser, my_bool is_X509) static int test_ssl(MYSQL *mysql) { int rc; + unsigned int iversion; MYSQL_RES *res; MYSQL_ROW row; char *tls_library; + MYSQL *my= mysql_init(NULL); + + mysql_ssl_set(my,0, 0, 0, 0, 0); + + FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema, + port, socketname, 0), mysql_error(my)); + + mariadb_get_infov(my, MARIADB_CONNECTION_TLS_VERSION_ID, &iversion); + diag("iversion: %d", iversion); + if (iversion == 4) + have_tls13= 1; + + mysql_close(my); rc= mysql_query(mysql, "SELECT @@have_ssl, @@have_openssl"); check_mysql_rc(rc, mysql); @@ -904,12 +920,18 @@ static int test_cipher_mapping(MYSQL *unused __attribute__((unused))) { unsigned int i=0; const char *ciphers[]= { "DHE-RSA-AES256-GCM-SHA384", "DHE-RSA-AES256-SHA256", "DHE-RSA-AES256-SHA", - "DHE-RSA-CAMELLIA256-SHA", "AES256-GCM-SHA384", "AES256-SHA256", - "AES256-SHA", "CAMELLIA256-SHA", "DHE-RSA-AES128-GCM-SHA256", - "DHE-RSA-AES128-SHA256", "DHE-RSA-AES128-SHA", "DHE-RSA-CAMELLIA128-SHA", - "AES128-GCM-SHA256", "AES128-SHA256", "AES128-SHA", "CAMELLIA128-SHA", - "EDH-RSA-DES-CBC3-SHA", "DES-CBC3-SHA", "DHE-RSA-AES256-SHA", - "DHE-RSA-CAMELLIA256-SHA", "AES256-SHA", "CAMELLIA256-SHA", +#ifdef TEST_CAMELLIA_CIPHER + "DHE-RSA-CAMELLIA256-SHA", "CAMELLIA256-SHA", + "DHE-RSA-CAMELLIA128-SHA", "CAMELLIA128-SHA", +#endif +#ifdef TEST_DES_CIPHER + "EDH-RSA-DES-CBC3-SHA", + "DES-CBC3-SHA", +#endif + "AES256-GCM-SHA384", "AES256-SHA256", "AES256-SHA", + "DHE-RSA-AES128-GCM-SHA256", "DHE-RSA-AES128-SHA256", "DHE-RSA-AES128-SHA", + "AES128-GCM-SHA256", "AES128-SHA256", "AES128-SHA", + "DHE-RSA-AES256-SHA", "AES256-SHA", NULL }; diag("This test depends on OpenSSL version - since several ciphers might not be available"); @@ -933,6 +955,7 @@ static int test_cipher_mapping(MYSQL *unused __attribute__((unused))) int rc; const char *cipher; + mysql_options(mysql, MYSQL_OPT_TLS_VERSION, "TLSv1.0,TLSv1.1,TLSv1.2"); mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, ciphers[i]); diag("%s", ciphers[i]); @@ -980,6 +1003,9 @@ static int test_openssl_1(MYSQL *mysql) if (check_skip_ssl()) return SKIP; + if (have_tls13) + return SKIP; + if (!mariadb_connection(mysql)) return SKIP; @@ -1238,7 +1264,7 @@ static int test_mdev14101(MYSQL *my __attribute__((unused))) if (!combinations[i].do_yassl && skip_tlsv12) break; - diag("combination: %s", combinations[i].opt_tls_version); + diag("combination %d: %s", i, combinations[i].opt_tls_version); mysql= mysql_init(NULL); mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &val); @@ -1247,7 +1273,7 @@ static int test_mdev14101(MYSQL *my __attribute__((unused))) port, socketname, 0), mysql_error(mysql)); mariadb_get_infov(mysql, MARIADB_CONNECTION_TLS_VERSION, &tls_version); diag("options: %s", combinations[i].opt_tls_version); - diag("protocol: %s", tls_version); + diag("protocol: %s expected: %s", tls_version, combinations[i].expected); FAIL_IF(strcmp(combinations[i].expected, tls_version), "Wrong tls_version"); mysql_close(mysql); }