diff options
author | unknown <monty@tik.mysql.fi> | 2002-02-13 21:53:26 +0200 |
---|---|---|
committer | unknown <monty@tik.mysql.fi> | 2002-02-13 21:53:26 +0200 |
commit | 33d2d76549f8ccf037f733c61e2b9c17500fe738 (patch) | |
tree | d9a4ab04b8347c3969351b9c33b0c3f55c2f0145 | |
parent | 501650c5b16a4c7cf7b673b19f9a2ae9c319e24f (diff) | |
download | mariadb-git-33d2d76549f8ccf037f733c61e2b9c17500fe738.tar.gz |
Made LOAD DATA LOCAL INFILE more secure
Docs/manual.texi:
Changelog
sql/sql_yacc.yy:
optimization
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | Docs/manual.texi | 6 | ||||
-rw-r--r-- | acconfig.h | 3 | ||||
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysql.cc | 13 | ||||
-rw-r--r-- | configure.in | 12 | ||||
-rw-r--r-- | include/mysql.h | 3 | ||||
-rw-r--r-- | libmysql/libmysql.c | 44 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 7 | ||||
-rw-r--r-- | sql/sql_load.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 16 |
13 files changed, 93 insertions, 27 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index e9dc3e56d39..19a311081c8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,3 +9,4 @@ miguel@light.local monty@donna.mysql.fi monty@bitch.mysql.fi mwagner@cash.mwagner.org +monty@tik.mysql.fi diff --git a/Docs/manual.texi b/Docs/manual.texi index a705340fe86..eb727cef882 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46892,6 +46892,12 @@ not yet 100% confident in this code. @item Fixed unlikely caching bug when doing a join without keys. In this case the last used field for a table always returned @code{NULL}. +@item +Added options to make @code{LOAD DATA LOCAL INFILE} more secure. +@item +MySQL binary release 3.23.48 for Linux contained a new glibc library, which +has serious problems under high load and RedHat 7.2. The 3.23.49 binary +release doesn't have this problem. @end itemize @node News-3.23.48, News-3.23.47, News-3.23.49, News-3.23.x diff --git a/acconfig.h b/acconfig.h index be4461da7fd..3cea5bf4b73 100644 --- a/acconfig.h +++ b/acconfig.h @@ -21,6 +21,9 @@ /* Version of .frm files */ #undef DOT_FRM_VERSION +/* If LOAD DATA LOCAL INFILE should be enabled by default */ +#undef ENABLED_LOCAL_INFILE + /* READLINE: */ #undef FIONREAD_IN_SYS_IOCTL diff --git a/client/client_priv.h b/client/client_priv.h index 261367f7176..56eaf311070 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -30,4 +30,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS, OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE, OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES, - OPT_MASTER_DATA, OPT_AUTOCOMMIT}; + OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_LOCAL_INFILE}; diff --git a/client/mysql.cc b/client/mysql.cc index 5ae8df39863..cfe6d823cac 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -34,7 +34,7 @@ #include "my_readline.h" #include <signal.h> -const char *VER="11.15"; +const char *VER="11.16"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -113,10 +113,10 @@ static MYSQL mysql; /* The connection */ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, connected=0,opt_raw_data=0,unbuffered=0,output_tables=0, no_rehash=0,skip_updates=0,safe_updates=0,one_database=0, - opt_compress=0, + opt_compress=0, using_opt_local_infile=0, vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0, opt_nopager=1, opt_outfile=0, no_named_cmds=1; -static uint verbose=0,opt_silent=0,opt_mysql_port=0; +static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static my_string opt_mysql_unix_port=0; static int connect_flag=CLIENT_INTERACTIVE; static char *current_host,*current_db,*current_user=0,*opt_password=0, @@ -394,6 +394,7 @@ static struct option long_options[] = {"html", no_argument, 0, 'H'}, {"host", required_argument, 0, 'h'}, {"ignore-spaces", no_argument, 0, 'i'}, + {"local-infile", optional_argument, 0, OPT_LOCAL_INFILE}, {"no-auto-rehash",no_argument, 0, 'A'}, {"no-named-commands", no_argument, 0, 'g'}, {"no-tee", no_argument, 0, OPT_NOTEE}, @@ -693,6 +694,10 @@ static int get_options(int argc, char **argv) case 'C': opt_compress=1; break; + case OPT_LOCAL_INFILE: + using_opt_local_infile=1; + opt_local_infile= test(!optarg || atoi(optarg)>0); + break; case 'L': skip_line_numbers=1; break; @@ -2105,6 +2110,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, } if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); + if (using_opt_local_infile) + mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile); #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, diff --git a/configure.in b/configure.in index 33d6443275d..f11e2354dfd 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 3.23.48) +AM_INIT_AUTOMAKE(mysql, 3.23.49) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -518,7 +518,7 @@ AC_ARG_ENABLE(thread-safe-client, [ THREAD_SAFE_CLIENT=no ] ) -# Make thread safe client +# compile with strings functions in assembler AC_ARG_ENABLE(assembler, [ --enable-assembler Use assembler versions of some string functions if available.], @@ -583,6 +583,14 @@ AC_ARG_WITH(mysqld-user, ) AC_SUBST(MYSQLD_USER) +# compile with strings functions in assembler +AC_ARG_ENABLE(local-infile, + [ --enable-local-infile + If LOAD DATA LOCAL INFILE is enabled by default.], + [ ENABLED_LOCAL_INFILE=$enablewal ], + [ ENABLED_LOCAL_INFILE=no ] + ) + # Use Paul Eggerts macros from GNU tar to check for large file support. MYSQL_SYS_LARGEFILE diff --git a/include/mysql.h b/include/mysql.h index bd54be0bc22..0bd5b7092b8 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -143,7 +143,8 @@ struct st_mysql_options { enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, - MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME}; + MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, + MYSQL_OPT_LOCAL_INFILE}; enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT, MYSQL_STATUS_USE_RESULT}; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8a73f694e41..b632595bad9 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -61,7 +61,7 @@ static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS) +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS) #ifdef __WIN__ #define CONNECT_TIMEOUT 20 @@ -671,11 +671,12 @@ mysql_free_result(MYSQL_RES *result) ****************************************************************************/ static const char *default_options[]= -{"port","socket","compress","password","pipe", "timeout", "user", - "init-command", "host", "database", "debug", "return-found-rows", - "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", - "character-set-dir", "default-character-set", "interactive-timeout", - "connect_timeout", +{ + "port","socket","compress","password","pipe", "timeout", "user", + "init-command", "host", "database", "debug", "return-found-rows", + "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", + "character-set-dir", "default-character-set", "interactive-timeout", + "connect-timeout", "local-infile", "disable-local-infile", NullS }; @@ -710,6 +711,9 @@ static void mysql_read_default_options(struct st_mysql_options *options, opt_arg=end+1; *end=0; /* Remove '=' */ } + /* Change all '_' in variable name to '-' */ + for (end= *option ; (end= strcend(end,'_')) ; ) + *end= '-'; switch (find_type(*option+2,&option_types,2)) { case 1: /* port */ if (opt_arg) @@ -807,7 +811,16 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); break; case 19: /* Interactive-timeout */ - options->client_flag|=CLIENT_INTERACTIVE; + options->client_flag|= CLIENT_INTERACTIVE; + break; + case 21: + if (!opt_arg || atoi(opt_arg) != 0) + options->client_flag|= CLIENT_LOCAL_FILES; + else + options->client_flag&= ~CLIENT_LOCAL_FILES; + break; + case 22: + options->client_flag&= CLIENT_LOCAL_FILES; break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); @@ -1006,6 +1019,14 @@ mysql_init(MYSQL *mysql) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) (void) signal(SIGPIPE,pipe_sig_handler); #endif + +/* + Only enable LOAD DATA INFILE by default if configured with + --with-enabled-local-inflile +*/ +#ifdef ENABLED_LOCAL_INFILE + mysql->options.client_flag|= CLIENT_LOCAL_FILES; +#endif return mysql; } @@ -1453,7 +1474,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->options.use_ssl) client_flag|=CLIENT_SSL; #endif /* HAVE_OPENSSL */ - if (db) client_flag|=CLIENT_CONNECT_WITH_DB; #ifdef HAVE_COMPRESS @@ -2267,11 +2287,17 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) mysql->options.connect_timeout= *(uint*) arg; break; case MYSQL_OPT_COMPRESS: - mysql->options.compress=1; /* Remember for connect */ + mysql->options.compress= 1; /* Remember for connect */ break; case MYSQL_OPT_NAMED_PIPE: mysql->options.named_pipe=1; /* Force named pipe */ break; + case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ + if (!arg || test(*(uint*) arg)) + mysql->client_flag|= CLIENT_LOCAL_FILES; + else + mysql->client_flag&= ~CLIENT_LOCAL_FILES; + break; case MYSQL_INIT_COMMAND: my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.init_command=my_strdup(arg,MYF(MY_WME)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a569fecfc9d..072cbf540af 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -524,7 +524,7 @@ extern pthread_cond_t COND_refresh,COND_thread_count, COND_binlog_update, COND_slave_stopped, COND_slave_start; extern pthread_attr_t connection_attrib; extern bool opt_endinfo, using_udf_functions, locked_in_memory, - opt_using_transactions, use_temp_pool; + opt_using_transactions, use_temp_pool, opt_local_infile; extern char f_fyllchar; extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count, ha_read_key_count, ha_read_next_count, ha_read_prev_count, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a7c59dc3c7f..72a8f74ee38 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -287,6 +287,7 @@ ulong bytes_sent = 0L, bytes_received = 0L; bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory; bool opt_using_transactions, using_update_log, opt_warnings=0; +bool opt_local_infile; bool volatile abort_loop,select_thread_in_use,grant_option; bool volatile ready_to_exit,shutdown_in_progress; ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */ @@ -2612,7 +2613,7 @@ enum options { OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS, OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL, OPT_SAFE_USER_CREATE, OPT_SQL_MODE, - OPT_SLAVE_SKIP_ERRORS + OPT_SLAVE_SKIP_ERRORS, OPT_LOCAL_INFILE }; static struct option long_options[] = { @@ -2676,6 +2677,7 @@ static struct option long_options[] = { {"init-file", required_argument, 0, (int) OPT_INIT_FILE}, {"log", optional_argument, 0, 'l'}, {"language", required_argument, 0, 'L'}, + {"local-infile", optional_argument, 0, (int) OPT_LOCAL_INFILE}, {"log-bin", optional_argument, 0, (int) OPT_BIN_LOG}, {"log-bin-index", required_argument, 0, (int) OPT_BIN_LOG_INDEX}, {"log-isam", optional_argument, 0, (int) OPT_ISAM_LOG}, @@ -3468,6 +3470,9 @@ static void get_options(int argc,char **argv) case 'P': mysql_port= (unsigned int) atoi(optarg); break; + case OPT_LOCAL_INFILE: + opt_local_infile= test(optarg || atoi(optarg) != 0); + break; case OPT_SLAVE_SKIP_ERRORS: init_slave_skip_errors(optarg); break; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 9d3b899d31b..dd8487ceecc 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -132,7 +132,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (read_file_from_client && handle_duplicates == DUP_ERROR) handle_duplicates=DUP_IGNORE; - if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES)) + if (read_file_from_client) { char tmp [FN_REFLEN+1],*end; DBUG_PRINT("info",("reading local file")); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 48b48dc77a7..9b439081d50 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1796,13 +1796,20 @@ mysql_execute_command(void) { uint privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL); - if (!(lex->local_file && (thd->client_capabilities & CLIENT_LOCAL_FILES))) + + if (!lex->local_file) { if (check_access(thd,privilege | FILE_ACL,tables->db)) goto error; } else { + if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) || + ! opt_local_infile) + { + send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); + goto error; + } if (check_access(thd,privilege,tables->db,&tables->grant.privilege) || grant_option && check_grant(thd,privilege,tables)) goto error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 42872399dec..08fab22629a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2356,8 +2356,9 @@ use: USE_SYM ident load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING { - Lex->sql_command= SQLCOM_LOAD; - Lex->local_file= $4; + LEX *lex= Lex; + lex->sql_command= SQLCOM_LOAD; + lex->local_file= $4; if (!(Lex->exchange= new sql_exchange($6.str,0))) YYABORT; Lex->field_list.empty(); @@ -2643,11 +2644,12 @@ set: SET opt_option { THD *thd=current_thd; - Lex->sql_command= SQLCOM_SET_OPTION; - Lex->options=thd->options; - Lex->select_limit=thd->default_select_limit; - Lex->gemini_spin_retries=thd->gemini_spin_retries; - Lex->tx_isolation=thd->tx_isolation; + LEX *lex= &thd->lex; + lex->sql_command= SQLCOM_SET_OPTION; + lex->options=thd->options; + lex->select_limit=thd->default_select_limit; + lex->gemini_spin_retries=thd->gemini_spin_retries; + lex->tx_isolation=thd->tx_isolation; } option_value_list |