You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +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:
@@ -334,6 +334,16 @@ IF(NOT WITH_SSL STREQUAL "OFF")
|
||||
MARK_AS_ADVANCED(SSL_SOURCES)
|
||||
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)
|
||||
INCLUDE(${CC_SOURCE_DIR}/cmake/FindIconv.cmake)
|
||||
ENDIF()
|
||||
|
@@ -31,6 +31,13 @@ enum enum_multi_status {
|
||||
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
|
||||
{
|
||||
struct st_mariadb_client_plugin_DB *plugin;
|
||||
@@ -71,6 +78,7 @@ struct st_mysql_options_extension {
|
||||
char *server_public_key;
|
||||
char *proxy_header;
|
||||
size_t proxy_header_len;
|
||||
my_bool auto_local_infile;
|
||||
};
|
||||
|
||||
typedef struct st_connection_handler
|
||||
|
@@ -131,5 +131,10 @@
|
||||
|
||||
#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@"
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
|
||||
${CC_SOURCE_DIR}/libmariadb)
|
||||
|
||||
ADD_DEFINITIONS(-D ENABLED_LOCAL_INFILE)
|
||||
ADD_DEFINITIONS(-D HAVE_COMPRESS)
|
||||
ADD_DEFINITIONS(-D LIBMARIADB)
|
||||
ADD_DEFINITIONS(-D THREAD)
|
||||
|
@@ -50,6 +50,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <share.h>
|
||||
#endif
|
||||
#include <ma_common.h>
|
||||
|
||||
typedef struct st_mysql_infile_info
|
||||
{
|
||||
@@ -183,7 +184,7 @@ void STDCALL mysql_set_local_infile_handler(MYSQL *conn,
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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;
|
||||
int bufread;
|
||||
@@ -199,7 +200,9 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename)
|
||||
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");
|
||||
/* write empty packet to server */
|
||||
ma_net_write(&conn->net, (unsigned char *)"", 0);
|
||||
|
@@ -87,7 +87,7 @@ extern void release_configuration_dirs();
|
||||
extern char **get_default_configuration_dirs();
|
||||
extern my_bool ma_init_done;
|
||||
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_name(const char * const name);
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1009,6 +1017,8 @@ mysql_init(MYSQL *mysql)
|
||||
*/
|
||||
#ifdef ENABLED_LOCAL_INFILE
|
||||
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
|
||||
mysql->options.reconnect= 0;
|
||||
return mysql;
|
||||
@@ -2113,6 +2123,10 @@ int mthd_my_read_query_result(MYSQL *mysql)
|
||||
ulong field_count;
|
||||
MYSQL_DATA *fields;
|
||||
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)
|
||||
{
|
||||
@@ -2125,7 +2139,7 @@ get_info:
|
||||
return ma_read_ok_packet(mysql, pos, length);
|
||||
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)
|
||||
return(-1);
|
||||
@@ -2669,6 +2683,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
||||
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
|
||||
else
|
||||
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;
|
||||
case MYSQL_INIT_COMMAND:
|
||||
options_add_initcommand(&mysql->options, (char *)arg1);
|
||||
|
Reference in New Issue
Block a user