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

Crude "auto-load-data-local-infile" mode

Disable LOAD DATA LOCAL INFILE suport by default and
auto-enable it for the duration of one query, if the query
string starts with the word "load". In all other cases the application
should enable LOAD DATA LOCAL INFILE support explicitly.

(Based on Sergei Golubchiks 5.5 server patch)
This commit is contained in:
Georg Richter
2019-02-05 07:19:36 +01:00
parent 2e3c152c59
commit 02e7d5654d
6 changed files with 47 additions and 5 deletions

View File

@@ -334,6 +334,16 @@ IF(NOT WITH_SSL STREQUAL "OFF")
MARK_AS_ADVANCED(SSL_SOURCES) MARK_AS_ADVANCED(SSL_SOURCES)
ENDIF() 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)$")
SET(ENABLED_LOCAL_INFILE OFF)
ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$")
SET(ENABLED_LOCAL_INFILE ON)
ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$")
MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO")
ENDIF()
IF(NOT WIN32) IF(NOT WIN32)
INCLUDE(${CC_SOURCE_DIR}/cmake/FindIconv.cmake) INCLUDE(${CC_SOURCE_DIR}/cmake/FindIconv.cmake)
ENDIF() ENDIF()

View File

@@ -31,6 +31,13 @@ enum enum_multi_status {
COM_MULTI_END COM_MULTI_END
}; };
typedef enum {
ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */
WAIT_FOR_QUERY, /* heuristics is enabled, not sending files */
ACCEPT_FILE_REQUEST /* heuristics is enabled, ready to send a file */
} auto_local_infile_state;
typedef struct st_mariadb_db_driver typedef struct st_mariadb_db_driver
{ {
struct st_mariadb_client_plugin_DB *plugin; struct st_mariadb_client_plugin_DB *plugin;
@@ -71,6 +78,7 @@ struct st_mysql_options_extension {
char *server_public_key; char *server_public_key;
char *proxy_header; char *proxy_header;
size_t proxy_header_len; size_t proxy_header_len;
my_bool auto_local_infile;
}; };
typedef struct st_connection_handler typedef struct st_connection_handler

View File

@@ -131,5 +131,10 @@
#cmakedefine SOCKET_SIZE_TYPE @SOCKET_SIZE_TYPE@ #cmakedefine SOCKET_SIZE_TYPE @SOCKET_SIZE_TYPE@
#define LOCAL_INFILE_MODE_OFF 0
#define LOCAL_INFILE_MODE_ON 1
#define LOCAL_INFILE_MODE_AUTO 2
#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_@ENABLED_LOCAL_INFILE@
#define MARIADB_DEFAULT_CHARSET "@DEFAULT_CHARSET@" #define MARIADB_DEFAULT_CHARSET "@DEFAULT_CHARSET@"

View File

@@ -1,7 +1,6 @@
INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
${CC_SOURCE_DIR}/libmariadb) ${CC_SOURCE_DIR}/libmariadb)
ADD_DEFINITIONS(-D ENABLED_LOCAL_INFILE)
ADD_DEFINITIONS(-D HAVE_COMPRESS) ADD_DEFINITIONS(-D HAVE_COMPRESS)
ADD_DEFINITIONS(-D LIBMARIADB) ADD_DEFINITIONS(-D LIBMARIADB)
ADD_DEFINITIONS(-D THREAD) ADD_DEFINITIONS(-D THREAD)

View File

