summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavinder Thakur <ravinder.thakur@oracle.com>2012-12-13 20:58:09 +0530
committerRavinder Thakur <ravinder.thakur@oracle.com>2012-12-13 20:58:09 +0530
commite604bb8a0300c5b84650d90a01da7088ad7794c5 (patch)
treef81464d5ff0181e73ed47972b92ea2590323f1c7
parentc85f51f92ab5c28baad9d2ff72dcf9778f9bea4b (diff)
parent2d16c5bd4b6a0fb9f3cd325d0ae8c3805c1ac62c (diff)
downloadmariadb-git-e604bb8a0300c5b84650d90a01da7088ad7794c5.tar.gz
Merging from 5.1 to 5.5 for bug#11761752
-rw-r--r--include/my_sys.h1
-rw-r--r--mysys/my_access.c64
-rw-r--r--sql/sys_vars.cc8
3 files changed, 73 insertions, 0 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index e13ef1af067..a1d6d4cadf2 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -604,6 +604,7 @@ extern int my_access(const char *path, int amode);
extern int check_if_legal_filename(const char *path);
extern int check_if_legal_tablename(const char *path);
+extern my_bool is_filename_allowed(const char *name, size_t length);
#ifdef _WIN32
extern int nt_share_delete(const char *name,myf MyFlags);
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 43917da7f98..a2925f99655 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -156,6 +156,67 @@ int check_if_legal_tablename(const char *name)
}
+#ifdef __WIN__
+/**
+ Checks if the drive letter supplied is valid or not. Valid drive
+ letters are A to Z, both lower case and upper case.
+
+ @param drive_letter : The drive letter to validate.
+
+ @return TRUE if the drive exists, FALSE otherwise.
+*/
+static my_bool does_drive_exists(char drive_letter)
+{
+ DWORD drive_mask= GetLogicalDrives();
+ drive_letter= toupper(drive_letter);
+
+ return (drive_letter >= 'A' && drive_letter <= 'Z') &&
+ (drive_mask & (0x1 << (drive_letter - 'A')));
+}
+#endif
+
+/**
+ Verifies if the file name supplied is allowed or not. On Windows
+ file names with a colon (:) are not allowed because such file names
+ store data in Alternate Data Streams which can be used to hide
+ the data.
+
+ @param name contains the file name with or without path
+ @param length contains the length of file name
+
+ @return TRUE if the file name is allowed, FALSE otherwise.
+*/
+my_bool is_filename_allowed(const char *name __attribute__((unused)),
+ size_t length __attribute__((unused)))
+{
+#ifdef __WIN__
+ /*
+ For Windows, check if the file name contains : character.
+ Start from end of path and search if the file name contains :
+ */
+ const char* ch = NULL;
+ for(ch= name + length - 1; ch >= name; --ch)
+ {
+ if (FN_LIBCHAR == *ch || '/' == *ch)
+ break;
+ else if (':' == *ch)
+ {
+ /*
+ File names like C:foobar.txt are allowed since the syntax means
+ file foobar.txt in current directory of C drive. However file
+ names likes CC:foobar are not allowed since this syntax means ADS
+ foobar in file CC.
+ */
+ return ((ch - name == 1) && does_drive_exists(*name));
+ }
+ }
+ return TRUE;
+#else
+ /* For other platforms, file names can contain colon : */
+ return TRUE;
+#endif
+} /* is_filename_allowed */
+
#if defined(__WIN__) || defined(__EMX__)
@@ -177,6 +238,9 @@ int check_if_legal_filename(const char *path)
const char **reserved_name;
DBUG_ENTER("check_if_legal_filename");
+ if(!is_filename_allowed(path, strlen(path)))
+ DBUG_RETURN(1);
+
path+= dirname_length(path); /* To start of filename */
if (!(end= strchr(path, FN_EXTCHAR)))
end= strend(path);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 5a0d2709a52..9e79cdcb6f3 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2812,6 +2812,14 @@ static bool check_log_path(sys_var *self, THD *thd, set_var *var)
if (!path_length)
return true;
+ if (!is_filename_allowed(var->save_result.string_value.str,
+ var->save_result.string_value.length))
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ self->name.str, var->save_result.string_value.str);
+ return true;
+ }
+
MY_STAT f_stat;
if (my_stat(path, &f_stat, MYF(0)))