summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@tik.mysql.fi>2002-02-13 21:53:26 +0200
committerunknown <monty@tik.mysql.fi>2002-02-13 21:53:26 +0200
commit33d2d76549f8ccf037f733c61e2b9c17500fe738 (patch)
treed9a4ab04b8347c3969351b9c33b0c3f55c2f0145
parent501650c5b16a4c7cf7b673b19f9a2ae9c319e24f (diff)
downloadmariadb-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_ok1
-rw-r--r--Docs/manual.texi6
-rw-r--r--acconfig.h3
-rw-r--r--client/client_priv.h2
-rw-r--r--client/mysql.cc13
-rw-r--r--configure.in12
-rw-r--r--include/mysql.h3
-rw-r--r--libmysql/libmysql.c44
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc7
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc9
-rw-r--r--sql/sql_yacc.yy16
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