@@ -50,6 +50,7 @@
#ifdef _WIN32 #ifdef _WIN32
#include <share.h> #include <share.h>
#endif #endif
#include <ma_common.h>
typedef struct st_mysql_infile_info typedef struct st_mysql_infile_info
{ {
@@ -183,7 +184,7 @@ void STDCALL mysql_set_local_infile_handler(MYSQL *conn,
/* }}} */ /* }}} */
/* {{{ mysql_handle_local_infile */ /* {{{ mysql_handle_local_infile */
my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename) my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can_local_infile)
{ {
unsigned int buflen= 4096; unsigned int buflen= 4096;
int bufread; int bufread;
@@ -199,7 +200,9 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename)
mysql_set_local_infile_default(conn); mysql_set_local_infile_default(conn);
} }
if (!(conn->options.client_flag & CLIENT_LOCAL_FILES)) { if (!(conn->options.client_flag & CLIENT_LOCAL_FILES) ||
!can_local_infile)
{
my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden"); my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden");
/* write empty packet to server */ /* write empty packet to server */
ma_net_write(&conn->net, (unsigned char *)"", 0); ma_net_write(&conn->net, (unsigned char *)"", 0);

View File

@@ -87,7 +87,7 @@ extern void release_configuration_dirs();
extern char **get_default_configuration_dirs(); extern char **get_default_configuration_dirs();
extern my_bool ma_init_done; extern my_bool ma_init_done;
extern my_bool mysql_ps_subsystem_initialized; extern my_bool mysql_ps_subsystem_initialized;
extern my_bool mysql_handle_local_infile(MYSQL *mysql, const char *filename); extern my_bool mysql_handle_local_infile(MYSQL *mysql, const char *filename, my_bool can_local_infile);
extern const MARIADB_CHARSET_INFO * mysql_find_charset_nr(uint charsetnr); extern const MARIADB_CHARSET_INFO * mysql_find_charset_nr(uint charsetnr);
extern const MARIADB_CHARSET_INFO * mysql_find_charset_name(const char * const name); extern const MARIADB_CHARSET_INFO * mysql_find_charset_name(const char * const name);
extern my_bool set_default_charset_by_name(const char *cs_name, myf flags __attribute__((unused))); extern my_bool set_default_charset_by_name(const char *cs_name, myf flags __attribute__((unused)));
@@ -428,6 +428,14 @@ int
ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg) size_t length, my_bool skipp_check, void *opt_arg)
{ {
if ((mysql->options.client_flag & CLIENT_LOCAL_FILES) &&
mysql->options.extension && mysql->options.extension->auto_local_infile == WAIT_FOR_QUERY &&
arg && (*arg == 'l' || *arg == 'L') &&
command == COM_QUERY)
{
if (strncasecmp(arg, "load", 4) == 0)
mysql->options.extension->auto_local_infile= ACCEPT_FILE_REQUEST;
}
return mysql->methods->db_command(mysql, command, arg, length, skipp_check, opt_arg); return mysql->methods->db_command(mysql, command, arg, length, skipp_check, opt_arg);
} }
@@ -1009,6 +1017,8 @@ mysql_init(MYSQL *mysql)
*/ */
#ifdef ENABLED_LOCAL_INFILE #ifdef ENABLED_LOCAL_INFILE
mysql->options.client_flag|= CLIENT_LOCAL_FILES; mysql->options.client_flag|= CLIENT_LOCAL_FILES;
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, auto_local_infile, ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO
? WAIT_FOR_QUERY : ALWAYS_ACCEPT);
#endif #endif
mysql->options.reconnect= 0; mysql->options.reconnect= 0;
return mysql; return mysql;
@@ -2113,6 +2123,10 @@ int mthd_my_read_query_result(MYSQL *mysql)
ulong field_count; ulong field_count;
MYSQL_DATA *fields; MYSQL_DATA *fields;
ulong length; ulong length;
my_bool can_local_infile= (mysql->options.extension) && (mysql->options.extension->auto_local_infile != WAIT_FOR_QUERY);
if (mysql->options.extension && mysql->options.extension->auto_local_infile == ACCEPT_FILE_REQUEST)
mysql->options.extension->auto_local_infile= WAIT_FOR_QUERY;
if (!mysql || (length = ma_net_safe_read(mysql)) == packet_error) if (!mysql || (length = ma_net_safe_read(mysql)) == packet_error)
{ {
@@ -2125,7 +2139,7 @@ get_info:
return ma_read_ok_packet(mysql, pos, length); return ma_read_ok_packet(mysql, pos, length);
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
{ {
int error=mysql_handle_local_infile(mysql, (char *)pos); int error=mysql_handle_local_infile(mysql, (char *)pos, can_local_infile);
if ((length=ma_net_safe_read(mysql)) == packet_error || error) if ((length=ma_net_safe_read(mysql)) == packet_error || error)
return(-1); return(-1);
@@ -2669,6 +2683,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.client_flag|= CLIENT_LOCAL_FILES; mysql->options.client_flag|= CLIENT_LOCAL_FILES;
else else
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
if (arg1)
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, auto_local_infile, *(uint*)arg1 == LOCAL_INFILE_MODE_AUTO
? WAIT_FOR_QUERY : ALWAYS_ACCEPT);
break; break;
case MYSQL_INIT_COMMAND: case MYSQL_INIT_COMMAND:
options_add_initcommand(&mysql->options, (char *)arg1); options_add_initcommand(&mysql->options, (char *)arg1);