diff options
author | Ravinder Thakur <ravinder.thakur@oracle.com> | 2012-12-13 20:58:09 +0530 |
---|---|---|
committer | Ravinder Thakur <ravinder.thakur@oracle.com> | 2012-12-13 20:58:09 +0530 |
commit | e604bb8a0300c5b84650d90a01da7088ad7794c5 (patch) | |
tree | f81464d5ff0181e73ed47972b92ea2590323f1c7 | |
parent | c85f51f92ab5c28baad9d2ff72dcf9778f9bea4b (diff) | |
parent | 2d16c5bd4b6a0fb9f3cd325d0ae8c3805c1ac62c (diff) | |
download | mariadb-git-e604bb8a0300c5b84650d90a01da7088ad7794c5.tar.gz |
Merging from 5.1 to 5.5 for bug#11761752
-rw-r--r-- | include/my_sys.h | 1 | ||||
-rw-r--r-- | mysys/my_access.c | 64 | ||||
-rw-r--r-- | sql/sys_vars.cc | 8 |
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))) |