diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index 4782be62..f444042b 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -723,6 +723,26 @@ const struct st_cipher_map tls_ciphers[]= "TLS_DH_anon_WITH_AES_256_GCM_SHA384", NULL, "TLS_DH_ANON_AES_256_GCM_SHA384"}, + { {0x13, 0x01}, + "TLS_AES_128_GCM_SHA256", + "TLS_AES_128_GCM_SHA256", + "TLS_AES_128_GCM_SHA256"}, + { {0x13, 0x02}, + "TLS_AES_256_GCM_SHA384", + "TLS_AES_256_GCM_SHA384", + "TLS_AES_256_GCM_SHA384"}, + { {0x13, 0x03}, + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_CHACHA20_POLY1305_SHA256"}, + { {0x13, 0x04}, + "TLS_AES_128_CCM_SHA256", + "TLS_AES_128_CCM_SHA256", + "TLS_AES_128_CCM_SHA256"}, + { {0x13, 0x05}, + "TLS_AES_128_CCM_8_SHA256", + "TLS_AES_128_CCM_8_SHA256", + "TLS_AES_128_CCM_8_SHA256"}, { {0xC0, 0x84}, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", NULL, @@ -793,6 +813,7 @@ const struct st_cipher_map tls_ciphers[]= NULL} }; +#if GNUTLS_VERSION_NUMBER < 0x030704 /* map the gnutls cipher suite (defined by key exchange algorithm, cipher and mac algorithm) to the corresponding OpenSSL cipher name */ static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx, @@ -829,6 +850,7 @@ static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx, } return NULL; } +#endif /* get priority string for a given openssl cipher name */ static char *get_priority(const char *cipher_name, char *priority, size_t len) @@ -857,10 +879,20 @@ static char *get_priority(const char *cipher_name, char *priority, size_t len) { if (!strcmp(name, tls_ciphers[i].gnutls_name)) { - snprintf(priority, len - 1, ":+%s:+%s:+%s", - gnutls_cipher_get_name(cipher), - gnutls_mac_get_name(mac), - gnutls_kx_get_name(kx)); + const char *p; + + if ((p= gnutls_cipher_get_name(cipher))) + snprintf(priority, len - 1, ":+%s",p); + if ((p= gnutls_mac_get_name(mac))) + { + strncat(priority, ":+", len - 1); + strncat(priority, p, len - 1); + } + if ((p= gnutls_kx_get_name(kx))) + { + strncat(priority, ":+", len - 1); + strncat(priority, p, len - 1); + } return priority; } } @@ -1337,6 +1369,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused))) const char *ma_tls_get_cipher(MARIADB_TLS *ctls) { +#if GNUTLS_VERSION_NUMBER < 0x030704 gnutls_kx_algorithm_t kx; gnutls_cipher_algorithm_t cipher; gnutls_mac_algorithm_t mac; @@ -1348,6 +1381,24 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls) cipher= gnutls_cipher_get((gnutls_session_t)ctls->ssl); kx= gnutls_kx_get((gnutls_session_t)ctls->ssl); return openssl_cipher_name(kx, cipher, mac); +#else + const char *cs= gnutls_ciphersuite_get((gnutls_session_t)ctls->ssl); + int i=0; + + while (tls_ciphers[i].iana_name) + { + if (!strcmp(tls_ciphers[i].gnutls_name, cs)) + { + if (tls_ciphers[i].openssl_name) + return tls_ciphers[i].openssl_name; + if (tls_ciphers[i].gnutls_name) + return tls_ciphers[i].gnutls_name; + return tls_ciphers[i].iana_name; + } + i++; + } + return NULL; +#endif } static int my_verify_callback(gnutls_session_t ssl) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index a10e01bd..5d5ff542 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -2332,7 +2332,42 @@ static int test_conc505(MYSQL *my __attribute__((unused))) return OK; } +#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) +static int test_conc748(MYSQL *my __attribute__((unused))) +{ + MYSQL *mysql; + int i; + const char *ciphers[3]= {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"}; + + for (i=0; i < 3; i++) + { + const char *tls_version; + mysql= mysql_init(NULL); + + mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL); + mysql_optionsv(mysql, MYSQL_OPT_SSL_CIPHER, ciphers[i]); + + if (!my_test_connect(mysql, hostname, NULL, + NULL, schema, port, socketname, 0)) + { + diag("error: %s", mysql_error(mysql)); + return FAIL; + } + + FAIL_IF(strcmp(ciphers[i], mysql_get_ssl_cipher(mysql)), "Cipher mismatch"); + mariadb_get_infov(mysql, MARIADB_CONNECTION_TLS_VERSION, &tls_version); + FAIL_IF(strcmp(tls_version, "TLSv1.3"), "TLS version mismatch"); + + mysql_close(mysql); + } + return OK; +} +#endif + struct my_tests_st my_tests[] = { +#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) + {"test_conc748", test_conc748, TEST_CONNECTION_NONE, 0, NULL, NULL}, +#endif {"test_conc505", test_conc505, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc632", test_conc632, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_status_callback", test_status_callback, TEST_CONNECTION_NONE, 0, NULL, NULL}, diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index f67d1366..5f6f854d 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -1534,6 +1534,41 @@ static int test_conc458(MYSQL *my __attribute__((unused))) return OK; } +static int test_conc163(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + + rc= mysql_query(mysql, "SET @a:=1"); + check_mysql_rc(rc, mysql); + + FAIL_IF(mysql_info(mysql) != NULL, "mysql_info: expected NULL"); + + rc= mysql_query(mysql, "CREATE OR REPLACE TABLE t1 AS SELECT 1"); + check_mysql_rc(rc, mysql); + + FAIL_IF(mysql_info(mysql) == NULL, "mysql_info: expected != NULL"); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mariadb_stmt_execute_direct(stmt, SL("SET @a:=1")); + check_stmt_rc(rc, stmt); + FAIL_IF(mysql_info(mysql) != NULL, "mysql_info: expected NULL"); + + rc= mariadb_stmt_execute_direct(stmt, SL("CREATE OR REPLACE TABLE t1 AS SELECT 1")); + check_stmt_rc(rc, stmt); + FAIL_IF(mysql_info(mysql) == NULL, "mysql_info: expected != NULL"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + static int test_conc533(MYSQL *mysql) { @@ -1631,6 +1666,7 @@ static int test_ext_field_attr(MYSQL *mysql) struct my_tests_st my_tests[] = { {"test_ext_field_attr", test_ext_field_attr, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc533", test_conc533, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_conc163", test_conc163, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc458", test_conc458, TEST_CONNECTION_NONE, 0, NULL, NULL}, #if !__has_feature(memory_sanitizer) {"test_conc457", test_conc457, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index 2fcbd90e..8eb3ba2a 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -5854,8 +5854,56 @@ static int test_conc739(MYSQL *mysql) return OK; } +static int test_conc176(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind; + char buffer[9]; + + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int(8) zerofill)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, "SELECT a FROM t1", -1); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + + bind.buffer= buffer; + bind.buffer_type= MYSQL_TYPE_STRING; + bind.buffer_length= 9; + + rc= mysql_stmt_bind_result(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + + diag("Buffer: %s", buffer); + FAIL_IF(strlen(buffer) == 1, "Expected zerofilled string"); + + rc= mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + + struct my_tests_st my_tests[] = { {"test_conc702", test_conc702, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc176", test_conc176, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc739", test_conc739, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc633", test_conc633, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc623", test_conc623, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},