summaryrefslogtreecommitdiffstats
path: root/libmariadb
diff options
context:
space:
mode:
Diffstat (limited to 'libmariadb')
-rw-r--r--libmariadb/.travis.yml2
-rw-r--r--libmariadb/CMakeLists.txt22
-rw-r--r--libmariadb/cmake/plugins.cmake18
-rw-r--r--libmariadb/include/errmsg.h3
-rw-r--r--libmariadb/include/ma_common.h16
-rw-r--r--libmariadb/include/ma_config.h.in1
-rw-r--r--libmariadb/include/ma_crypt.h24
-rw-r--r--libmariadb/include/ma_tls.h7
-rw-r--r--libmariadb/include/mariadb_com.h10
-rw-r--r--libmariadb/include/mariadb_rpl.h5
-rw-r--r--libmariadb/include/mariadb_stmt.h8
-rw-r--r--libmariadb/include/mysql.h30
-rw-r--r--libmariadb/include/mysql/client_plugin.h3
-rw-r--r--libmariadb/libmariadb/CMakeLists.txt4
-rw-r--r--libmariadb/libmariadb/ma_charset.c2
-rw-r--r--libmariadb/libmariadb/ma_client_plugin.c.in5
-rw-r--r--libmariadb/libmariadb/ma_errmsg.c1
-rw-r--r--libmariadb/libmariadb/ma_pvio.c63
-rw-r--r--libmariadb/libmariadb/ma_tls.c103
-rw-r--r--libmariadb/libmariadb/mariadb_lib.c48
-rw-r--r--libmariadb/libmariadb/mariadb_rpl.c23
-rw-r--r--libmariadb/libmariadb/mariadb_stmt.c48
-rw-r--r--libmariadb/libmariadb/secure/gnutls.c96
-rw-r--r--libmariadb/libmariadb/secure/gnutls_crypt.c2
-rw-r--r--libmariadb/libmariadb/secure/ma_schannel.c7
-rw-r--r--libmariadb/libmariadb/secure/ma_schannel.h4
-rw-r--r--libmariadb/libmariadb/secure/openssl.c104
-rw-r--r--libmariadb/libmariadb/secure/openssl_crypt.c2
-rw-r--r--libmariadb/libmariadb/secure/schannel.c94
-rw-r--r--libmariadb/plugins/auth/CMakeLists.txt5
-rw-r--r--libmariadb/plugins/auth/auth_gssapi_client.c3
-rw-r--r--libmariadb/plugins/auth/caching_sha2_pw.c3
-rw-r--r--libmariadb/plugins/auth/dialog.c3
-rw-r--r--libmariadb/plugins/auth/ed25519.c35
-rw-r--r--libmariadb/plugins/auth/mariadb_cleartext.c3
-rw-r--r--libmariadb/plugins/auth/my_auth.c124
-rw-r--r--libmariadb/plugins/auth/old_password.c3
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_sign.h2
-rw-r--r--libmariadb/plugins/auth/ref10/sign.c3
-rw-r--r--libmariadb/plugins/auth/sha256_pw.c3
-rwxr-xr-xlibmariadb/travis.sh6
-rw-r--r--libmariadb/unittest/libmariadb/CMakeLists.txt4
-rw-r--r--libmariadb/unittest/libmariadb/bulk1.c350
-rw-r--r--libmariadb/unittest/libmariadb/charset.c9
-rw-r--r--libmariadb/unittest/libmariadb/connection.c47
-rw-r--r--libmariadb/unittest/libmariadb/misc.c30
-rw-r--r--libmariadb/unittest/libmariadb/my_test.h24
-rw-r--r--libmariadb/unittest/libmariadb/ps_bugs.c70
-rw-r--r--libmariadb/unittest/libmariadb/rpl_api.c80
49 files changed, 1367 insertions, 195 deletions
diff --git a/libmariadb/.travis.yml b/libmariadb/.travis.yml
index aab4dfec..02d0d29c 100644
--- a/libmariadb/.travis.yml
+++ b/libmariadb/.travis.yml
@@ -24,5 +24,7 @@ jobs:
name: "CS 10.11 Server unit testing"
- env: server_branch=11.3 TEST_OPTION=--ps-protocol
name: "11.3 Server unit testing with ps-protocol"
+ - env: server_branch=11.4
+ name: "11.4 Server unit testing"
script: ./travis.sh
diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt
index b987bc7f..ed9572cb 100644
--- a/libmariadb/CMakeLists.txt
+++ b/libmariadb/CMakeLists.txt
@@ -25,7 +25,8 @@ get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
SET_PROPERTY(DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
FOREACH(V WITH_MYSQLCOMPAT WITH_MSI WITH_SIGNCODE WITH_RTC WITH_UNIT_TESTS
WITH_DYNCOL WITH_EXTERNAL_ZLIB WITH_CURL WITH_SQLITE WITH_SSL WITH_ICONV
- DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG)
+ DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG
+ DEFAULT_SSL_VERIFY_SERVER_CERT)
SET(${V} ${${OPT}${V}})
ENDFOREACH()
@@ -35,8 +36,8 @@ SET(CC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(CPACK_PACKAGE_VERSION_MAJOR 3)
-SET(CPACK_PACKAGE_VERSION_MINOR 3)
-SET(CPACK_PACKAGE_VERSION_PATCH 10)
+SET(CPACK_PACKAGE_VERSION_MINOR 4)
+SET(CPACK_PACKAGE_VERSION_PATCH 0)
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 +
@@ -65,6 +66,7 @@ ADD_OPTION(WITH_DYNCOL "Enables support of dynamic columns" ON)
ADD_OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF)
ADD_OPTION(WITH_CURL "Enables use of curl" ON)
ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON)
+ADD_OPTION(DEFAULT_SSL_VERIFY_SERVER_CERT "Default value for MYSQL_OPT_SSL_VERIFY_SERVER_CERT" ON)
###############
INCLUDE(${CC_SOURCE_DIR}/cmake/misc.cmake)
@@ -305,7 +307,8 @@ IF(NOT WITH_SSL STREQUAL "OFF")
ENDIF()
IF(OPENSSL_FOUND)
ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_TLS)
- SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c")
+ SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c"
+ "${CC_SOURCE_DIR}/libmariadb/secure/openssl_crypt.c")
SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
IF(WIN32)
CHECK_INCLUDE_FILES (${OPENSSL_INCLUDE_DIR}/openssl/applink.c HAVE_OPENSSL_APPLINK_C)
@@ -332,7 +335,8 @@ IF(NOT WITH_SSL STREQUAL "OFF")
FIND_PACKAGE(GnuTLS "3.3.24" REQUIRED)
IF(GNUTLS_FOUND)
ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_TLS)
- SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c")
+ SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c"
+ "${CC_SOURCE_DIR}/libmariadb/secure/gnutls_crypt.c")
SET(SSL_LIBRARIES ${GNUTLS_LIBRARY})
SET(TLS_LIBRARY_VERSION "GnuTLS ${GNUTLS_VERSION_STRING}")
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR})
@@ -342,12 +346,13 @@ IF(NOT WITH_SSL STREQUAL "OFF")
ENDIF()
IF(WIN32)
IF(WITH_SSL STREQUAL "SCHANNEL")
- ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_TLS)
+ ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_TLS -DHAVE_WINCRYPT)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/schannel.c"
+ "${CC_SOURCE_DIR}/libmariadb/secure/win_crypt.c"
"${CC_SOURCE_DIR}/libmariadb/secure/ma_schannel.c"
"${CC_SOURCE_DIR}/libmariadb/secure/schannel_certs.c")
INCLUDE_DIRECTORIES("${CC_SOURCE_DIR}/plugins/pvio/")
- SET(SSL_LIBRARIES secur32)
+ SET(SSL_LIBRARIES secur32 crypt32 bcrypt)
SET(TLS_LIBRARY_VERSION "Schannel ${CMAKE_SYSTEM_VERSION}")
ENDIF()
ENDIF()
@@ -382,7 +387,7 @@ CONFIGURE_FILE(${CC_SOURCE_DIR}/include/mariadb_version.h.in
INCLUDE_DIRECTORIES(${CC_BINARY_DIR}/include)
IF(WIN32)
- SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 ${LIBZ})
+ SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 bcrypt ${LIBZ})
ELSE()
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBPTHREAD} ${CMAKE_DL_LIBS} ${LIBM})
IF(ICONV_EXTERNAL)
@@ -542,6 +547,7 @@ ENDIF()
MESSAGE1(STATUS "MariaDB Connector/c configuration:
-- Static PLUGINS ${PLUGINS_STATIC}
-- Dynamic PLUGINS ${PLUGINS_DYNAMIC}
+-- Disabled PLUGINS ${PLUGINS_DISABLED}
-- CPack generation: ${CPACK_GENERATOR}
-- SSL support: ${WITH_SSL} Libs: ${SSL_LIBRARIES}
-- Zlib support: ${zlib_status}
diff --git a/libmariadb/cmake/plugins.cmake b/libmariadb/cmake/plugins.cmake
index 1f321b14..de5c12c1 100644
--- a/libmariadb/cmake/plugins.cmake
+++ b/libmariadb/cmake/plugins.cmake
@@ -12,7 +12,7 @@ include(${CC_SOURCE_DIR}/cmake/sign.cmake)
FUNCTION(REGISTER_PLUGIN)
- SET(one_value_keywords TARGET DEFAULT TYPE)
+ SET(one_value_keywords TARGET DISABLED TYPE DEFAULT)
SET(multi_value_keywords CONFIGURATIONS SOURCES LIBRARIES INCLUDES COMPILE_OPTIONS)
cmake_parse_arguments(CC_PLUGIN
@@ -43,12 +43,19 @@ FUNCTION(REGISTER_PLUGIN)
message(FATAL_ERROR "Invalid plugin type ${CC_PLUGIN_DEFAULT}. Allowed plugin types are ${CC_PLUGIN_CONFIGURATIONS}")
endif()
+# check if plugin is disabled
+ string(TOUPPER "${CC_PLUGIN_DISABLED}" CC_PLUGIN_DISABLED)
+ if("${CC_PLUGIN_DISABLED}" STREQUAL "YES")
+ set(PLUGINS_DISABLED ${PLUGINS_DISABLED} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
+ endif()
+
if(NOT ${CC_PLUGIN_DEFAULT} STREQUAL "OFF")
set(PLUGIN_${CC_PLUGIN_TARGET}_TYPE ${CC_PLUGIN_TYPE})
- if(${CC_PLUGIN_DEFAULT} STREQUAL "DYNAMIC")
+ if(${CC_PLUGIN_DEFAULT} MATCHES "DYNAMIC")
set(PLUGINS_DYNAMIC ${PLUGINS_DYNAMIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
+ add_library(${CC_PLUGIN_TARGET} MODULE ${CC_PLUGIN_SOURCES})
if(WIN32)
set(target ${CC_PLUGIN_TARGET})
set(FILE_TYPE "VFT_DLL")
@@ -58,9 +65,9 @@ FUNCTION(REGISTER_PLUGIN)
configure_file(${CC_SOURCE_DIR}/win/resource.rc.in
${CC_BINARY_DIR}/win/${target}.rc
@ONLY)
- set(CC_PLUGIN_SOURCES ${CC_PLUGIN_SOURCES} ${CC_BINARY_DIR}/win/${target}.rc ${CC_SOURCE_DIR}/plugins/plugin.def)
+ target_sources(${CC_PLUGIN_TARGET} PRIVATE
+ ${CC_BINARY_DIR}/win/${target}.rc ${CC_SOURCE_DIR}/plugins/plugin.def)
endif()
- add_library(${CC_PLUGIN_TARGET} MODULE ${CC_PLUGIN_SOURCES})
target_link_libraries(${CC_PLUGIN_TARGET} ${CC_PLUGIN_LIBRARIES})
set_target_properties(${CC_PLUGIN_TARGET} PROPERTIES PREFIX "")
set_target_properties(${CC_PLUGIN_TARGET}
@@ -81,7 +88,8 @@ FUNCTION(REGISTER_PLUGIN)
SIGN_TARGET(${target})
endif()
INSTALL_PLUGIN(${CC_PLUGIN_TARGET} ${CMAKE_CURRENT_BINARY_DIR})
- elseif(${CC_PLUGIN_DEFAULT} STREQUAL "STATIC")
+ endif()
+ if(${CC_PLUGIN_DEFAULT} MATCHES "STATIC")
set(PLUGINS_STATIC ${PLUGINS_STATIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_CFLAGS ${LIBMARIADB_PLUGIN_CFLAGS} ${CC_PLUGIN_COMPILE_OPTIONS} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_INCLUDES ${LIBMARIADB_PLUGIN_INCLUDES} ${CC_PLUGIN_INCLUDES} PARENT_SCOPE)
diff --git a/libmariadb/include/errmsg.h b/libmariadb/include/errmsg.h
index f22db164..0e6d24e0 100644
--- a/libmariadb/include/errmsg.h
+++ b/libmariadb/include/errmsg.h
@@ -115,10 +115,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */
#define CR_BINLOG_INVALID_FILE 5022
#define CR_BINLOG_SEMI_SYNC_ERROR 5023
#define CR_INVALID_CLIENT_FLAG 5024
+#define CR_STMT_NO_RESULT 5025
/* Always last, if you add new error codes please update the
value for CR_MARIADB_LAST_ERROR */
-#define CR_MARIADB_LAST_ERROR CR_INVALID_CLIENT_FLAG
+#define CR_MARIADB_LAST_ERROR CR_STMT_NO_RESULT
#endif
diff --git a/libmariadb/include/ma_common.h b/libmariadb/include/ma_common.h
index 1ac0cb68..dfa96621 100644
--- a/libmariadb/include/ma_common.h
+++ b/libmariadb/include/ma_common.h
@@ -73,6 +73,7 @@ struct st_mysql_options_extension {
unsigned int tls_cipher_strength;
char *tls_version;
my_bool read_only;
+ my_bool bulk_unit_results;
char *connection_handler;
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
MA_HASHTBL userdata;
@@ -86,7 +87,7 @@ struct st_mysql_options_extension {
unsigned short rpl_port;
void (*status_callback)(void *ptr, enum enum_mariadb_status_info type, ...);
void *status_data;
- my_bool tls_verify_server_cert;
+ my_bool tls_allow_invalid_server_cert;
};
typedef struct st_connection_handler
@@ -129,3 +130,16 @@ 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) \
+ 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; \
+ } while(0)
+#endif
diff --git a/libmariadb/include/ma_config.h.in b/libmariadb/include/ma_config.h.in
index c5c758dc..4cabfef3 100644
--- a/libmariadb/include/ma_config.h.in
+++ b/libmariadb/include/ma_config.h.in
@@ -148,3 +148,4 @@
#define MARIADB_DEFAULT_CHARSET "@DEFAULT_CHARSET@"
+#cmakedefine DEFAULT_SSL_VERIFY_SERVER_CERT 1
diff --git a/libmariadb/include/ma_crypt.h b/libmariadb/include/ma_crypt.h
index 367488fa..b4d2a09f 100644
--- a/libmariadb/include/ma_crypt.h
+++ b/libmariadb/include/ma_crypt.h
@@ -17,34 +17,20 @@
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*/
-#ifndef _ma_hash_h_
-#define _ma_hash_h_
+#ifndef _ma_crypt_h_
+#define _ma_crypt_h_
+#include <ma_hash.h>
#include <stddef.h>
#include <stdarg.h>
/*! Hash algorithms */
-#define MA_HASH_MD5 1
-#define MA_HASH_SHA1 2
-#define MA_HASH_SHA224 3
-#define MA_HASH_SHA256 4
-#define MA_HASH_SHA384 5
-#define MA_HASH_SHA512 6
#define MA_HASH_RIPEMD160 7
#define MA_HASH_MAX 8
/*! Hash digest sizes */
-#define MA_MD5_HASH_SIZE 16
-#define MA_SHA1_HASH_SIZE 20
-#define MA_SHA224_HASH_SIZE 28
-#define MA_SHA256_HASH_SIZE 32
-#define MA_SHA384_HASH_SIZE 48
-#define MA_SHA512_HASH_SIZE 64
#define MA_RIPEMD160_HASH_SIZE 20
-#define MA_MAX_HASH_SIZE 64
-/** \typedef MRL hash context */
-
#if defined(HAVE_WINCRYPT)
typedef void MA_HASH_CTX;
#elif defined(HAVE_OPENSSL)
@@ -123,8 +109,6 @@ static inline size_t ma_hash_digest_size(unsigned int hash_alg)
return MA_SHA384_HASH_SIZE;
case MA_HASH_SHA512:
return MA_SHA512_HASH_SIZE;
- case MA_HASH_RIPEMD160:
- return MA_RIPEMD160_HASH_SIZE;
default:
return 0;
}
@@ -152,4 +136,4 @@ static inline void ma_hash(unsigned int algorithm,
ma_hash_free(ctx);
}
-#endif /* _ma_hash_h_ */
+#endif /* _ma_crypt_h_ */
diff --git a/libmariadb/include/ma_tls.h b/libmariadb/include/ma_tls.h
index ec8bc239..6601f896 100644
--- a/libmariadb/include/ma_tls.h
+++ b/libmariadb/include/ma_tls.h
@@ -1,6 +1,8 @@
#ifndef _ma_tls_h_
#define _ma_tls_h_
+#include <ma_hash.h>
+
enum enum_pvio_tls_type {
SSL_TYPE_DEFAULT=0,
#ifdef _WIN32
@@ -25,6 +27,7 @@ typedef struct st_ma_pvio_tls {
void *data;
MARIADB_PVIO *pvio;
void *ssl;
+ MARIADB_X509_INFO cert_info;
} MARIADB_TLS;
/* Function prototypes */
@@ -128,12 +131,14 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ssl);
returns SHA1 finger print of server certificate
Parameter:
MARIADB_TLS MariaDB SSL container
+ hash_type hash_type as defined in ma_hash.h
fp buffer for fingerprint
fp_len buffer length
+
Returns:
actual size of finger print
*/
-unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int fp_len);
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int fp_len);
/* ma_tls_get_protocol_version
returns protocol version number in use
diff --git a/libmariadb/include/mariadb_com.h b/libmariadb/include/mariadb_com.h
index 01a13dab..6e7164a3 100644
--- a/libmariadb/include/mariadb_com.h
+++ b/libmariadb/include/mariadb_com.h
@@ -177,6 +177,8 @@ enum enum_server_command
#define MARIADB_CLIENT_EXTENDED_METADATA (1ULL << 35)
/* Do not resend metadata for prepared statements, since 10.6*/
#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
+/* permit sending unit result-set for BULK commands */
+#define MARIADB_CLIENT_BULK_UNIT_RESULTS (1ULL << 37)
#define IS_MARIADB_EXTENDED_SERVER(mysql)\
(!(mysql->server_capabilities & CLIENT_MYSQL))
@@ -184,7 +186,8 @@ enum enum_server_command
#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\
MARIADB_CLIENT_STMT_BULK_OPERATIONS|\
MARIADB_CLIENT_EXTENDED_METADATA|\
- MARIADB_CLIENT_CACHE_METADATA)
+ MARIADB_CLIENT_CACHE_METADATA|\
+ MARIADB_CLIENT_BULK_UNIT_RESULTS)
#define CLIENT_SUPPORTED_FLAGS (CLIENT_MYSQL |\
CLIENT_FOUND_ROWS |\
@@ -231,6 +234,9 @@ enum enum_server_command
#define CLIENT_DEFAULT_FLAGS ((CLIENT_SUPPORTED_FLAGS & ~CLIENT_COMPRESS)\
& ~CLIENT_SSL)
+#define CLIENT_DEFAULT_EXTENDED_FLAGS (MARIADB_CLIENT_SUPPORTED_FLAGS &\
+ ~MARIADB_CLIENT_BULK_UNIT_RESULTS)
+
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_MORE_RESULTS_EXIST 8
@@ -294,7 +300,7 @@ typedef struct st_net {
my_bool unused_2;
my_bool compress;
my_bool unused_3;
- void *unused_4;
+ const char *tls_self_signed_error;
unsigned int last_errno;
unsigned char error;
my_bool unused_5;
diff --git a/libmariadb/include/mariadb_rpl.h b/libmariadb/include/mariadb_rpl.h
index ea0ca4db..f12fdfa1 100644
--- a/libmariadb/include/mariadb_rpl.h
+++ b/libmariadb/include/mariadb_rpl.h
@@ -501,10 +501,7 @@ struct st_mariadb_rpl_rows_event {
};
struct st_mariadb_rpl_heartbeat_event {
- uint32_t timestamp;
- uint32_t next_position;
- uint8_t type;
- uint16_t flags;
+ MARIADB_STRING filename;
};
struct st_mariadb_rpl_xa_prepare_log_event {
diff --git a/libmariadb/include/mariadb_stmt.h b/libmariadb/include/mariadb_stmt.h
index 531c2181..87ad4fa5 100644
--- a/libmariadb/include/mariadb_stmt.h
+++ b/libmariadb/include/mariadb_stmt.h
@@ -34,6 +34,12 @@
((stmt)->mysql->extension->mariadb_server_capabilities & \
(MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32))))
+#define MARIADB_STMT_BULK_UNIT_RESULTS_SUPPORTED(stmt)\
+ ((stmt)->mysql && \
+ (!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\
+ ((stmt)->mysql->extension->mariadb_client_flag & \
+ (MARIADB_CLIENT_BULK_UNIT_RESULTS >> 32))))
+
#define CLEAR_CLIENT_STMT_ERROR(a) \
do { \
(a)->last_errno= 0;\
@@ -88,7 +94,7 @@ enum enum_indicator_type
bulk PS flags
*/
#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128
-#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64
+#define STMT_BULK_FLAG_SEND_UNIT_RESULTS 64
typedef enum mysql_stmt_state
{
diff --git a/libmariadb/include/mysql.h b/libmariadb/include/mysql.h
index 76b16830..1d30486a 100644
--- a/libmariadb/include/mysql.h
+++ b/libmariadb/include/mysql.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
#include <stdarg.h>
+#include <time.h>
#if !defined (_global_h) && !defined (MY_GLOBAL_INCLUDED) /* If not standard header */
#include <sys/types.h>
@@ -257,7 +258,8 @@ extern const char *SQLSTATE_UNKNOWN;
MARIADB_OPT_RESTRICTED_AUTH,
MARIADB_OPT_RPL_REGISTER_REPLICA,
MARIADB_OPT_STATUS_CALLBACK,
- MARIADB_OPT_SERVER_PLUGINS
+ MARIADB_OPT_SERVER_PLUGINS,
+ MARIADB_OPT_BULK_UNIT_RESULTS
};
enum mariadb_value {
@@ -296,7 +298,8 @@ extern const char *SQLSTATE_UNKNOWN;
MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES,
MARIADB_CONNECTION_CLIENT_CAPABILITIES,
MARIADB_CONNECTION_BYTES_READ,
- MARIADB_CONNECTION_BYTES_SENT
+ MARIADB_CONNECTION_BYTES_SENT,
+ MARIADB_TLS_PEER_CERT_INFO,
};
enum mysql_status { MYSQL_STATUS_READY,
@@ -336,7 +339,7 @@ struct st_mysql_options {
enum mysql_option methods_to_use;
char *bind_address;
my_bool secure_auth;
- my_bool report_data_truncation;
+ my_bool report_data_truncation;
/* function pointers for local infile support */
int (*local_infile_init)(void **, const char *, void *);
int (*local_infile_read)(void *, char *, unsigned int);
@@ -480,6 +483,27 @@ struct st_mysql_client_plugin
MYSQL_CLIENT_PLUGIN_HEADER
};
+enum mariadb_tls_verification {
+ MARIADB_VERIFY_NONE = 0,
+ MARIADB_VERIFY_PIPE,
+ MARIADB_VERIFY_UNIXSOCKET,
+ MARIADB_VERIFY_LOCALHOST,
+ MARIADB_VERIFY_FINGERPRINT,
+ MARIADB_VERIFY_PEER_CERT
+};
+
+typedef struct
+{
+ int version;
+ char *issuer;
+ char *subject;
+ char fingerprint[65];
+ struct tm not_before;
+ struct tm not_after;
+ enum mariadb_tls_verification verify_mode;
+} MARIADB_X509_INFO;
+
+
struct st_mysql_client_plugin *
mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
int argc, ...);
diff --git a/libmariadb/include/mysql/client_plugin.h b/libmariadb/include/mysql/client_plugin.h
index 667074ce..aa7e5363 100644
--- a/libmariadb/include/mysql/client_plugin.h
+++ b/libmariadb/include/mysql/client_plugin.h
@@ -43,7 +43,7 @@
#define MYSQL_CLIENT_PLUGIN_RESERVED2 1
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 /* authentication */
-#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0101
#define MYSQL_CLIENT_MAX_PLUGINS 3
/* Connector/C specific plugin types */
@@ -128,6 +128,7 @@ struct st_mysql_client_plugin_AUTHENTICATION
{
MYSQL_CLIENT_PLUGIN_HEADER
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+ int (*hash_password_bin)(struct st_mysql *mysql, unsigned char *hash, size_t *hash_length);
};
/******** trace plugin *******/
diff --git a/libmariadb/libmariadb/CMakeLists.txt b/libmariadb/libmariadb/CMakeLists.txt
index 43ed67b4..852be8dc 100644
--- a/libmariadb/libmariadb/CMakeLists.txt
+++ b/libmariadb/libmariadb/CMakeLists.txt
@@ -344,6 +344,10 @@ IF(WIN32)
${CC_SOURCE_DIR}/win-iconv/win_iconv.c
win32_errmsg.c
win32_errmsg.h)
+ IF(WITH_SSL STREQUAL "SCHANNEL")
+ SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}
+ secure/win_crypt.c)
+ ENDIF()
ELSE()
IF(ICONV_INCLUDE_DIR)
INCLUDE_DIRECTORIES(BEFORE ${ICONV_INCLUDE_DIR})
diff --git a/libmariadb/libmariadb/ma_charset.c b/libmariadb/libmariadb/ma_charset.c
index f6ed6f80..10c191cd 100644
--- a/libmariadb/libmariadb/ma_charset.c
+++ b/libmariadb/libmariadb/ma_charset.c
@@ -830,9 +830,11 @@ const MARIADB_CHARSET_INFO mariadb_compiled_charsets[] =
{ 576, 1, UTF8_MB3, UTF8_MB3"_croatian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
{ 577, 1, UTF8_MB3, UTF8_MB3"_myanmar_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
{ 578, 1, UTF8_MB3, UTF8_MB3"_thai_520_w2", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+ { 579, 1, UTF8_MB3, UTF8_MB3"_general1400_as_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
{ 608, 1, UTF8_MB4, UTF8_MB4"_croatian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
{ 609, 1, UTF8_MB4, UTF8_MB4"_myanmar_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
{ 610, 1, UTF8_MB4, UTF8_MB4"_thai_520_w2", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 611, 1, UTF8_MB4, UTF8_MB4"_general1400_as_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8, check_mb_utf8_valid},
{ 640, 1, "ucs2", "ucs2_croatian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
{ 641, 1, "ucs2", "ucs2_myanmar_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
{ 642, 1, "ucs2", "ucs2_thai_520_w2", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
diff --git a/libmariadb/libmariadb/ma_client_plugin.c.in b/libmariadb/libmariadb/ma_client_plugin.c.in
index 6e0433b3..a402d082 100644
--- a/libmariadb/libmariadb/ma_client_plugin.c.in
+++ b/libmariadb/libmariadb/ma_client_plugin.c.in
@@ -46,6 +46,8 @@
#include <dlfcn.h>
#endif
+const char *disabled_plugins= "@PLUGINS_DISABLED@";
+
struct st_client_plugin_int {
struct st_client_plugin_int *next;
void *dlhandle;
@@ -111,8 +113,7 @@ static int get_plugin_nr(uint type)
static const char *check_plugin_version(struct st_mysql_client_plugin *plugin, unsigned int version)
{
- if (plugin->interface_version < version ||
- (plugin->interface_version >> 8) > (version >> 8))
+ if (plugin->interface_version >> 8 != version >> 8)
return "Incompatible client plugin interface";
return 0;
}
diff --git a/libmariadb/libmariadb/ma_errmsg.c b/libmariadb/libmariadb/ma_errmsg.c
index 90218573..53890f87 100644
--- a/libmariadb/libmariadb/ma_errmsg.c
+++ b/libmariadb/libmariadb/ma_errmsg.c
@@ -119,6 +119,7 @@ const char *mariadb_client_errors[] =
/* 5022 */ "File '%s' is not a binary log file",
/* 5023 */ "Semi sync request error: %s",
/* 5024 */ "Invalid client flags (%lu) specified. Supported flags: %lu",
+ /* 5025 */ "Statement has no result set",
""
};
diff --git a/libmariadb/libmariadb/ma_pvio.c b/libmariadb/libmariadb/ma_pvio.c
index a8a653b6..e18af51e 100644
--- a/libmariadb/libmariadb/ma_pvio.c
+++ b/libmariadb/libmariadb/ma_pvio.c
@@ -522,6 +522,55 @@ 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)
+ {
+ pvio->ctls->cert_info.verify_mode=
+#ifdef WIN32
+ MARIADB_VERIFY_PIPE;
+#else
+ MARIADB_VERIFY_UNIXSOCKET;
+#endif
+ return TRUE;
+ }
+ if (!hostname)
+ return FALSE;
+ for (i= 0; local_host_names[i]; i++)
+ {
+ if (strcmp(hostname, local_host_names[i]) == 0)
+ {
+ pvio->ctls->cert_info.verify_mode= MARIADB_VERIFY_LOCALHOST;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* {{{ my_bool ma_pvio_start_ssl */
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
{
@@ -544,20 +593,28 @@ 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.extension->tls_verify_server_cert &&
+ 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;
+ else
+ pvio->ctls->cert_info.verify_mode= MARIADB_VERIFY_PEER_CERT;
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))
+ pvio->mysql->options.extension->tls_fp,
+ pvio->mysql->options.extension->tls_fp_list))
return 1;
+ pvio->ctls->cert_info.verify_mode= MARIADB_VERIFY_FINGERPRINT;
+ reset_tls_self_signed_error(pvio->mysql); // validated
}
+ if (pvio->mysql->net.tls_self_signed_error && ignore_self_signed_cert_error(pvio))
+ reset_tls_self_signed_error(pvio->mysql);
+
return 0;
}
/* }}} */
diff --git a/libmariadb/libmariadb/ma_tls.c b/libmariadb/libmariadb/ma_tls.c
index 3f48ad8b..432a0f4a 100644
--- a/libmariadb/libmariadb/ma_tls.c
+++ b/libmariadb/libmariadb/ma_tls.c
@@ -41,12 +41,15 @@
#include <ma_tls.h>
#include <mysql/client_plugin.h>
#include <mariadb/ma_io.h>
+#include <ma_hash.h>
#ifdef HAVE_NONBLOCK
#include <mariadb_async.h>
#include <ma_context.h>
#endif
+#define MAX_FINGERPRINT_LEN 128;
+
/* Errors should be handled via pvio callback function */
my_bool ma_tls_initialized= FALSE;
unsigned int mariadb_deinitialize_ssl= 1;
@@ -141,62 +144,96 @@ static signed char ma_hex2int(char c)
return -1;
}
-static my_bool ma_pvio_tls_compare_fp(const char *cert_fp,
- unsigned int cert_fp_len,
- const char *fp, unsigned int fp_len)
+#ifndef EVP_MAX_MD_SIZE
+#define EVP_MAX_MD_SIZE 64
+#endif
+
+static my_bool ma_pvio_tls_compare_fp(MARIADB_TLS *ctls,
+ const char *cert_fp,
+ unsigned int cert_fp_len
+)
{
- char *p= (char *)fp,
- *c;
+ const char fp[EVP_MAX_MD_SIZE];
+ unsigned int fp_len= EVP_MAX_MD_SIZE;
+ unsigned int hash_type;
+
+ char *p, *c;
+ uint hash_len;
+
+ /* check length without colons */
+ if (strchr(cert_fp, ':'))
+ hash_len= (uint)((strlen(cert_fp) + 1) / 3) * 2;
+ else
+ hash_len= (uint)strlen(cert_fp);
+
+ /* check hash size */
+ switch (hash_len) {
+#ifndef DISABLE_WEAK_HASH
+ case MA_SHA1_HASH_SIZE * 2:
+ hash_type = MA_HASH_SHA1;
+ break;
+#endif
+ case MA_SHA224_HASH_SIZE * 2:
+ hash_type = MA_HASH_SHA224;
+ break;
+ case MA_SHA256_HASH_SIZE * 2:
+ hash_type = MA_HASH_SHA256;
+ break;
+ case MA_SHA384_HASH_SIZE * 2:
+ hash_type = MA_HASH_SHA384;
+ break;
+ case MA_SHA512_HASH_SIZE * 2:
+ hash_type = MA_HASH_SHA512;
+ break;
+ default:
+ {
+ MYSQL* mysql = ctls->pvio->mysql;
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Unknown or invalid fingerprint hash size detected");
+ return 1;
+ }
+ }
- /* check length */
- if (cert_fp_len != 20)
+ if (!ma_tls_get_finger_print(ctls, hash_type, (char *)fp, fp_len))
return 1;
- /* We support two formats:
- 2 digits hex numbers, separated by colons (length=59)
- 20 * 2 digits hex numbers without separators (length = 40)
- */
- if (fp_len != (strchr(fp, ':') ? 59 : 40))
- return 1;
+ p= (char *)cert_fp;
+ c = (char *)fp;
- for(c= (char *)cert_fp; c < cert_fp + cert_fp_len; c++)
+ for (p = (char*)cert_fp; p < cert_fp + cert_fp_len; c++, p += 2)
{
signed char d1, d2;
if (*p == ':')
p++;
- if (p - fp > (int)fp_len -1)
+ 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)
+ if ((d1 = ma_hex2int(*p)) == -1 ||
+ (d2 = ma_hex2int(*(p + 1))) == -1 ||
+ (char)(d1 * 16 + d2) != *c)
return 1;
- p+= 2;
}
return 0;
}
my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list)
{
- unsigned int cert_fp_len= 64;
- char *cert_fp= NULL;
my_bool rc=1;
MYSQL *mysql= ctls->pvio->mysql;
- cert_fp= (char *)malloc(cert_fp_len);
-
- if ((cert_fp_len= ma_tls_get_finger_print(ctls, cert_fp, cert_fp_len)) < 1)
- goto end;
if (fp)
- rc= ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, fp, (unsigned int)strlen(fp));
+ {
+ rc = ma_pvio_tls_compare_fp(ctls, fp, (uint)strlen(fp));
+ }
else if (fp_list)
{
- MA_FILE *fp;
+ MA_FILE *f;
char buff[255];
- if (!(fp = ma_open(fp_list, "r", mysql)))
+ if (!(f = ma_open(fp_list, "r", mysql)))
goto end;
- while (ma_gets(buff, sizeof(buff)-1, fp))
+ while (ma_gets(buff, sizeof(buff)-1, f))
{
/* remove trailing new line character */
char *pos= strchr(buff, '\r');
@@ -205,22 +242,20 @@ my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_l
if (pos)
*pos= '\0';
- if (!ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, buff, (unsigned int)strlen(buff)))
+ if (!ma_pvio_tls_compare_fp(ctls, buff, (uint)strlen(buff)))
{
/* finger print is valid: close file and exit */
- ma_close(fp);
+ ma_close(f);
rc= 0;
goto end;
}
}
/* No finger print matched - close file and return error */
- ma_close(fp);
+ ma_close(f);
}
end:
- if (cert_fp)
- free(cert_fp);
if (rc)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
diff --git a/libmariadb/libmariadb/mariadb_lib.c b/libmariadb/libmariadb/mariadb_lib.c
index c48ccdad..b4a36585 100644
--- a/libmariadb/libmariadb/mariadb_lib.c
+++ b/libmariadb/libmariadb/mariadb_lib.c
@@ -693,6 +693,7 @@ struct st_default_options mariadb_defaults[] =
{{MYSQL_OPT_SSL_ENFORCE}, MARIADB_OPTION_BOOL, "ssl-enforce"},
{{MARIADB_OPT_RESTRICTED_AUTH}, MARIADB_OPTION_STR, "restricted-auth"},
{{.option_func=parse_connection_string}, MARIADB_OPTION_FUNC, "connection"},
+ {{MARIADB_OPT_BULK_UNIT_RESULTS}, MARIADB_OPTION_BOOL, "bulk-unit-results"},
/* Aliases */
{{MARIADB_OPT_SCHEMA}, MARIADB_OPTION_STR, "db"},
{{MARIADB_OPT_UNIXSOCKET}, MARIADB_OPTION_STR, "unix_socket"},
@@ -714,10 +715,19 @@ struct st_default_options mariadb_defaults[] =
{{0}, 0, NULL}
};
+#ifdef DEFAULT_SSL_VERIFY_SERVER_CERT
+#define FIX_SSL_VERIFY_SERVER_CERT(OPTS)
+#else
+#define FIX_SSL_VERIFY_SERVER_CERT(OPTS) (OPTS)->extension->tls_allow_invalid_server_cert=1
+#endif
+
#define CHECK_OPT_EXTENSION_SET(OPTS)\
if (!(OPTS)->extension) \
+ { \
(OPTS)->extension= (struct st_mysql_options_extension *) \
- calloc(1, sizeof(struct st_mysql_options_extension));
+ calloc(1, sizeof(struct st_mysql_options_extension)); \
+ FIX_SSL_VERIFY_SERVER_CERT(OPTS); \
+ }
#define OPT_SET_EXTENDED_VALUE_BIN(OPTS, KEY, KEY_LEN, VAL, LEN)\
CHECK_OPT_EXTENSION_SET(OPTS) \
@@ -1449,6 +1459,8 @@ 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);
+
/* if host contains a semicolon, we need to parse connection string */
if (host && strchr(host, ';'))
{
@@ -2453,6 +2465,7 @@ mysql_close(MYSQL *mysql)
mysql_close_memory(mysql);
mysql_close_options(mysql);
ma_clear_session_state(mysql);
+ reset_tls_self_signed_error(mysql);
if (mysql->net.extension)
{
@@ -3300,10 +3313,17 @@ mysql_refresh(MYSQL *mysql,uint options)
int STDCALL
mysql_kill(MYSQL *mysql,ulong pid)
{
- char buff[12];
- int4store(buff,pid);
- /* if we kill our own thread, reading the response packet will fail */
- return(ma_simple_command(mysql, COM_PROCESS_KILL,buff,4,0,0));
+ char buff[16];
+
+ /* process id can't be larger than 4-bytes */
+ if (pid & (~0xFFFFFFFFUL))
+ {
+ my_set_error(mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
+ snprintf(buff, sizeof buff, "KILL %lu", pid);
+ return mysql_real_query(mysql, (char *)buff, (ulong)strlen(buff));
}
@@ -3528,6 +3548,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
goto end;
}
if (!mysql->options.extension)
+ {
if(!(mysql->options.extension= (struct st_mysql_options_extension *)
calloc(1, sizeof(struct st_mysql_options_extension))))
{
@@ -3535,6 +3556,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto end;
}
+ FIX_SSL_VERIFY_SERVER_CERT(&mysql->options);
+ }
mysql->options.extension->async_context= ctxt;
break;
case MYSQL_OPT_MAX_ALLOWED_PACKET:
@@ -3556,7 +3579,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.use_ssl= (*(my_bool *)arg1);
break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
- OPT_SET_EXTENDED_VALUE(&mysql->options, tls_verify_server_cert, *(my_bool *)arg1);
+ OPT_SET_EXTENDED_VALUE(&mysql->options, tls_allow_invalid_server_cert, !*(my_bool *)arg1);
break;
case MYSQL_OPT_SSL_KEY:
OPT_SET_VALUE_STR(&mysql->options, ssl_key, (char *)arg1);
@@ -3824,6 +3847,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
}
}
break;
+ case MARIADB_OPT_BULK_UNIT_RESULTS:
+ OPT_SET_EXTENDED_VALUE_INT(&mysql->options, bulk_unit_results, *(my_bool *)arg1);
+ break;
default:
va_end(ap);
SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
@@ -3922,7 +3948,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
*((my_bool *)arg)= mysql->options.use_ssl;
break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
- *((my_bool*)arg) = mysql->options.extension ? mysql->options.extension->tls_verify_server_cert : 0;
+ *((my_bool*)arg) = mysql->options.extension ? !mysql->options.extension->tls_allow_invalid_server_cert: 1;
break;
case MYSQL_OPT_SSL_KEY:
*((char **)arg)= mysql->options.ssl_key;
@@ -4046,6 +4072,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
case MARIADB_OPT_SKIP_READ_RESPONSE:
*((my_bool*)arg)= mysql->options.extension ? mysql->options.extension->skip_read_response : 0;
break;
+ case MARIADB_OPT_BULK_UNIT_RESULTS:
+ *((my_bool *)arg)= mysql->options.extension ? mysql->options.extension->bulk_unit_results : 0;
+ break;
default:
va_end(ap);
SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
@@ -4506,6 +4535,11 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...
va_start(ap, arg);
switch(value) {
+#ifdef HAVE_TLS
+ case MARIADB_TLS_PEER_CERT_INFO:
+ *((MARIADB_X509_INFO **)arg)= mysql->net.pvio->ctls ? (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info : NULL;
+ break;
+#endif
case MARIADB_MAX_ALLOWED_PACKET:
*((size_t *)arg)= (size_t)max_allowed_packet;
break;
diff --git a/libmariadb/libmariadb/mariadb_rpl.c b/libmariadb/libmariadb/mariadb_rpl.c
index 0019f246..cfaf228d 100644
--- a/libmariadb/libmariadb/mariadb_rpl.c
+++ b/libmariadb/libmariadb/mariadb_rpl.c
@@ -1165,20 +1165,15 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN
switch(rpl_event->event_type) {
case UNKNOWN_EVENT:
case SLAVE_EVENT:
- return rpl_event;
- break;
+ return rpl_event;
+ break;
+
case HEARTBEAT_LOG_EVENT:
- /* no post header size */
- RPL_CHECK_POS(ev, ev_end, 11);
- rpl_event->event.heartbeat.timestamp= uint4korr(ev);
- ev+= 4;
- rpl_event->event.heartbeat.next_position= uint4korr(ev);
- ev+= 4;
- rpl_event->event.heartbeat.type= (uint8_t)*ev;
- ev+= 1;
- rpl_event->event.heartbeat.flags= uint2korr(ev);
- ev+= 2;
-
+ len= rpl_event->event_length - (ev - ev_start) - (rpl->use_checksum ? 4 : 0) - (EVENT_HEADER_OFS - 1);
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_event->event.heartbeat.filename.length= len;
+ rpl_event->event.heartbeat.filename.str= (char *)ev;
+ ev+= len;
break;
case BEGIN_LOAD_QUERY_EVENT:
@@ -1835,7 +1830,7 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN
if (rpl_event->event.rows.extra_data_size - 2 > 0)
{
rpl_alloc_set_string_and_len(rpl_event, rpl_event->event.rows.extra_data, ev, rpl_event->event.rows.extra_data_size - 2);
- ev+= rpl_event->event.rows.extra_data_size;
+ ev+= (rpl_event->event.rows.extra_data_size -2);
}
}
/* END_ROWS_EVENT_V2 */
diff --git a/libmariadb/libmariadb/mariadb_stmt.c b/libmariadb/libmariadb/mariadb_stmt.c
index 5bcecfde..cb37359e 100644
--- a/libmariadb/libmariadb/mariadb_stmt.c
+++ b/libmariadb/libmariadb/mariadb_stmt.c
@@ -123,6 +123,26 @@ void stmt_set_error(MYSQL_STMT *stmt,
return;
}
+/* checks if there are any other statements which have a
+ pending result set */
+static my_bool madb_have_pending_results(MYSQL_STMT *stmt)
+{
+ LIST *li_stmt;
+
+ if (!stmt->mysql)
+ return 0;
+
+ li_stmt= stmt->mysql->stmts;
+ for (;li_stmt;li_stmt= li_stmt->next)
+ {
+ MYSQL_STMT *s= (MYSQL_STMT *)li_stmt->data;
+ if (s != stmt && s->state == MYSQL_STMT_WAITING_USE_OR_STORE &&
+ !(s->flags & CURSOR_TYPE_READ_ONLY))
+ return 1;
+ }
+ return 0;
+}
+
my_bool mthd_supported_buffer_type(enum enum_field_types type)
{
switch (type) {
@@ -911,7 +931,7 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
0 4 Statement id
4 2 Flags (cursor type):
STMT_BULK_FLAG_CLIENT_SEND_TYPES = 128
- STMT_BULK_FLAG_INSERT_ID_REQUEST = 64
+ STMT_BULK_FLAG_SEND_UNIT_RESULTS = 64
-----------------------------------------
if (stmt->send_types_to_server):
for (i=0; i < param_count; i++)
@@ -964,6 +984,9 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
/* todo: request to return auto generated ids */
if (stmt->send_types_to_server)
flags|= STMT_BULK_FLAG_CLIENT_SEND_TYPES;
+ if (MARIADB_STMT_BULK_UNIT_RESULTS_SUPPORTED(stmt))
+ flags|= STMT_BULK_FLAG_SEND_UNIT_RESULTS;
+
int2store(p, flags);
p+=2;
@@ -1486,6 +1509,12 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
my_bool rc= 1;
+ if (madb_have_pending_results(stmt))
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
if (stmt)
{
if (stmt->mysql && stmt->mysql->net.pvio)
@@ -1610,6 +1639,12 @@ unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
{
+ if (stmt->state < MYSQL_STMT_EXECUTED || !stmt->field_count)
+ {
+ stmt_set_error(stmt, CR_STMT_NO_RESULT, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_STORED |
MADB_RESET_BUFFER | MADB_RESET_ERROR);
}
@@ -2196,6 +2231,14 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
MYSQL *mysql= stmt->mysql;
my_bool ret= 0;
+ /* CONC-667: If an other statement has a pending result set, we
+ need to return an error */
+ if (madb_have_pending_results(stmt))
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
if (!stmt->mysql)
{
stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
@@ -2294,7 +2337,8 @@ static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close)
stmt->fetch_row_func == stmt_unbuffered_fetch)
flags|= MADB_RESET_BUFFER;
- ret= madb_reset_stmt(stmt, flags);
+ if ((ret= madb_reset_stmt(stmt, flags)))
+ return ret;
if (stmt->stmt_id)
{
diff --git a/libmariadb/libmariadb/secure/gnutls.c b/libmariadb/libmariadb/secure/gnutls.c
index 4782be62..0d40746e 100644
--- a/libmariadb/libmariadb/secure/gnutls.c
+++ b/libmariadb/libmariadb/secure/gnutls.c
@@ -995,9 +995,6 @@ static size_t ma_gnutls_get_protocol_version(const char *tls_version_option,
if (!tls_version_option || !tls_version_option[0])
goto end;
-
- if (strstr(tls_version_option, "TLSv1.0"))
- strcat(tls_versions, ":+VERS-TLS1.0");
if (strstr(tls_version_option, "TLSv1.1"))
strcat(tls_versions, ":+VERS-TLS1.1");
if (strstr(tls_version_option, "TLSv1.2"))
@@ -1010,7 +1007,7 @@ end:
if (tls_versions[0])
snprintf(priority_string, prio_len - 1, "-VERS-TLS-ALL%s:NORMAL", tls_versions);
else
- strncpy(priority_string, "NORMAL:+VERS-ALL", prio_len - 1);
+ strncpy(priority_string, "NORMAL:+VERS-ALL+!VERS-TLS1.0", prio_len - 1);
return strlen(priority_string);
}
@@ -1176,6 +1173,8 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
MARIADB_PVIO *pvio;
int ret;
+ const gnutls_datum_t *cert_list;
+ unsigned int list_size= 0;
if (!mysql)
return 1;
@@ -1217,6 +1216,42 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
return 1;
}
ctls->ssl= (void *)ssl;
+
+ /* retrieve peer certificate information */
+ if ((cert_list= gnutls_certificate_get_peers(ssl, &list_size)))
+ {
+ 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))
+ {
+ size_t len= 0;
+ char fp[33];
+ time_t notBefore, notAfter;
+
+ ctls->cert_info.version= gnutls_x509_crt_get_version(cert);
+
+ gnutls_x509_crt_get_issuer_dn(cert, NULL, &len);
+ if ((ctls->cert_info.issuer= (char *)malloc(len)))
+ gnutls_x509_crt_get_issuer_dn(cert, ctls->cert_info.issuer, &len);
+
+ gnutls_x509_crt_get_dn(cert, NULL, &len);
+ if ((ctls->cert_info.subject= (char *)malloc(len)))
+ gnutls_x509_crt_get_dn(cert, ctls->cert_info.subject, &len);
+
+ notBefore= gnutls_x509_crt_get_activation_time(cert);
+ memcpy(&ctls->cert_info.not_before, gmtime(&notBefore), sizeof(struct tm));
+
+ 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;
}
@@ -1324,6 +1359,8 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
gnutls_certificate_free_ca_names(ctx);
gnutls_certificate_free_credentials(ctx);
gnutls_deinit((gnutls_session_t )ctls->ssl);
+ free(ctls->cert_info.issuer);
+ free(ctls->cert_info.subject);
ctls->ssl= NULL;
}
return 0;
@@ -1357,7 +1394,7 @@ static int my_verify_callback(gnutls_session_t ssl)
CLEAR_CLIENT_ERROR(mysql);
- if ((mysql->options.extension->tls_verify_server_cert))
+ if (!mysql->options.extension->tls_allow_invalid_server_cert)
{
const char *hostname= mysql->host;
@@ -1371,10 +1408,22 @@ static int my_verify_callback(gnutls_session_t ssl)
{
gnutls_datum_t out;
int type;
- /* accept self signed certificates if we don't have to verify server cert */
- if (!(mysql->options.extension->tls_verify_server_cert) &&
- (status & GNUTLS_CERT_SIGNER_NOT_FOUND))
- return 0;
+
+ 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 */
@@ -1391,18 +1440,43 @@ static int my_verify_callback(gnutls_session_t ssl)
return 0;
}
-unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+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;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
+ gnutls_digest_algorithm_t hash_alg;
if (!ctls || !ctls->ssl)
return 0;
mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
+ switch (hash_type)
+ {
+ case MA_HASH_SHA1:
+ hash_alg = GNUTLS_DIG_SHA1;
+ break;
+ case MA_HASH_SHA224:
+ hash_alg = GNUTLS_DIG_SHA224;
+ break;
+ case MA_HASH_SHA256:
+ hash_alg = GNUTLS_DIG_SHA256;
+ break;
+ case MA_HASH_SHA384:
+ hash_alg = GNUTLS_DIG_SHA384;
+ break;
+ case MA_HASH_SHA512:
+ hash_alg = GNUTLS_DIG_SHA512;
+ break;
+ default:
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Cannot detect hash algorithm for fingerprint verification");
+ return 0;
+ }
+
cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
if (cert_list == NULL)
{
@@ -1412,7 +1486,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int l
return 0;
}
- if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0)
+ if (gnutls_fingerprint(hash_alg, &cert_list[0], fp, &fp_len) == 0)
return fp_len;
else
{
diff --git a/libmariadb/libmariadb/secure/gnutls_crypt.c b/libmariadb/libmariadb/secure/gnutls_crypt.c
index a669e88e..222e5585 100644
--- a/libmariadb/libmariadb/secure/gnutls_crypt.c
+++ b/libmariadb/libmariadb/secure/gnutls_crypt.c
@@ -34,8 +34,6 @@ static gnutls_digest_algorithm_t ma_hash_get_algorithm(unsigned int alg)
return GNUTLS_DIG_SHA384;
case MA_HASH_SHA512:
return GNUTLS_DIG_SHA512;
- case MA_HASH_RIPEMD160:
- return GNUTLS_DIG_RMD160;
default:
return GNUTLS_DIG_UNKNOWN;
}
diff --git a/libmariadb/libmariadb/secure/ma_schannel.c b/libmariadb/libmariadb/secure/ma_schannel.c
index be4148c7..10ea3318 100644
--- a/libmariadb/libmariadb/secure/ma_schannel.c
+++ b/libmariadb/libmariadb/secure/ma_schannel.c
@@ -526,6 +526,13 @@ my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
end:
if (!ret)
{
+ /* postpone the error for self signed certificates if CA isn't set */
+ if (status == CERT_E_UNTRUSTEDROOT && !ca_file && !ca_path)
+ {
+ mysql->net.tls_self_signed_error= strdup(errmsg);
+ ret= 1;
+ }
+ else
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, errmsg);
}
if (pServerCert)
diff --git a/libmariadb/libmariadb/secure/ma_schannel.h b/libmariadb/libmariadb/secure/ma_schannel.h
index af7fc602..562dae1f 100644
--- a/libmariadb/libmariadb/secure/ma_schannel.h
+++ b/libmariadb/libmariadb/secure/ma_schannel.h
@@ -28,6 +28,7 @@
#include <ma_common.h>
#include <ma_pvio.h>
#include <errmsg.h>
+#include <ma_hash.h>
#include <wincrypt.h>
@@ -35,6 +36,7 @@
#include <security.h>
+#include <ma_crypt.h>
#include <schnlsp.h>
#undef SECURITY_WIN32
@@ -57,7 +59,7 @@ struct st_schannel {
DWORD IoBufferSize;
SecPkgContext_StreamSizes Sizes;
CtxtHandle hCtxt;
-
+ BCRYPT_ALG_HANDLE HashProv[MA_MAX_HASH_SIZE];
/* Cached data from the last read/decrypt call.*/
SecBuffer extraBuf; /* encrypted data read from server. */
SecBuffer dataBuf; /* decrypted but still unread data from server.*/
diff --git a/libmariadb/libmariadb/secure/openssl.c b/libmariadb/libmariadb/secure/openssl.c
index edc90a3b..828c3121 100644
--- a/libmariadb/libmariadb/secure/openssl.c
+++ b/libmariadb/libmariadb/secure/openssl.c
@@ -29,6 +29,10 @@
#include <openssl/err.h> /* error reporting */
#include <openssl/conf.h>
#include <openssl/md4.h>
+#include <ma_tls.h>
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#include <time.h>
+#endif
#if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C)
#include <openssl/applink.c>
@@ -103,8 +107,6 @@ static long ma_tls_version_options(const char *version)
if (!version)
return 0;
- if (strstr(version, "TLSv1.0"))
- protocol_options&= ~SSL_OP_NO_TLSv1;
if (strstr(version, "TLSv1.1"))
protocol_options&= ~SSL_OP_NO_TLSv1_1;
if (strstr(version, "TLSv1.2"))
@@ -420,7 +422,8 @@ void *ma_tls_init(MYSQL *mysql)
SSL_CTX *ctx= NULL;
long default_options= SSL_OP_ALL |
SSL_OP_NO_SSLv2 |
- SSL_OP_NO_SSLv3;
+ SSL_OP_NO_SSLv3 |
+ SSL_OP_NO_TLSv1;
long options= 0;
pthread_mutex_lock(&LOCK_openssl_config);
@@ -463,6 +466,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
MYSQL *mysql;
MARIADB_PVIO *pvio;
int rc;
+ X509 *cert;
#ifdef OPENSSL_USE_BIOMETHOD
BIO_METHOD *bio_method= NULL;
BIO *bio;
@@ -505,13 +509,17 @@ 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_verify_server_cert ||
+ if (rc != 1 || !mysql->options.extension->tls_allow_invalid_server_cert ||
mysql->options.ssl_ca || mysql->options.ssl_capath)
{
long x509_err= SSL_get_verify_result(ssl);
- if (x509_err != X509_V_OK)
+ 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,
+ 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)
@@ -525,6 +533,40 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
}
pvio->ctls->ssl= ctls->ssl= (void *)ssl;
+ /* Store peer certificate information */
+ 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);
+ ASN1_TIME_to_tm(not_before, (struct tm *)&ctls->cert_info.not_before);
+ ASN1_TIME_to_tm(not_after, (struct tm *)&ctls->cert_info.not_after);
+#else
+ const ASN1_TIME *not_before= X509_get_notBefore(cert),
+ *not_after= X509_get_notAfter(cert);
+ time_t now, from, to;
+ int pday, psec;
+ /* ANS1_TIME_diff returns days and seconds between now and the
+ specified ASN1_TIME */
+ time(&now);
+ ASN1_TIME_diff(&pday, &psec, not_before, NULL);
+ from= now - (pday * 86400 + psec);
+ gmtime_r(&from, &ctls->cert_info.not_before);
+ ASN1_TIME_diff(&pday, &psec, NULL, not_after);
+ to= now + (pday * 86400 + psec);
+ gmtime_r(&to, &ctls->cert_info.not_after);
+#endif
+ 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;
}
@@ -650,6 +692,9 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
SSL_free(ssl);
ctls->ssl= NULL;
+ OPENSSL_free(ctls->cert_info.issuer);
+ OPENSSL_free(ctls->cert_info.subject);
+
return rc;
}
@@ -729,33 +774,64 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
return SSL_get_cipher_name(ctls->ssl);
}
-unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
{
X509 *cert= NULL;
MYSQL *mysql;
unsigned int fp_len;
+ const EVP_MD *hash_alg;
+ unsigned int max_len= EVP_MAX_MD_SIZE;
if (!ctls || !ctls->ssl)
return 0;
- mysql= SSL_get_app_data(ctls->ssl);
+ mysql = SSL_get_app_data(ctls->ssl);
- if (!(cert= SSL_get_peer_certificate(ctls->ssl)))
+ switch (hash_type)
{
+ case MA_HASH_SHA1:
+ hash_alg = EVP_sha1();
+ max_len= 20;
+ break;
+ case MA_HASH_SHA224:
+ hash_alg = EVP_sha224();
+ max_len= 28;
+ break;
+ case MA_HASH_SHA256:
+ hash_alg = EVP_sha256();
+ max_len= 32;
+ break;
+ case MA_HASH_SHA384:
+ hash_alg = EVP_sha384();
+ max_len= 48;
+ break;
+ case MA_HASH_SHA512:
+ hash_alg = EVP_sha512();
+ break;
+ default:
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
- ER(CR_SSL_CONNECTION_ERROR),
- "Unable to get server certificate");
- goto end;
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Cannot detect hash algorithm for fingerprint verification");
+ return 0;
}
- if (len < EVP_MAX_MD_SIZE)
+ if (len < max_len)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Finger print buffer too small");
+ return 0;
+ }
+
+ if (!(cert= SSL_get_peer_certificate(ctls->ssl)))
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Unable to get server certificate");
goto end;
}
- if (!X509_digest(cert, EVP_sha1(), (unsigned char *)fp, &fp_len))
+
+ if (!X509_digest(cert, hash_alg, (unsigned char *)fp, &fp_len))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
diff --git a/libmariadb/libmariadb/secure/openssl_crypt.c b/libmariadb/libmariadb/secure/openssl_crypt.c
index faf755c9..fd3538ba 100644
--- a/libmariadb/libmariadb/secure/openssl_crypt.c
+++ b/libmariadb/libmariadb/secure/openssl_crypt.c
@@ -36,8 +36,6 @@ static const EVP_MD *ma_hash_get_algorithm(unsigned int alg)
return EVP_sha384();
case MA_HASH_SHA512:
return EVP_sha512();
- case MA_HASH_RIPEMD160:
- return EVP_ripemd160();
default:
return NULL;
}
diff --git a/libmariadb/libmariadb/secure/schannel.c b/libmariadb/libmariadb/secure/schannel.c
index 8069af53..a6617d2e 100644
--- a/libmariadb/libmariadb/secure/schannel.c
+++ b/libmariadb/libmariadb/secure/schannel.c
@@ -20,6 +20,9 @@
#include "ma_schannel.h"
#include "schannel_certs.h"
#include <string.h>
+#include <ma_crypt.h>
+#include <wincrypt.h>
+#include <bcrypt.h>
extern my_bool ma_tls_initialized;
char tls_library_version[] = "Schannel";
@@ -29,6 +32,8 @@ char tls_library_version[] = "Schannel";
#define PROT_TLS1_2 4
#define PROT_TLS1_3 8
+unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls);
+
static struct
{
DWORD cipher_id;
@@ -418,15 +423,13 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
if (mysql->options.extension && mysql->options.extension->tls_version)
{
- if (strstr(mysql->options.extension->tls_version, "TLSv1.0"))
- Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0_CLIENT;
if (strstr(mysql->options.extension->tls_version, "TLSv1.1"))
Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1_CLIENT;
if (strstr(mysql->options.extension->tls_version, "TLSv1.2"))
Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2_CLIENT;
}
if (!Cred.grbitEnabledProtocols)
- Cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
+ Cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
if (ma_tls_set_client_certs(ctls, &cert_context))
@@ -448,14 +451,15 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
goto end;
verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
- (mysql->options.extension->tls_verify_server_cert);
+ !mysql->options.extension->tls_allow_invalid_server_cert;
if (verify_certs)
{
- if (!ma_schannel_verify_certs(ctls, mysql->options.extension->tls_verify_server_cert))
+ if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert))
goto end;
}
+ ma_set_tls_x509_info(ctls);
rc = 0;
end:
@@ -510,6 +514,8 @@ my_bool ma_tls_close(MARIADB_TLS *ctls)
DeleteSecurityContext(&sctx->hCtxt);
}
LocalFree(sctx);
+ LocalFree(ctls->cert_info.issuer);
+ LocalFree(ctls->cert_info.subject);
return 0;
}
/* }}} */
@@ -550,15 +556,87 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
return cipher_name(&CipherInfo);
}
-unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+unsigned char *ma_cert_blob_to_str(PCERT_NAME_BLOB cnblob)
+{
+ DWORD type= CERT_X500_NAME_STR;
+ DWORD size= CertNameToStrA(X509_ASN_ENCODING, cnblob, type, NULL, 0);
+ char *str= NULL;
+
+ if (!size)
+ return NULL;
+
+ str= (char *)LocalAlloc(LMEM_ZEROINIT,size);
+ CertNameToStrA(X509_ASN_ENCODING, cnblob, type, str, size);
+ return str;
+}
+
+static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm)
{
+ memset(tm, 0, sizeof(struct tm));
+ tm->tm_year= sys_tm.wYear - 1900;
+ tm->tm_mon= sys_tm.wMonth - 1;
+ tm->tm_mday= sys_tm.wDay;
+ tm->tm_hour = sys_tm.wHour;
+ tm->tm_min = sys_tm.wMinute;
+}
+
+unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls)
+{
+ PCCERT_CONTEXT pCertCtx= NULL;
+ SC_CTX *sctx= (SC_CTX *)ctls->ssl;
+ PCERT_INFO pci= NULL;
+ DWORD size´= 0;
+ SYSTEMTIME tm;
+ char fp[33];
+
+ if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK)
+ return 1;
+
+ pci= pCertCtx->pCertInfo;
+
+ ctls->cert_info.version= pci->dwVersion;
+ ctls->cert_info.subject = ma_cert_blob_to_str(&pci->Subject);
+ ctls->cert_info.issuer = ma_cert_blob_to_str(&pci->Issuer);
+
+ FileTimeToSystemTime(&pci->NotBefore, &tm);
+ 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);
+
+ return 0;
+}
+
+
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
+{
+ MA_HASH_CTX* hash_ctx;
+
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
PCCERT_CONTEXT pRemoteCertContext = NULL;
+ int rc= 0;
+
+ if (hash_type == MA_HASH_SHA224)
+ {
+ MYSQL *mysql = ctls->pvio->mysql;
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "SHA224 hash for fingerprint verification is not supported in Schannel");
+ return 0;
+ }
+
if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
return 0;
- CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
+
+ hash_ctx = ma_hash_new(hash_type);
+ ma_hash_input(hash_ctx, pRemoteCertContext->pbCertEncoded, pRemoteCertContext->cbCertEncoded);
+ ma_hash_result(hash_ctx, fp);
+ ma_hash_free(hash_ctx);
+
CertFreeCertificateContext(pRemoteCertContext);
- return len;
+ return (uint)ma_hash_digest_size(hash_type);
}
void ma_tls_set_connection(MYSQL *mysql __attribute__((unused)))
diff --git a/libmariadb/plugins/auth/CMakeLists.txt b/libmariadb/plugins/auth/CMakeLists.txt
index 83e324b9..d04fc7f1 100644
--- a/libmariadb/plugins/auth/CMakeLists.txt
+++ b/libmariadb/plugins/auth/CMakeLists.txt
@@ -108,12 +108,12 @@ IF(NOT WIN32)
ELSE()
SET(GSSAPI_LIBS secur32)
SET(GSSAPI_SOURCES ${AUTH_DIR}/auth_gssapi_client.c ${AUTH_DIR}/sspi_client.c ${AUTH_DIR}/sspi_errmsg.c)
- SET(AUTH_GSSAPI_DEFAULT_CONFIG STATIC)
+ SET(AUTH_GSSAPI_DEFAULT_CONFIG DYNAMIC_AND_STATIC)
ENDIF()
IF(GSSAPI_SOURCES)
REGISTER_PLUGIN(TARGET auth_gssapi_client
TYPE MARIADB_CLIENT_PLUGIN_AUTH
- CONFIGURATIONS DYNAMIC STATIC OFF
+ CONFIGURATIONS DYNAMIC STATIC OFF DYNAMIC_AND_STATIC
DEFAULT ${AUTH_GSSAPI_DEFAULT_CONFIG}
SOURCES ${GSSAPI_SOURCES}
INCLUDES ${CC_SOURCE_DIR}/plugins/auth ${GSSAPI_INCS}
@@ -131,6 +131,7 @@ REGISTER_PLUGIN(TARGET mysql_old_password
TYPE MARIADB_CLIENT_PLUGIN_AUTH
CONFIGURATIONS STATIC DYNAMIC OFF
DEFAULT STATIC
+ DISABLED YES
SOURCES ${AUTH_DIR}/old_password.c)
# Cleartext
diff --git a/libmariadb/plugins/auth/auth_gssapi_client.c b/libmariadb/plugins/auth/auth_gssapi_client.c
index 6f6c6ceb..19cdf246 100644
--- a/libmariadb/plugins/auth/auth_gssapi_client.c
+++ b/libmariadb/plugins/auth/auth_gssapi_client.c
@@ -117,5 +117,6 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
- gssapi_auth_client
+ gssapi_auth_client,
+ NULL
};
diff --git a/libmariadb/plugins/auth/caching_sha2_pw.c b/libmariadb/plugins/auth/caching_sha2_pw.c
index b442e477..14abb0c8 100644
--- a/libmariadb/plugins/auth/caching_sha2_pw.c
+++ b/libmariadb/plugins/auth/caching_sha2_pw.c
@@ -145,7 +145,8 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_caching_sha2_init,
auth_caching_sha2_deinit,
NULL,
- auth_caching_sha2_client
+ auth_caching_sha2_client,
+ NULL
};
#ifdef HAVE_WINCRYPT
diff --git a/libmariadb/plugins/auth/dialog.c b/libmariadb/plugins/auth/dialog.c
index 31d7b7d8..8513e9ac 100644
--- a/libmariadb/plugins/auth/dialog.c
+++ b/libmariadb/plugins/auth/dialog.c
@@ -58,7 +58,8 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_dialog_init,
NULL,
NULL,
- auth_dialog_open
+ auth_dialog_open,
+ NULL
};
diff --git a/libmariadb/plugins/auth/ed25519.c b/libmariadb/plugins/auth/ed25519.c
index 38b896f8..ff2f39a5 100644
--- a/libmariadb/plugins/auth/ed25519.c
+++ b/libmariadb/plugins/auth/ed25519.c
@@ -64,6 +64,7 @@ static int auth_ed25519_init(char *unused1,
size_t unused2,
int unused3,
va_list);
+static int auth_ed25519_hash(MYSQL *, unsigned char *out, size_t *outlen);
#ifndef PLUGIN_DYNAMIC
@@ -77,21 +78,25 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
"client_ed25519",
"Sergei Golubchik, Georg Richter",
"Ed25519 Authentication Plugin",
- {0,1,0},
+ {0,1,1},
"LGPL",
NULL,
auth_ed25519_init,
auth_ed25519_deinit,
NULL,
- auth_ed25519_client
+ auth_ed25519_client,
+ auth_ed25519_hash
};
static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
unsigned char *packet,
- signature[CRYPTO_BYTES + NONCE_BYTES];
- int pkt_len;
+ signature[CRYPTO_BYTES + NONCE_BYTES],
+ pk[CRYPTO_PUBLICKEYBYTES];
+ unsigned long long pkt_len;
+ size_t pwlen= strlen(mysql->passwd);
+ char *newpw;
/*
Step 1: Server sends nonce
@@ -106,16 +111,36 @@ static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return CR_SERVER_HANDSHAKE_ERR;
/* Sign nonce: the crypto_sign function is part of ref10 */
- ma_crypto_sign(signature, packet, NONCE_BYTES, (unsigned char*)mysql->passwd, strlen(mysql->passwd));
+ ma_crypto_sign(signature, pk, packet, NONCE_BYTES, (unsigned char*)mysql->passwd, pwlen);
/* send signature to server */
if (vio->write_packet(vio, signature, CRYPTO_BYTES))
return CR_ERROR;
+ /* save pk for the future auth_ed25519_hash() call */
+ if ((newpw= realloc(mysql->passwd, pwlen + 1 + sizeof(pk))))
+ {
+ memcpy(newpw + pwlen + 1, pk, sizeof(pk));
+ mysql->passwd= newpw;
+ }
+
return CR_OK;
}
/* }}} */
+/* {{{ static int auth_ed25519_hash */
+static int auth_ed25519_hash(MYSQL *mysql, unsigned char *out, size_t *outlen)
+{
+ if (*outlen < CRYPTO_PUBLICKEYBYTES)
+ return 1;
+ *outlen= CRYPTO_PUBLICKEYBYTES;
+
+ /* use the cached value */
+ memcpy(out, mysql->passwd + strlen(mysql->passwd) + 1, CRYPTO_PUBLICKEYBYTES);
+ return 0;
+}
+/* }}} */
+
/* {{{ static int auth_ed25519_init */
static int auth_ed25519_init(char *unused1 __attribute__((unused)),
size_t unused2 __attribute__((unused)),
diff --git a/libmariadb/plugins/auth/mariadb_cleartext.c b/libmariadb/plugins/auth/mariadb_cleartext.c
index b63c1d3b..92e56547 100644
--- a/libmariadb/plugins/auth/mariadb_cleartext.c
+++ b/libmariadb/plugins/auth/mariadb_cleartext.c
@@ -70,7 +70,8 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
- clear_password_auth_client
+ clear_password_auth_client,
+ NULL
};
diff --git a/libmariadb/plugins/auth/my_auth.c b/libmariadb/plugins/auth/my_auth.c
index 72773079..faea968c 100644
--- a/libmariadb/plugins/auth/my_auth.c
+++ b/libmariadb/plugins/auth/my_auth.c
@@ -3,16 +3,29 @@
#include <errmsg.h>
#include <string.h>
#include <ma_common.h>
+#include <ma_crypt.h>
#include <mysql/client_plugin.h>
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, size_t);
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int native_password_hash(MYSQL *mysql, unsigned char *out, size_t *outlen);
static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attribute__((unused)));
extern void read_user_name(char *name);
extern char *ma_send_connect_attr(MYSQL *mysql, unsigned char *buffer);
extern int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length);
extern unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length);
+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;
+}
typedef struct {
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
@@ -44,13 +57,14 @@ auth_plugin_t mysql_native_password_client_plugin=
native_password_plugin_name,
"R.J.Silk, Sergei Golubchik",
"Native MySQL authentication",
- {1, 0, 0},
+ {1, 0, 1},
"LGPL",
NULL,
NULL,
NULL,
NULL,
- native_password_auth_client
+ native_password_auth_client,
+ native_password_hash
};
@@ -97,6 +111,22 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return CR_OK;
}
+static int native_password_hash(MYSQL *mysql, unsigned char *out, size_t *out_length)
+{
+ unsigned char digest[MA_SHA1_HASH_SIZE];
+
+ if (*out_length < MA_SHA1_HASH_SIZE)
+ return 1;
+ *out_length= MA_SHA1_HASH_SIZE;
+
+ /* would it be better to reuse instead of recalculating here? see ed25519 */
+ ma_hash(MA_HASH_SHA1, (unsigned char*)mysql->passwd, strlen(mysql->passwd),
+ digest);
+ ma_hash(MA_HASH_SHA1, digest, sizeof(digest), out);
+
+ return 0;
+}
+
auth_plugin_t dummy_fallback_client_plugin=
{
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
@@ -110,7 +140,8 @@ auth_plugin_t dummy_fallback_client_plugin=
NULL,
NULL,
NULL,
- dummy_fallback_auth_client
+ dummy_fallback_auth_client,
+ NULL
};
@@ -223,7 +254,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mysql->options.ssl_key || mysql->options.ssl_cert ||
mysql->options.ssl_ca || mysql->options.ssl_capath ||
mysql->options.ssl_cipher || mysql->options.use_ssl ||
- mysql->options.extension->tls_verify_server_cert)
+ !mysql->options.extension->tls_allow_invalid_server_cert)
mysql->options.use_ssl= 1;
if (mysql->options.use_ssl)
mysql->client_flag|= CLIENT_SSL;
@@ -243,15 +274,16 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
mysql->net.pvio->type == PVIO_TYPE_SHAREDMEM))
{
mysql->server_capabilities &= ~(CLIENT_SSL);
+ mysql->options.extension->tls_allow_invalid_server_cert= 1;
}
/* if server doesn't support SSL and verification of server certificate
was set to mandatory, we need to return an error */
if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
{
- if (mysql->options.extension->tls_verify_server_cert ||
- (mysql->options.extension && (mysql->options.extension->tls_fp ||
- mysql->options.extension->tls_fp_list)))
+ if (!mysql->options.extension->tls_allow_invalid_server_cert ||
+ mysql->options.extension->tls_fp ||
+ mysql->options.extension->tls_fp_list)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
@@ -307,9 +339,11 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (!(mysql->server_capabilities & CLIENT_MYSQL))
{
uint server_extended_cap= mysql->extension->mariadb_server_capabilities;
- uint client_extended_cap= (uint)(MARIADB_CLIENT_SUPPORTED_FLAGS >> 32);
+ ulonglong client_extended_flag = CLIENT_DEFAULT_EXTENDED_FLAGS;
+ if (mysql->options.extension && mysql->options.extension->bulk_unit_results)
+ client_extended_flag|= MARIADB_CLIENT_BULK_UNIT_RESULTS;
mysql->extension->mariadb_client_flag=
- server_extended_cap & client_extended_cap;
+ server_extended_cap & (long)(client_extended_flag >> 32);
int4store(buff + 28, mysql->extension->mariadb_client_flag);
}
end= buff+32;
@@ -350,6 +384,13 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
}
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)))
+ {
+ /* cannot use auth to validate the cert */
+ set_error_from_tls_self_signed_error(mysql);
+ goto error;
+ }
}
#endif /* HAVE_TLS */
@@ -658,13 +699,13 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
retry:
mpvio.plugin= auth_plugin;
- if (auth_plugin_name &&
- mysql->options.extension &&
- mysql->options.extension->restricted_auth)
+ if (auth_plugin_name)
{
- if (!strstr(mysql->options.extension->restricted_auth, auth_plugin_name))
+ if ((mysql->options.extension && mysql->options.extension->restricted_auth)
+ ? !strstr(mysql->options.extension->restricted_auth, auth_plugin_name)
+ : strstr(disabled_plugins, auth_plugin_name) != NULL)
{
- my_set_error(mysql, CR_PLUGIN_NOT_ALLOWED, SQLSTATE_UNKNOWN, 0, data_plugin);
+ my_set_error(mysql, CR_PLUGIN_NOT_ALLOWED, SQLSTATE_UNKNOWN, 0, auth_plugin_name);
return 1;
}
}
@@ -727,15 +768,62 @@ retry:
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
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);
goto retry;
-
}
/*
net->read_pos[0] should always be 0 here if the server implements
the protocol correctly
*/
- if (mysql->net.read_pos[0] == 0)
- return ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length);
- return 1;
+ if (mysql->net.read_pos[0] != 0)
+ return 1;
+ if (ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length))
+ return -1;
+
+ if (!mysql->net.tls_self_signed_error)
+ return 0;
+
+ assert(mysql->options.use_ssl);
+ assert(!mysql->options.extension->tls_allow_invalid_server_cert);
+ assert(!mysql->options.ssl_ca);
+ assert(!mysql->options.ssl_capath);
+ assert(!mysql->options.extension->tls_fp);
+ assert(!mysql->options.extension->tls_fp_list);
+ assert(hashing(auth_plugin));
+ assert(mysql->passwd[0]);
+ if (mysql->info && mysql->info[0] == '\1')
+ {
+ MA_HASH_CTX *ctx = NULL;
+ unsigned char buf[1024], digest[MA_SHA256_HASH_SIZE];
+ char fp[128], hexdigest[sizeof(digest)*2+1], *hexsig= mysql->info + 1;
+ size_t buflen= sizeof(buf) - 1, fplen;
+
+ mysql->info= NULL; /* no need to confuse the client with binary info */
+
+ if (!(fplen= ma_tls_get_finger_print(mysql->net.pvio->ctls, MA_HASH_SHA256,
+ fp, sizeof(fp))))
+ return 1; /* error is already set */
+
+ if (auth_plugin->hash_password_bin(mysql, buf, &buflen) ||
+ !(ctx= ma_hash_new(MA_HASH_SHA256)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
+ ma_hash_input(ctx, (unsigned char*)buf, buflen);
+ ma_hash_input(ctx, (unsigned char*)mysql->scramble_buff, SCRAMBLE_LENGTH);
+ ma_hash_input(ctx, (unsigned char*)fp, fplen);
+ ma_hash_result(ctx, digest);
+ ma_hash_free(ctx);
+
+ mysql_hex_string(hexdigest, (char*)digest, sizeof(digest));
+ if (strcmp(hexdigest, hexsig) == 0)
+ return 0; /* phew. self-signed certificate is validated! */
+ }
+
+ return set_error_from_tls_self_signed_error(mysql);
}
diff --git a/libmariadb/plugins/auth/old_password.c b/libmariadb/plugins/auth/old_password.c
index 07756e92..3f7d533c 100644
--- a/libmariadb/plugins/auth/old_password.c
+++ b/libmariadb/plugins/auth/old_password.c
@@ -63,7 +63,8 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
- auth_old_password
+ auth_old_password,
+ NULL
};
/**
diff --git a/libmariadb/plugins/auth/ref10/crypto_sign.h b/libmariadb/plugins/auth/ref10/crypto_sign.h
index 5f9b3437..3c676885 100644
--- a/libmariadb/plugins/auth/ref10/crypto_sign.h
+++ b/libmariadb/plugins/auth/ref10/crypto_sign.h
@@ -3,7 +3,7 @@ int crypto_sign_keypair(
unsigned char *pw, unsigned long long pwlen
);
int ma_crypto_sign(
- unsigned char *sm,
+ unsigned char *sm, unsigned char *pk,
const unsigned char *m, unsigned long long mlen,
const unsigned char *pw, unsigned long long pwlen
);
diff --git a/libmariadb/plugins/auth/ref10/sign.c b/libmariadb/plugins/auth/ref10/sign.c
index b4153201..421a0aed 100644
--- a/libmariadb/plugins/auth/ref10/sign.c
+++ b/libmariadb/plugins/auth/ref10/sign.c
@@ -5,7 +5,7 @@
#include "sc.h"
int ma_crypto_sign(
- unsigned char *sm,
+ unsigned char *sm, unsigned char *pk,
const unsigned char *m,unsigned long long mlen,
const unsigned char *pw,unsigned long long pwlen
)
@@ -26,6 +26,7 @@ int ma_crypto_sign(
ge_scalarmult_base(&A,az);
ge_p3_tobytes(sm + 32,&A);
+ memmove(pk, sm + 32, 32);
sc_reduce(nonce);
ge_scalarmult_base(&R,nonce);
diff --git a/libmariadb/plugins/auth/sha256_pw.c b/libmariadb/plugins/auth/sha256_pw.c
index 79febf1a..66fb1071 100644
--- a/libmariadb/plugins/auth/sha256_pw.c
+++ b/libmariadb/plugins/auth/sha256_pw.c
@@ -76,7 +76,8 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_sha256_init,
NULL,
NULL,
- auth_sha256_client
+ auth_sha256_client,
+ NULL
};
#ifdef HAVE_WINCRYPT
diff --git a/libmariadb/travis.sh b/libmariadb/travis.sh
index c316dec2..d918b010 100755
--- a/libmariadb/travis.sh
+++ b/libmariadb/travis.sh
@@ -62,9 +62,10 @@ else
mkdir bld
cd bld
- cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCERT_PATH=${SSLCERT}
-
if [ "$TRAVIS_OS_NAME" = "windows" ] ; then
+ export WIX="c:/Program Files (x86)/WiX Toolset v3.14"
+ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCERT_PATH=${SSLCERT} -DDEFAULT_SSL_VERIFY_SERVER_CERT=OFF -DWITH_MSI=ON -DWITH_CURL=ON
+
echo "build from windows"
set MARIADB_CC_TEST=1
set MYSQL_TEST_DB=testc
@@ -77,6 +78,7 @@ else
cmake --build . --config RelWithDebInfo
else
echo "build from linux"
+ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCERT_PATH=${SSLCERT} -DDEFAULT_SSL_VERIFY_SERVER_CERT=OFF -DWITH_CURL=ON
export MARIADB_CC_TEST=1
export MYSQL_TEST_USER=$TEST_DB_USER
export MYSQL_TEST_HOST=$TEST_DB_HOST
diff --git a/libmariadb/unittest/libmariadb/CMakeLists.txt b/libmariadb/unittest/libmariadb/CMakeLists.txt
index 876e5cfc..d5b93716 100644
--- a/libmariadb/unittest/libmariadb/CMakeLists.txt
+++ b/libmariadb/unittest/libmariadb/CMakeLists.txt
@@ -31,7 +31,9 @@ IF(WITH_DYNCOL)
SET(API_TESTS ${API_TESTS} "dyncol")
ENDIF()
-SET(API_TESTS ${API_TESTS} "async")
+IF(NOT WIN32)
+ SET(API_TESTS ${API_TESTS} "async")
+ENDIF()
#exclude following tests from ctests, since we need to run them manually with different credentials
SET(MANUAL_TESTS "t_conc173" "rpl_api")
diff --git a/libmariadb/unittest/libmariadb/bulk1.c b/libmariadb/unittest/libmariadb/bulk1.c
index 62267cd7..56ae20d8 100644
--- a/libmariadb/unittest/libmariadb/bulk1.c
+++ b/libmariadb/unittest/libmariadb/bulk1.c
@@ -21,6 +21,12 @@
static my_bool bulk_enabled= 0;
+#define SERVER_SUPPORT_BULK_UNIT_RESULTS(mysql)\
+ (!(mysql->server_capabilities & CLIENT_MYSQL) &&\
+ (mysql->extension->mariadb_server_capabilities & \
+ (MARIADB_CLIENT_BULK_UNIT_RESULTS >> 32)))
+
+
char *rand_str(size_t length) {
const char charset[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
@@ -57,11 +63,14 @@ static int bulk1(MYSQL *mysql)
MYSQL_RES *res;
MYSQL_ROW row;
unsigned int intval;
+ my_bool bool_val;
if (!bulk_enabled)
return SKIP;
rc= mysql_select_db(mysql, "testc");
+ mysql_get_option(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &bool_val);
+ FAIL_IF(bool_val, "bool_val == true");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1");
check_mysql_rc(rc, mysql);
@@ -1067,6 +1076,344 @@ static int test_mdev16593(MYSQL *mysql)
return OK;
}
+static int bulk_with_unit_result_insert(MYSQL *my)
+{
+ my_bool unique_result= 1;
+ my_bool bool_val;
+ MYSQL *mysql;
+ MYSQL_STMT *stmt;
+ unsigned int array_size= TEST_ARRAY_SIZE;
+ int rc, rowcount= 0;
+ unsigned int i;
+ char **buffer;
+ unsigned long *lengths;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL_BIND bind_out[2];
+ int id, affected_rows = 0;
+ int expectedId = 1;
+ unsigned int intval;
+
+ SKIP_MAXSCALE;
+ if (!SERVER_SUPPORT_BULK_UNIT_RESULTS(my))
+ {
+ diag("Server doesn't support bulk unit results");
+ return SKIP;
+ }
+
+ mysql= mysql_init(NULL);
+ 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));
+ mysql_get_option(mysql, MARIADB_OPT_BULK_UNIT_RESULTS, &bool_val);
+ FAIL_UNLESS(bool_val, "bool_val != true");
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ rc= mysql_select_db(mysql, "testc");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_insert");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk_with_unit_result_insert (a int NOT NULL AUTO_INCREMENT, b VARCHAR(255), PRIMARY KEY (a)) engine=MyISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk_with_unit_result_insert(b) VALUES (?)"));
+ check_stmt_rc(rc, stmt);
+
+ /* allocate memory */
+ buffer= calloc(TEST_ARRAY_SIZE, sizeof(char *));
+ lengths= (unsigned long *)calloc(sizeof(long), TEST_ARRAY_SIZE);
+
+ for (i=0; i < TEST_ARRAY_SIZE; i++)
+ {
+ buffer[i]= rand_str(254);
+ lengths[i]= -1;
+ }
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 1);
+ memset(bind_out, '\0', sizeof(bind_out));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)buffer;
+ bind[0].length= (unsigned long *)lengths;
+
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &id;
+ bind_out[1].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[1].buffer= (void*) &affected_rows;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i=0; i < 100; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_stmt_rc(rc, stmt);
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rowcount++;
+ // diag("id:%llu expected %llu", id, expectedId);
+ FAIL_UNLESS(id == expectedId, "id != expectedId");
+ expectedId++;
+ // diag("affected_rows:%llu", affected_rows);
+ FAIL_UNLESS(affected_rows == 1, "affected_rows != 1");
+ }
+ // test can be improved depending on auto_increment_increment/auto_increment_offset...
+ FAIL_IF(rowcount != TEST_ARRAY_SIZE, "rowcount != TEST_ARRAY_SIZE");
+ }
+
+ for (i=0; i < array_size; i++)
+ free(buffer[i]);
+
+ free(buffer);
+ free(lengths);
+
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT COUNT(*) FROM bulk_with_unit_result_insert");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ intval= atoi(row[0]);
+ mysql_free_result(res);
+ FAIL_IF(intval != array_size * 100, "Expected 102400 rows");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_insert");
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ check_mysql_rc(rc, my);
+ return OK;
+}
+
+static int bulk_with_unit_result_delete(MYSQL *my)
+{
+ my_bool unique_result= 1;
+ unsigned int array_size= 5;
+ int rc, rowcount= 0;
+ unsigned int i, j;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL_BIND bind_out[2];
+ unsigned int *vals;
+ int id, affected_rows = 0;
+ unsigned int intval;
+ MYSQL *mysql;
+ MYSQL_STMT *stmt;
+
+ SKIP_MAXSCALE;
+ if (!SERVER_SUPPORT_BULK_UNIT_RESULTS(my))
+ {
+ diag("Server doesn't support bulk unit results");
+ return SKIP;
+ }
+
+ mysql= mysql_init(NULL);
+ 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));
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ rc= mysql_select_db(mysql, "testc");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_delete");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk_with_unit_result_delete (a int NOT NULL AUTO_INCREMENT, b VARCHAR(255), PRIMARY KEY (a))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO bulk_with_unit_result_delete(b) with recursive cte (seq) as (select 1 union all select seq+1 from cte where seq < 100) select concat(seq, 'test') from cte");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("DELETE FROM bulk_with_unit_result_delete WHERE a = ?"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind_out, '\0', sizeof(bind_out));
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &id;
+ bind_out[1].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[1].buffer= (void*) &affected_rows;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ vals= (unsigned int *)calloc(sizeof(int), 5);
+ memset(bind, 0, sizeof(MYSQL_BIND) * 1);
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= vals;
+
+ for (i=0; i < 10; i++)
+ {
+ for (j=0; j < 5; j++)
+ vals[j]= 1 + j * 2 + i * 10;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_stmt_rc(rc, stmt);
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rowcount++;
+ FAIL_UNLESS(id == 0, "id != 0");
+ FAIL_UNLESS(affected_rows == 1, "affected_rows != 1");
+ }
+ // test can be improved depending on auto_increment_increment/auto_increment_offset...
+ FAIL_UNLESS(rowcount == 5, "rowcount != 5");
+ }
+
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+ free(vals);
+ rc= mysql_query(mysql, "SELECT a FROM bulk_with_unit_result_delete");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rowcount= 0;
+ for (i=1; i < 51; i++)
+ {
+ row=mysql_fetch_row(res);
+ intval = atoi(row[0]);
+ FAIL_UNLESS(intval == i * 2, "intval != i * 2");
+ }
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_delete");
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ check_mysql_rc(rc, my);
+ return OK;
+}
+
+
+static int bulk_with_unit_result_update(MYSQL *my)
+{
+ my_bool unique_result= 1;
+ unsigned int array_size= 5;
+ int rc, rowcount= 0;
+ unsigned int i, j;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL_BIND bind_out[2];
+ unsigned int *vals;
+ int id, affected_rows = 0;
+ char str[50];
+ MYSQL *mysql;
+ MYSQL_STMT *stmt;
+
+ SKIP_MAXSCALE;
+ if (!SERVER_SUPPORT_BULK_UNIT_RESULTS(my))
+ {
+ diag("Server doesn't support bulk unit results");
+ return SKIP;
+ }
+
+ mysql= mysql_init(NULL);
+ 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));
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ rc= mysql_select_db(mysql, "testc");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_update");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk_with_unit_result_update (a int NOT NULL AUTO_INCREMENT, b VARCHAR(255), PRIMARY KEY (a))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO bulk_with_unit_result_update(b) with recursive cte (seq) as (select 1 union all select seq+1 from cte where seq < 100) select concat(seq, 'test') from cte");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("UPDATE bulk_with_unit_result_update SET b=CONCAT(b,'added') WHERE a = ?"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind_out, '\0', sizeof(bind_out));
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &id;
+ bind_out[1].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[1].buffer= (void*) &affected_rows;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ vals= (unsigned int *)calloc(sizeof(int), 5);
+ memset(bind, 0, sizeof(MYSQL_BIND) * 1);
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= vals;
+
+ for (i=0; i < 10; i++)
+ {
+ for (j=0; j < 5; j++)
+ vals[j]= 1 + j * 2 + i * 10;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_stmt_rc(rc, stmt);
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rowcount++;
+ FAIL_UNLESS(id == 0, "id != 0");
+ FAIL_UNLESS(affected_rows == 1, "affected_rows != 1");
+ }
+ // test can be improved depending on auto_increment_increment/auto_increment_offset...
+ FAIL_UNLESS(rowcount == 5, "rowcount != 5");
+ }
+
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+ free(vals);
+ rc= mysql_query(mysql, "SELECT b FROM bulk_with_unit_result_update");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rowcount= 0;
+ for (i=1; i < 101; i++)
+ {
+ row=mysql_fetch_row(res);
+ if (i % 2 == 0) {
+ sprintf(str, "%dtest", i);
+ } else {
+ sprintf(str, "%dtestadded", i);
+ }
+ FAIL_IF(strcmp(row[0], str) != 0, "strcmp(row[0], str) != 0");
+ }
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_with_unit_result_update");
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ check_mysql_rc(rc, my);
+ return OK;
+}
+
struct my_tests_st my_tests[] = {
{"check_bulk", check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_mdev16593", test_mdev16593, TEST_CONNECTION_NEW, 0, NULL, NULL},
@@ -1083,6 +1430,9 @@ struct my_tests_st my_tests[] = {
{"bulk4", bulk4, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"bulk_null", bulk_null, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"bulk_skip_row", bulk_skip_row, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk_with_unit_result_insert", bulk_with_unit_result_insert, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk_with_unit_result_delete", bulk_with_unit_result_delete, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk_with_unit_result_update", bulk_with_unit_result_update, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{NULL, NULL, 0, 0, NULL, NULL}
};
diff --git a/libmariadb/unittest/libmariadb/charset.c b/libmariadb/unittest/libmariadb/charset.c
index 4d17731f..35ae716f 100644
--- a/libmariadb/unittest/libmariadb/charset.c
+++ b/libmariadb/unittest/libmariadb/charset.c
@@ -794,6 +794,10 @@ static int test_conc223(MYSQL *mysql)
MYSQL_ROW row;
int found= 0;
int mdev27266= 0;
+ int unsupported[]= {
+ 579, /* utf8mb3_general1400_as_ci added in 11.5 */
+ 611, /* utf8mb4_general1400_as_ci added in 11.5 */
+ 0};
SKIP_MYSQL(mysql);
@@ -839,8 +843,11 @@ static int test_conc223(MYSQL *mysql)
id= atoi(row[0]);
if (!mariadb_get_charset_by_nr(id))
{
- diag("%04d %s %s", id, row[1], row[2]);
+ int j=0;
found++;
+ for (j=0; unsupported[j]; j++)
+ if (unsupported[j] == id)
+ found--;
}
}
}
diff --git a/libmariadb/unittest/libmariadb/connection.c b/libmariadb/unittest/libmariadb/connection.c
index a10e01bd..bd4e0e0a 100644
--- a/libmariadb/unittest/libmariadb/connection.c
+++ b/libmariadb/unittest/libmariadb/connection.c
@@ -686,6 +686,7 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
unsigned int timeout= 5;
time_t start, elapsed;
MYSQL *mysql;
+ my_bool no= 0;
SKIP_SKYSQL;
SKIP_MAXSCALE;
@@ -694,6 +695,7 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
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))
{
@@ -1378,7 +1380,6 @@ static int test_conc276(MYSQL *unused __attribute__((unused)))
return FAIL;
}
diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
-
rc= mariadb_reconnect(mysql);
check_mysql_rc(rc, mysql);
@@ -2307,6 +2308,49 @@ static int test_conc632(MYSQL *my __attribute__((unused)))
return OK;
}
+static int test_x509(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql1, *mysql2;
+ my_bool val= 1;
+ my_bool verify= 0;
+ char fp[65];
+ MARIADB_X509_INFO *info;
+
+ SKIP_MAXSCALE;
+
+ mysql1= mysql_init(NULL);
+ mysql2= mysql_init(NULL);
+
+ mysql_options(mysql1, MYSQL_OPT_SSL_ENFORCE, &val);
+ mysql_options(mysql2, MYSQL_OPT_SSL_ENFORCE, &val);
+
+ mysql_options(mysql1, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
+ if (!(my_test_connect(mysql1, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ return FAIL;
+ }
+ mariadb_get_infov(mysql1, MARIADB_TLS_PEER_CERT_INFO, &info);
+ memset(fp, 0, 65);
+ diag("fingerprint: %s", info->fingerprint);
+ mysql_options(mysql2, MARIADB_OPT_TLS_PEER_FP, info->fingerprint);
+ if (!(my_test_connect(mysql2, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ return FAIL;
+ }
+ mariadb_get_infov(mysql2, MARIADB_TLS_PEER_CERT_INFO, &info);
+ FAIL_IF(info->verify_mode != MARIADB_VERIFY_FINGERPRINT, "Fingerprint verification expected");
+
+ mysql_close(mysql1);
+ mysql_close(mysql2);
+ return OK;
+}
+
static int test_conc505(MYSQL *my __attribute__((unused)))
{
MYSQL *mysql= mysql_init(NULL);
@@ -2333,6 +2377,7 @@ static int test_conc505(MYSQL *my __attribute__((unused)))
}
struct my_tests_st my_tests[] = {
+ {"test_x509", test_x509, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"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/libmariadb/unittest/libmariadb/misc.c b/libmariadb/unittest/libmariadb/misc.c
index f67d1366..47f2f523 100644
--- a/libmariadb/unittest/libmariadb/misc.c
+++ b/libmariadb/unittest/libmariadb/misc.c
@@ -1628,7 +1628,37 @@ static int test_ext_field_attr(MYSQL *mysql)
return OK;
}
+static int test_disable_tls1_0(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ const char *disabled_version= "TLSv1.0";
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
+ mysql_optionsv(mysql, MARIADB_OPT_TLS_VERSION, disabled_version);
+
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(mysql));
+
+ rc= mysql_query(mysql, "SHOW STATUS LIKE 'ssl_version'");
+ check_mysql_rc(rc, mysql);
+
+ result = mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+
+ FAIL_IF(!strcmp(row[1], "TLSv1.0"), "TLS 1.0 should be disabled!");
+
+ mysql_free_result(result);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+
struct my_tests_st my_tests[] = {
+ {"test_disable_tls1_0", test_disable_tls1_0, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"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_conc458", test_conc458, TEST_CONNECTION_NONE, 0, NULL, NULL},
diff --git a/libmariadb/unittest/libmariadb/my_test.h b/libmariadb/unittest/libmariadb/my_test.h
index 9f75d67a..3184b80d 100644
--- a/libmariadb/unittest/libmariadb/my_test.h
+++ b/libmariadb/unittest/libmariadb/my_test.h
@@ -76,7 +76,7 @@ if (IS_SKYSQL(hostname)) \
#endif
#define SKIP_TLS \
-if (force_tls)\
+if (force_tls || fingerprint[0])\
{\
diag("Test doesn't work with TLS");\
return SKIP;\
@@ -224,6 +224,7 @@ MYSQL *my_test_connect(MYSQL *mysql,
static const char *schema = 0;
static char *hostname = 0;
static char *password = 0;
+static char fingerprint[65];
static unsigned int port = 0;
static unsigned int ssl_port = 0;
static char *socketname = 0;
@@ -656,7 +657,9 @@ MYSQL *my_test_connect(MYSQL *mysql,
unsigned long clientflag)
{
if (force_tls)
- mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &force_tls);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &force_tls);
+ if (fingerprint[0])
+ 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));
@@ -677,6 +680,8 @@ MYSQL *my_test_connect(MYSQL *mysql,
void run_tests(struct my_tests_st *test) {
int i, rc, total=0;
MYSQL *mysql;
+ my_bool verify= 0;
+ MARIADB_X509_INFO *info= NULL;
while (test[total].function)
total++;
@@ -684,13 +689,15 @@ void run_tests(struct my_tests_st *test) {
/* display TLS stats */
mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0))
{
+ diag("Error: %s", mysql_error(mysql));
BAIL_OUT("Can't establish TLS connection to server.");
}
-
+ fingerprint[0]= 0;
if (!mysql_query(mysql, "SHOW VARIABLES LIKE '%ssl%'"))
{
MYSQL_RES *res;
@@ -703,8 +710,15 @@ void run_tests(struct my_tests_st *test) {
while ((row= mysql_fetch_row(res)))
diag("%s: %s", row[0], row[1]);
mysql_free_result(res);
- diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
- diag("--------------------");
+ 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);
+ if (info)
+ {
+ strcpy(fingerprint, info->fingerprint);
+ diag("Peer certificate fingerprint: %s", fingerprint);
+ diag("--------------------");
+ }
}
mysql_close(mysql);
diff --git a/libmariadb/unittest/libmariadb/ps_bugs.c b/libmariadb/unittest/libmariadb/ps_bugs.c
index 72af30b4..7a581ad8 100644
--- a/libmariadb/unittest/libmariadb/ps_bugs.c
+++ b/libmariadb/unittest/libmariadb/ps_bugs.c
@@ -5741,7 +5741,77 @@ end:
return ret;
}
+static int test_conc667(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ int rc;
+
+ stmt1= mysql_stmt_init(mysql);
+ stmt2= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt1, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_prepare(stmt2, "SELECT 2", -1);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_free_result(stmt2);
+ FAIL_IF(!rc || mysql_stmt_errno(stmt2) != CR_STMT_NO_RESULT,
+ "Expected CR_STMT_NO_RESULT");
+ diag("Error (expected) %s", mysql_stmt_error(stmt2));
+
+ rc= mysql_stmt_reset(stmt2);
+ FAIL_IF(!rc || mysql_stmt_errno(stmt2) != CR_COMMANDS_OUT_OF_SYNC,
+ "Expected commands out of sync error");
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ mysql_stmt_free_result(stmt1);
+
+ rc= mysql_stmt_close(stmt1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_close(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ return OK;
+}
+
+static int test_conc683(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ int rc;
+
+ stmt1= mysql_stmt_init(mysql);
+ stmt2= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt1, "SELECT 1 UNION SELECT 2", -1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_prepare(stmt2, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_close(stmt2);
+ FAIL_IF(!rc || mysql_stmt_errno(stmt2) != CR_COMMANDS_OUT_OF_SYNC,
+ "Expected commands out of sync error");
+
+ rc= mysql_stmt_close(stmt1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_close(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ return OK;
+}
+
struct my_tests_st my_tests[] = {
+ {"test_conc683", test_conc683, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc667", test_conc667, 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},
{"test_conc627", test_conc627, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
diff --git a/libmariadb/unittest/libmariadb/rpl_api.c b/libmariadb/unittest/libmariadb/rpl_api.c
index f65a2915..b502eec8 100644
--- a/libmariadb/unittest/libmariadb/rpl_api.c
+++ b/libmariadb/unittest/libmariadb/rpl_api.c
@@ -72,6 +72,7 @@ static int test_rpl_async(MYSQL *my __attribute__((unused)))
mysql_query(mysql, "SET @mariadb_slave_capability=4");
mysql_query(mysql, "SET NAMES latin1");
mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @master_heartbeat_period=10");
mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
mysql_query(mysql, "SET NAMES utf8");
mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
@@ -85,7 +86,7 @@ static int test_rpl_async(MYSQL *my __attribute__((unused)))
/* We run rpl_api as very last test, too make sure
binary log contains > 10000 events.
*/
- while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000)
+ while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT)
{
events++;
}
@@ -142,6 +143,7 @@ static int test_rpl_semisync(MYSQL *my __attribute__((unused)))
mysql_query(mysql, "SET NAMES latin1");
mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET @master_heartbeat_period=10");
mysql_query(mysql, "SET NAMES utf8");
mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
rpl->server_id= 12;
@@ -161,10 +163,7 @@ static int test_rpl_semisync(MYSQL *my __attribute__((unused)))
if (mariadb_rpl_open(rpl))
return FAIL;
- /* We run rpl_api as very last test, too make sure
- binary log contains > 10000 events.
- */
- while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000)
+ while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT)
{
events++;
}
@@ -341,7 +340,78 @@ static int test_conc592(MYSQL *my __attribute__((unused)))
return OK;
}
+static int test_conc689(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MARIADB_RPL_EVENT *event= NULL;
+ MARIADB_RPL *rpl;
+ int events= 0, rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@log_bin");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ if (!atoi(row[0]))
+ rc= SKIP;
+ mysql_free_result(result);
+
+ if (rc == SKIP)
+ {
+ diag("binary log disabled -> skip");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rpl = mariadb_rpl_init(mysql);
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @master_heartbeat_period=10");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ if (mariadb_rpl_open(rpl))
+ return FAIL;
+
+ /* We run rpl_api as very last test, too make sure
+ binary log contains > 10000 events.
+ */
+ while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT)
+ {
+ events++;
+ }
+ FAIL_IF(event->event.heartbeat.filename.length == 0, "Invalid filename");
+ mariadb_free_rpl_event(event);
+ mariadb_rpl_close(rpl);
+ mysql_close(mysql);
+ return OK;
+}
+
+
struct my_tests_st my_tests[] = {
+ {"test_conc689", test_conc689, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_conc592", test_conc592, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_rpl_async", test_rpl_async, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_rpl_semisync", test_rpl_semisync, TEST_CONNECTION_NEW, 0, NULL, NULL},