diff --git a/.gitmodules b/.gitmodules index e04c0846..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "external/crypto_wrapper"] - path = external/crypto_wrapper - url = https://github.com/9EOR9/crypto_wrapper diff --git a/CMakeLists.txt b/CMakeLists.txt index 27346ba2..69036045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,8 +50,6 @@ MACRO(ADD_OPTION _name _text _default) ENDIF() ENDMACRO() -ADD_OPTION(WITH_CRYPTO "build with cryptograpy support" OFF) - ### Options ### IF(NOT WIN32) ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF) @@ -316,9 +314,6 @@ IF(NOT WITH_SSL STREQUAL "OFF") IF(WIN32) CHECK_INCLUDE_FILES (${OPENSSL_INCLUDE_DIR}/openssl/applink.c HAVE_OPENSSL_APPLINK_C) ENDIF() - IF(WITH_CRYPTO) - SET(WITH_CRYPTO=openssl) - ENDIF() INCLUDE_DIRECTORIES(BEFORE ${OPENSSL_INCLUDE_DIR}) @@ -345,9 +340,6 @@ IF(NOT WITH_SSL STREQUAL "OFF") SET(SSL_LIBRARIES ${GNUTLS_LIBRARY}) SET(TLS_LIBRARY_VERSION "GnuTLS ${GNUTLS_VERSION_STRING}") INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR}) - IF(WITH_CRYPTO) - SET(WITH_CRYPTO=nettle) - ENDIF() ELSE() MESSAGE(FATAL_ERROR "GnuTLS not found") ENDIF() @@ -361,9 +353,6 @@ IF(NOT WITH_SSL STREQUAL "OFF") INCLUDE_DIRECTORIES("${CC_SOURCE_DIR}/plugins/pvio/") SET(SSL_LIBRARIES secur32) SET(TLS_LIBRARY_VERSION "Schannel ${CMAKE_SYSTEM_VERSION}") - IF(WITH_CRYPTO) - SET(WITH_CRYPTO=schannel) - ENDIF() ENDIF() ENDIF() MESSAGE1(TLS_LIBRARY_VERSION "TLS library/version: ${TLS_LIBRARY_VERSION}") @@ -371,12 +360,6 @@ IF(NOT WITH_SSL STREQUAL "OFF") MARK_AS_ADVANCED(SSL_SOURCES) ENDIF() -IF(WITH_CRYPTO) - ADD_DEFINITIONS(-DHAVE_CRYPTO=1) - ADD_SUBDIRECTORY(${CC_SOURCE_DIR}/external/crypto_wrapper) - INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/external/crypto_wrapper/include) -ENDIF() - SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)") MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$") diff --git a/external/crypto_wrapper b/external/crypto_wrapper deleted file mode 160000 index 006ee66c..00000000 --- a/external/crypto_wrapper +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 006ee66ca7e41115a0c3042cbdfddb8ee78369f3 diff --git a/include/mariadb_rpl.h b/include/mariadb_rpl.h index 21f3adf4..5da6118e 100644 --- a/include/mariadb_rpl.h +++ b/include/mariadb_rpl.h @@ -22,6 +22,7 @@ extern "C" { #endif #include +#include #define MARIADB_RPL_VERSION 0x0002 #define MARIADB_RPL_REQUIRED_VERSION 0x0002 @@ -211,6 +212,46 @@ enum opt_metadata_field_type ENUM_AND_SET_COLUMN_CHARSET }; +/* QFLAGS2 codes */ +#define OPTION_AUTO_IS_NULL 0x00040000 +#define OPTION_NOT_AUTOCOMMIT 0x00080000 +#define OPTION_NO_FOREIGN_KEY_CHECKS 0x04000000 +#define OPTION_RELAXED_UNIQUE_CHECKS 0x08000000 + +/* SQL modes */ +#define MODE_REAL_AS_FLOAT 0x00000001 +#define MODE_PIPES_AS_CONCAT 0x00000002 +#define MODE_ANSI_QUOTES 0x00000004 +#define MODE_IGNORE_SPACE 0x00000008 +#define MODE_NOT_USED 0x00000010 +#define MODE_ONLY_FULL_GROUP_BY 0x00000020 +#define MODE_NO_UNSIGNED_SUBTRACTION 0x00000040 +#define MODE_NO_DIR_IN_CREATE 0x00000080 +#define MODE_POSTGRESQL 0x00000100 +#define MODE_ORACLE 0x00000200 +#define MODE_MSSQL 0x00000400 +#define MODE_DB2 0x00000800 +#define MODE_MAXDB 0x00001000 +#define MODE_NO_KEY_OPTIONS 0x00002000 +#define MODE_NO_TABLE_OPTIONS 0x00004000 +#define MODE_NO_FIELD_OPTIONS 0x00008000 +#define MODE_MYSQL323 0x00010000 +#define MODE_MYSQL40 0x00020000 +#define MODE_ANSI 0x00040000 +#define MODE_NO_AUTO_VALUE_ON_ZERO 0x00080000 +#define MODE_NO_BACKSLASH_ESCAPES 0x00100000 +#define MODE_STRICT_TRANS_TABLES 0x00200000 +#define MODE_STRICT_ALL_TABLES 0x00400000 +#define MODE_NO_ZERO_IN_DATE 0x00800000 +#define MODE_NO_ZERO_DATE 0x01000000 +#define MODE_INVALID_DATES 0x02000000 +#define MODE_ERROR_FOR_DIVISION_BY_ZERO 0x04000000 +#define MODE_TRADITIONAL 0x08000000 +#define MODE_NO_AUTO_CREATE_USER 0x10000000 +#define MODE_HIGH_NOT_PRECEDENCE 0x20000000 +#define MODE_NO_ENGINE_SUBSTITUTION 0x40000000 +#define MODE_PAD_CHAR_TO_FULL_LENGTH 0x80000000 + /* Log Event flags */ /* used in FOMRAT_DESCRIPTION_EVENT. Indicates if it @@ -287,7 +328,7 @@ typedef struct st_mariadb_rpl { uint8_t artificial_checksun; uint8_t verify_checksum; uint8_t post_header_len[ENUM_END_EVENT]; - FILE *fp; + MA_FILE *fp; uint32_t error_no; char error_msg[MYSQL_ERRMSG_SIZE]; uint8_t uncompress; @@ -296,7 +337,6 @@ typedef struct st_mariadb_rpl { uint8_t extract_values; char nonce[12]; uint8_t encrypted; - char *decryption_key; } MARIADB_RPL; typedef struct st_mariadb_rpl_value { @@ -334,6 +374,10 @@ struct st_mariadb_rpl_query_event { MARIADB_STRING statement; }; +struct st_mariadb_rpl_previous_gtid_event { + MARIADB_CONST_DATA content; +}; + struct st_mariadb_rpl_gtid_list_event { uint32_t gtid_cnt; MARIADB_GTID *gtid; @@ -504,6 +548,7 @@ typedef struct st_mariadb_rpl_event struct st_mariadb_execute_load_query_event execute_load_query; struct st_mariadb_gtid_log_event gtid_log; struct st_mariadb_start_encryption_event start_encryption; + struct st_mariadb_rpl_previous_gtid_event previous_gtid; } event; /* Added in C/C 3.3.0 */ uint8_t is_semi_sync; @@ -612,106 +657,6 @@ mariadb_rpl_extract_rows(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *tm_event, MARIADB_RPL_EVENT *row_event); -/* Returned from get_latest_key_version() */ -#define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0) -#define ENCRYPTION_KEY_NOT_ENCRYPTED (0) - -#define ENCRYPTION_KEY_SYSTEM_DATA 1 -#define ENCRYPTION_KEY_TEMPORARY_DATA 2 - -/* Returned from get_key() */ -#define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100) - -#define ENCRYPTION_FLAG_DECRYPT 0 -#define ENCRYPTION_FLAG_ENCRYPT 1 -#define ENCRYPTION_FLAG_NOPAD 2 - -struct st_mariadb_encryption { - int interface_version; /**< version plugin uses */ - - /********************* KEY MANAGEMENT ***********************************/ - - /** - Function returning latest key version for a given key id. - - @return A version or ENCRYPTION_KEY_VERSION_INVALID to indicate an error. - */ - unsigned int (*get_latest_key_version)(unsigned int key_id); - - /** - Function returning a key for a key version - - @param key_id The requested key id - @param version The requested key version - @param key The key will be stored there. Can be NULL - - in which case no key will be returned - @param key_length in: key buffer size - out: the actual length of the key - - This method can be used to query the key length - the required - buffer size - by passing key==NULL. - - If the buffer size is less than the key length the content of the - key buffer is undefined (the plugin is free to partially fill it with - the key data or leave it untouched). - - @return 0 on success, or - ENCRYPTION_KEY_VERSION_INVALID, ENCRYPTION_KEY_BUFFER_TOO_SMALL - or any other non-zero number for errors - */ - unsigned int (*get_key)(unsigned int key_id, unsigned int version, - unsigned char *key, unsigned int *key_length); - - /********************* ENCRYPTION **************************************/ - /* - The caller uses encryption as follows: - 1. Create the encryption context object of the crypt_ctx_size() bytes. - 2. Initialize it with crypt_ctx_init(). - 3. Repeat crypt_ctx_update() until there are no more data to encrypt. - 4. Write the remaining output bytes and destroy the context object - with crypt_ctx_finish(). - */ - - /** - Returns the size of the encryption context object in bytes - */ - unsigned int (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version); - /** - Initializes the encryption context object. - */ - int (*crypt_ctx_init)(void *ctx, const unsigned char *key, unsigned int klen, - const unsigned char *iv, unsigned int ivlen, int flags, - unsigned int key_id, unsigned int key_version); - /** - Processes (encrypts or decrypts) a chunk of data - - Writes the output to th dst buffer. note that it might write - more bytes that were in the input. or less. or none at all. - */ - int (*crypt_ctx_update)(void *ctx, const unsigned char *src, - unsigned int slen, unsigned char *dst, - unsigned int *dlen); - /** - Writes the remaining output bytes and destroys the encryption context - - crypt_ctx_update might've cached part of the output in the context, - this method will flush these data out. - */ - int (*crypt_ctx_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); - /** - Returns the length of the encrypted data - - It returns the exact length, given only the source length. - Which means, this API only supports encryption algorithms where - the length of the encrypted data only depends on the length of the - input (a.k.a. compression is not supported). - */ - unsigned int (*encrypted_length)(unsigned int slen, unsigned int key_id, - unsigned int key_version); -}; - - - #ifdef __cplusplus } #endif diff --git a/include/mysql.h b/include/mysql.h index 94a651b2..76b16830 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -256,7 +256,8 @@ extern const char *SQLSTATE_UNKNOWN; MARIADB_OPT_SKIP_READ_RESPONSE, MARIADB_OPT_RESTRICTED_AUTH, MARIADB_OPT_RPL_REGISTER_REPLICA, - MARIADB_OPT_STATUS_CALLBACK + MARIADB_OPT_STATUS_CALLBACK, + MARIADB_OPT_SERVER_PLUGINS }; enum mariadb_value { diff --git a/libmariadb/ma_decimal.c b/libmariadb/ma_decimal.c index daf4b797..bb428f99 100644 --- a/libmariadb/ma_decimal.c +++ b/libmariadb/ma_decimal.c @@ -396,7 +396,7 @@ int bin2decimal(const char *from, decimal *to, int precision, int scale) if (intg0x) { int i= dig2bytes[intg0x]; - dec1 x; + dec1 x= 0; switch (i) { case 1: x=myisam_sint1korr(from); break; @@ -431,7 +431,7 @@ int bin2decimal(const char *from, decimal *to, int precision, int scale) if (frac0x) { int i=dig2bytes[frac0x]; - dec1 x; + dec1 x= 0; switch (i) { case 1: x=myisam_sint1korr(from); break; @@ -440,7 +440,7 @@ int bin2decimal(const char *from, decimal *to, int precision, int scale) case 4: x=myisam_sint4korr(from); break; default: DBUG_ASSERT(0); } - *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; + *buf= (x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; buf++; } return error; diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index b4d8ac02..b9b8f56a 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -29,9 +29,6 @@ #include #include #include -#ifdef HAVE_CRYPTO -#include -#endif #ifdef WIN32 @@ -789,17 +786,18 @@ int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl) } else { char *buf[RPL_BINLOG_MAGIC_SIZE]; + MYSQL mysql; if (rpl->fp) - fclose(rpl->fp); + ma_close(rpl->fp); - if (!(rpl->fp= fopen((const char *)rpl->filename, "r"))) + if (!(rpl->fp= ma_open((const char *)rpl->filename, "r", &mysql))) { rpl_set_error(rpl, CR_FILE_NOT_FOUND, 0, rpl->filename, errno); return errno; } - if (fread(buf, 1, RPL_BINLOG_MAGIC_SIZE, rpl->fp) != 4) + if (ma_read(buf, 1, RPL_BINLOG_MAGIC_SIZE, rpl->fp) != 4) { rpl_set_error(rpl, CR_FILE_READ, 0, rpl->filename, errno); return errno; @@ -961,15 +959,14 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN size_t rc; uint32_t len= 0; char *p= buf; - uint32_t start_pos= ftell(rpl->fp); - if (feof(rpl->fp)) + if (ma_feof(rpl->fp)) { return NULL; } memset(buf, 0, EVENT_HEADER_OFS); - if ((rc= fread(buf, 1, EVENT_HEADER_OFS - 1, rpl->fp)) != EVENT_HEADER_OFS - 1) + if ((rc= ma_read(buf, 1, EVENT_HEADER_OFS - 1, rpl->fp)) != EVENT_HEADER_OFS - 1) { rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Can't read event header"); mariadb_free_rpl_event(rpl_event); @@ -987,7 +984,7 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN rpl_event->raw_data_size= len; memcpy(rpl_event->raw_data, buf, EVENT_HEADER_OFS - 1); len-= (EVENT_HEADER_OFS - 1); - rc= fread(rpl_event->raw_data + EVENT_HEADER_OFS - 1, 1, len, rpl->fp); + rc= ma_read(rpl_event->raw_data + EVENT_HEADER_OFS - 1, 1, len, rpl->fp); if (rc != len) { rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Error while reading post header"); @@ -998,38 +995,7 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN /* We don't decrypt yet */ if (rpl->encrypted) { - uchar iv[16]; - int rc; - uint32 event_len= uint4korr(ev + 9); - uint32 dlen= event_len; - uchar *dst; - - #ifndef HAVE_CRYPTO return rpl_event; - #endif - /* Application needs to set key after START_ENCRYPTION_EVENT, if not done - we return the encrypted event */ - if (!rpl->decryption_key) - return rpl_event; - - memcpy(iv, rpl->nonce, 12); - int4store(iv + 12, start_pos); - - /* move timestamp */ - memcpy(ev + 9, ev, 4); - dst= (uchar *)malloc(event_len); - if ((rc= cw_crypt(CW_AES_CTR, CW_CRYPT_DECRYPT, ev + 4, event_len - 4, dst + 4, &dlen, - (uchar*)rpl->decryption_key, strlen(rpl->decryption_key), iv, 16))) - { - rpl_set_error(rpl, CR_BINLOG_ERROR, 0, RPL_ERR_POS(rpl), "Decryption failed"); - free(dst); - return rpl_event; - } - - memcpy(dst, dst + 9, 4); - int4store(dst + 9, event_len); - memcpy(ev, dst, event_len); - free(dst); } } @@ -1553,11 +1519,29 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN */ break; - case ANONYMOUS_GTID_LOG_EVENT: case PREVIOUS_GTIDS_LOG_EVENT: + { + /* + PREVIOUS_GTID_LOG_EVENT (MySQL only): + + 8-bytes, always zero ?! + */ + int len= ev_end - ev - rpl->use_checksum * 4; + + if (len) + { + rpl_event->event.previous_gtid.content.data= ev; + rpl_event->event.previous_gtid.content.length= len; + ev+= len; + } + break; + } + case ANONYMOUS_GTID_LOG_EVENT: + case GTID_LOG_EVENT: /* - ANONYMOUS_GTID_LOG_EVENT, - PREVIOUS_GTIDS_LOG_EVENT (MySQL only) + ANONYMOUS_GTID_LOG_EVENT + + uint32_t thread_id Header: uint8_t flag: commit flag @@ -1861,12 +1845,9 @@ void STDCALL mariadb_rpl_close(MARIADB_RPL *rpl) free((void *)rpl->filename); if (rpl->fp) { - fclose(rpl->fp); + ma_close(rpl->fp); } free(rpl->host); -#ifdef HAVE_CRYPTO - free(rpl->decryption_key); -#endif free(rpl); return; } @@ -1942,13 +1923,6 @@ int mariadb_rpl_optionsv(MARIADB_RPL *rpl, rpl->extract_values= (uint8_t)va_arg(ap, uint32_t); break; } -#ifdef HAVE_CRYPTO - case MARIADB_RPL_DECRYPTION_KEY: - { - rpl->decryption_key=strdup(va_arg(ap, char *)); - break; - } -#endif default: rc= -1; goto end; diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index e9f4fdb4..ccee5292 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -49,6 +49,7 @@ static int test_conc66(MYSQL *my) fprintf(fp, "user=conc66\n"); fprintf(fp, "port=3306\n"); fprintf(fp, "enable-local-infile\n"); + fprintf(fp, "server_plugin=file_key_management:file_key_management_algorithm=AES_CTR;file_key_management_key=secret\n"); fprintf(fp, "password='test@A1\\\";#test'\n"); fclose(fp); @@ -2256,6 +2257,7 @@ static int test_status_callback(MYSQL *my __attribute__((unused))) } struct my_tests_st my_tests[] = { + {"test_conc66", test_conc66, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_status_callback", test_status_callback, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc365", test_conc365, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc365_reconnect", test_conc365_reconnect, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, @@ -2288,7 +2290,6 @@ struct my_tests_st my_tests[] = { {"test_wrong_bind_address", test_wrong_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bind_address", test_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc118", test_conc118, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, - {"test_conc66", test_conc66, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bug20023", test_bug20023, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_bug31669", test_bug31669, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_bug33831", test_bug33831, TEST_CONNECTION_NEW, 0, NULL, NULL},