mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Now external tables are checked against directories list
This commit is contained in:
parent
65f00fcac9
commit
70c9d082ba
@ -212,7 +212,7 @@ FBCLASSES_Objects = $(addprefix $(OBJ)/, $(addsuffix .o, $(basename $(FBCLASSES_
|
||||
#
|
||||
# common/config
|
||||
|
||||
FBCONFIG_ClientFiles=config.cpp config_file.cpp
|
||||
FBCONFIG_ClientFiles=config.cpp config_file.cpp dir_list.cpp
|
||||
FBCONFIG_ServerFiles=
|
||||
|
||||
FBCONFIG_Files= $(FBCONFIG_ClientFiles) $(FBCONFIG_ServerFiles)
|
||||
|
@ -115,6 +115,10 @@ SOURCE=..\..\..\src\common\config\config_file.cpp
|
||||
|
||||
SOURCE=..\..\..\src\jrd\os\win32\config_root.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\common\config\dir_list.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "OTHER files"
|
||||
|
||||
@ -151,6 +155,10 @@ SOURCE=..\..\..\src\common\config\config_impl.h
|
||||
|
||||
SOURCE=..\..\..\src\jrd\os\config_root.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\common\config\dir_list.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
@ -115,6 +115,10 @@ SOURCE=..\..\..\src\common\config\config_file.cpp
|
||||
|
||||
SOURCE=..\..\..\src\jrd\os\win32\config_root.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\common\config\dir_list.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "OTHER files"
|
||||
|
||||
@ -151,6 +155,10 @@ SOURCE=..\..\..\src\common\config\config_impl.h
|
||||
|
||||
SOURCE=..\..\..\src\jrd\os\config_root.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\common\config\dir_list.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
182
src/common/config/dir_list.cpp
Normal file
182
src/common/config/dir_list.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* PROGRAM: Client/Server Common Code
|
||||
* MODULE: dir_list.cpp
|
||||
* DESCRIPTION: Directory listing config file operation
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* Created by: Alex Peshkov <AlexPeshkov@users.sourceforge.net>
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "Firebird.h"
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
#include "../jrd/os/path_utils.h"
|
||||
|
||||
#define New FB_NEW(*getDefaultMemoryPool())
|
||||
|
||||
ParsedPath::ParsedPath(void) {
|
||||
PathElem = 0;
|
||||
nElem = 0;
|
||||
}
|
||||
|
||||
ParsedPath::ParsedPath(const Firebird::string & path) {
|
||||
PathElem = 0;
|
||||
Parse(path);
|
||||
}
|
||||
|
||||
ParsedPath::~ParsedPath() {
|
||||
delete[] PathElem;
|
||||
}
|
||||
|
||||
void ParsedPath::Parse(const Firebird::string &path) {
|
||||
delete PathElem;
|
||||
nElem = 0;
|
||||
Firebird::string oldpath = path;
|
||||
do {
|
||||
Firebird::string newpath, elem;
|
||||
PathUtils::splitLastComponent(newpath, elem, oldpath);
|
||||
oldpath = newpath;
|
||||
nElem++;
|
||||
} while (oldpath.length() > 0);
|
||||
|
||||
PathElem = New Firebird::string[nElem];
|
||||
oldpath = path;
|
||||
for (int i=nElem; i--; ) {
|
||||
Firebird::string newpath;
|
||||
PathUtils::splitLastComponent(newpath, PathElem[i], oldpath);
|
||||
oldpath = newpath;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParsedPath::operator==(const char * path) {
|
||||
return (Firebird::string(*this) == Firebird::string(path));
|
||||
}
|
||||
|
||||
Firebird::string ParsedPath::SubPath(int n) const {
|
||||
Firebird::string rc = "/" + PathElem[0];
|
||||
for (int i=1; i<n; i++) {
|
||||
Firebird::string newpath;
|
||||
PathUtils::concatPath(newpath, rc, PathElem[i]);
|
||||
rc = newpath;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
ParsedPath::operator Firebird::string() {
|
||||
if (! PathElem)
|
||||
return "";
|
||||
return SubPath(nElem);
|
||||
}
|
||||
|
||||
bool ParsedPath::Contains(const ParsedPath & pPath) {
|
||||
if (pPath.nElem < nElem) {
|
||||
return false;
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<nElem; i++) {
|
||||
if (! PathUtils::comparePaths(pPath.PathElem[i], PathElem[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = nElem + 1; i<=pPath.nElem; i++) {
|
||||
Firebird::string x = pPath.SubPath(i);
|
||||
if (PathUtils::isSymLink(x)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DirectoryList::DirectoryList() {
|
||||
ConfigDirs = 0;
|
||||
nDirs = 0;
|
||||
}
|
||||
|
||||
DirectoryList::~DirectoryList() {
|
||||
delete[] ConfigDirs;
|
||||
}
|
||||
|
||||
void DirectoryList::Initialize(void) {
|
||||
const Firebird::string val = GetConfigString();
|
||||
nDirs = 1;
|
||||
int i;
|
||||
for (i=0; i<val.length(); i++) {
|
||||
if (val[i] == ';') {
|
||||
nDirs++;
|
||||
}
|
||||
}
|
||||
ConfigDirs = New ParsedPath[nDirs];
|
||||
int Last = 0;
|
||||
nDirs = 0;
|
||||
Firebird::string Root = Config::getRootDirectory();
|
||||
for (i=0; i<val.length(); i++) {
|
||||
if (val[i] == ';') {
|
||||
Firebird::string dir = "";
|
||||
if (i > Last) {
|
||||
dir = val.substr(Last, i-Last);
|
||||
}
|
||||
if (PathUtils::isRelative(dir)) {
|
||||
Firebird::string newdir;
|
||||
PathUtils::concatPath(newdir, Root, dir);
|
||||
dir = newdir;
|
||||
}
|
||||
ConfigDirs[nDirs++].Parse(dir);
|
||||
Last = i + 1;
|
||||
}
|
||||
}
|
||||
Firebird::string dir = "";
|
||||
if (i > Last) {
|
||||
dir = val.substr(Last, i-Last);
|
||||
}
|
||||
if (PathUtils::isRelative(dir)) {
|
||||
Firebird::string newdir;
|
||||
PathUtils::concatPath(newdir, Root, dir);
|
||||
dir = newdir;
|
||||
}
|
||||
ConfigDirs[nDirs++].Parse(dir);
|
||||
}
|
||||
|
||||
bool DirectoryList::IsPathInList(const Firebird::string &path) {
|
||||
if (! ConfigDirs)
|
||||
Initialize();
|
||||
|
||||
// Disable any up-dir(..) references - in case our path_utils
|
||||
// and OS handle paths in slightly different ways,
|
||||
// this is "wonderful" potential hole for hacks
|
||||
// Example of IIS attack attempt:
|
||||
// "GET /scripts/..%252f../winnt/system32/cmd.exe?/c+dir HTTP/1.0"
|
||||
// (live from apache access log :)
|
||||
if (path.find(PathUtils::up_dir_link) != Firebird::string::npos)
|
||||
return false;
|
||||
|
||||
if (nDirs == 1 && ConfigDirs[0] == "/") // Handle special case - all open
|
||||
return true;
|
||||
|
||||
Firebird::string varpath = path;
|
||||
if (PathUtils::isRelative(path)) {
|
||||
PathUtils::concatPath(varpath,
|
||||
Firebird::string(Config::getRootDirectory()), path);
|
||||
}
|
||||
|
||||
ParsedPath pPath = path;
|
||||
bool rc = 0;
|
||||
for (int i=0; i<nDirs; i++) {
|
||||
if (ConfigDirs[i].Contains(pPath)) {
|
||||
rc = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
55
src/common/config/dir_list.h
Normal file
55
src/common/config/dir_list.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* PROGRAM: Client/Server Common Code
|
||||
* MODULE: dir_list.h
|
||||
* DESCRIPTION: Directory listing config file operation
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* Created by: Alex Peshkov <AlexPeshkov@users.sourceforge.net>
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef _DIR_LIST_H_
|
||||
#define _DIR_LIST_H_
|
||||
|
||||
class ParsedPath {
|
||||
Firebird::string * PathElem;
|
||||
int nElem;
|
||||
Firebird::string SubPath(int n) const;
|
||||
public:
|
||||
ParsedPath(void);
|
||||
ParsedPath(const Firebird::string & path);
|
||||
~ParsedPath();
|
||||
void Parse(const Firebird::string & path);
|
||||
Firebird::string operator[](int n);
|
||||
operator Firebird::string();
|
||||
bool operator==(const char * path);
|
||||
bool Contains(const ParsedPath & pPath);
|
||||
};
|
||||
|
||||
class DirectoryList {
|
||||
private:
|
||||
ParsedPath * ConfigDirs;
|
||||
int nDirs;
|
||||
void Initialize(void);
|
||||
protected:
|
||||
// for various configuration parameters
|
||||
// returns parameter value
|
||||
virtual const Firebird::string GetConfigString(void) = 0;
|
||||
public:
|
||||
DirectoryList();
|
||||
~DirectoryList();
|
||||
// Check, whether Path inside this DirectoryList
|
||||
bool IsPathInList(const Firebird::string & Path);
|
||||
};
|
||||
#endif // _DIR_LIST_H_
|
@ -54,7 +54,10 @@
|
||||
#include "../jrd/thd_proto.h"
|
||||
#include "../jrd/vio_proto.h"
|
||||
#include "../jrd/dls_proto.h"
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
|
||||
static IB_FILE *ext_fopen(const char *filename, const char *mode);
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -80,7 +83,6 @@ extern "C" {
|
||||
|
||||
//static void io_error(EXT, TEXT *, STATUS, SLONG);
|
||||
|
||||
|
||||
void EXT_close(RSB rsb)
|
||||
{
|
||||
/**************************************
|
||||
@ -199,10 +201,10 @@ EXT EXT_file(JRD_REL relation, TEXT * file_name, SLONG * description)
|
||||
#ifdef WIN_NT
|
||||
if (found_dir)
|
||||
{
|
||||
if (!(file->ext_ifi = (int*) ib_fopen(ib_file_path, FOPEN_TYPE)))
|
||||
if (!(file->ext_ifi = (int*) ext_fopen(ib_file_path, FOPEN_TYPE)))
|
||||
{
|
||||
/* could not open the file as read write attempt as read only */
|
||||
if (!(file->ext_ifi = (int*) ib_fopen(ib_file_path, FOPEN_READ_ONLY)))
|
||||
if (!(file->ext_ifi = (int*) ext_fopen(ib_file_path, FOPEN_READ_ONLY)))
|
||||
ERR_post(isc_io_error,
|
||||
gds_arg_string, "ib_fopen",
|
||||
gds_arg_string,
|
||||
@ -215,10 +217,10 @@ EXT EXT_file(JRD_REL relation, TEXT * file_name, SLONG * description)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(file->ext_ifi = (int*) ib_fopen(file_name, FOPEN_TYPE)))
|
||||
if (!(file->ext_ifi = (int*) ext_fopen(file_name, FOPEN_TYPE)))
|
||||
{
|
||||
/* could not open the file as read write attempt as read only */
|
||||
if (!(file->ext_ifi = (int*) ib_fopen(file_name, FOPEN_READ_ONLY)))
|
||||
if (!(file->ext_ifi = (int*) ext_fopen(file_name, FOPEN_READ_ONLY)))
|
||||
ERR_post(isc_io_error,
|
||||
gds_arg_string, "ib_fopen",
|
||||
gds_arg_string,
|
||||
@ -231,11 +233,11 @@ EXT EXT_file(JRD_REL relation, TEXT * file_name, SLONG * description)
|
||||
}
|
||||
#else
|
||||
if (!(dbb->dbb_flags & DBB_read_only))
|
||||
file->ext_ifi = (int *) ib_fopen(file_name, FOPEN_TYPE);
|
||||
file->ext_ifi = (int *) ext_fopen(file_name, FOPEN_TYPE);
|
||||
if (!(file->ext_ifi))
|
||||
{
|
||||
/* could not open the file as read write attempt as read only */
|
||||
if (!(file->ext_ifi = (int *) ib_fopen(file_name, FOPEN_READ_ONLY)))
|
||||
if (!(file->ext_ifi = (int *) ext_fopen(file_name, FOPEN_READ_ONLY)))
|
||||
ERR_post(isc_io_error,
|
||||
gds_arg_string, "ib_fopen",
|
||||
gds_arg_string,
|
||||
@ -653,3 +655,16 @@ void EXT_trans_start(JRD_TRA transaction)
|
||||
|
||||
|
||||
} // extern "C"
|
||||
|
||||
class ExternalFilesDirectoryList : public DirectoryList {
|
||||
virtual const Firebird::string GetConfigString(void) {
|
||||
return Firebird::string(Config::getExternalTablesDirectory());
|
||||
}
|
||||
};
|
||||
static ExternalFilesDirectoryList iExternalFilesDirectoryList;
|
||||
|
||||
static IB_FILE *ext_fopen(const char *filename, const char *mode) {
|
||||
if (! iExternalFilesDirectoryList.IsPathInList(filename))
|
||||
return 0;
|
||||
return ib_fopen(filename, mode);
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ public:
|
||||
/// The directory separator for the platform.
|
||||
static const char dir_sep;
|
||||
|
||||
/// String used to point to parent directory
|
||||
static const Firebird::string up_dir_link;
|
||||
|
||||
/** An abstract base class for iterating through the contents of a directory.
|
||||
Instances of this class are created using the newDirItr method of
|
||||
the PathUtils class. Each platform implementation is expected to
|
||||
@ -69,6 +72,19 @@ public:
|
||||
**/
|
||||
static bool isRelative(const Firebird::string& path);
|
||||
|
||||
/** isSymLink returns true if the given path is symbolic link, and false if not.
|
||||
Use of this links may provide way to override system security.
|
||||
Example: ln -s /usr/firebird/ExternalTables/mytable /etc/xinet.d/remoteshell
|
||||
and insert desired rows into mytable.
|
||||
**/
|
||||
static bool isSymLink(const Firebird::string& path);
|
||||
|
||||
/** comparePaths returns true if two given paths
|
||||
point to the same place in FileSystem.
|
||||
**/
|
||||
static bool comparePaths(const Firebird::string& path1,
|
||||
const Firebird::string& path2);
|
||||
|
||||
/** Concatinates the two paths given in the second and third parameters,
|
||||
and writes the resulting path into the first parameter. The
|
||||
two path input arguments (arg 2 and 3) are concatinated in the order
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "../jrd/os/path_utils.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
/// The POSIX implementation of the path_utils abstraction.
|
||||
|
||||
const char PathUtils::dir_sep = '/';
|
||||
const Firebird::string PathUtils::up_dir_link = "..";
|
||||
|
||||
class PosixDirItr : public PathUtils::dir_iterator
|
||||
{
|
||||
@ -117,3 +119,18 @@ bool PathUtils::isRelative(const Firebird::string& path)
|
||||
return path[0] != dir_sep;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathUtils::isSymLink(const Firebird::string& path)
|
||||
{
|
||||
struct stat st, lst;
|
||||
if (stat(path.c_str(), &st) != 0)
|
||||
return false;
|
||||
if (lstat(path.c_str(), &lst) != 0)
|
||||
return false;
|
||||
return st.st_ino != lst.st_ino;
|
||||
}
|
||||
|
||||
bool PathUtils::comparePaths(const Firebird::string& path1,
|
||||
const Firebird::string& path2) {
|
||||
return path1 == path2;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
/// The Win32 implementation of the path_utils abstraction.
|
||||
|
||||
const char PathUtils::dir_sep = '\\';
|
||||
const Firebird::string PathUtils::up_dir_link = "..";
|
||||
|
||||
class Win32DirItr : public PathUtils::dir_iterator
|
||||
{
|
||||
@ -117,7 +118,26 @@ void PathUtils::concatPath(Firebird::string& result,
|
||||
|
||||
bool PathUtils::isRelative(const Firebird::string& path)
|
||||
{
|
||||
if (path.length() > 0)
|
||||
return path[0] != PathUtils::dir_sep;
|
||||
if (path.length() > 0) {
|
||||
char ds = path[0];
|
||||
if (path.length() > 2) {
|
||||
if (path[1] == ':' &&
|
||||
(('A' <= path[0] && path[0] <= 'Z') ||
|
||||
('a' <= path[0] && path[0] <= 'z'))) {
|
||||
ds = path[2];
|
||||
}
|
||||
}
|
||||
return ds != PathUtils::dir_sep;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PathUtils::isSymLink(const Firebird::string& path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathUtils::comparePaths(const Firebird::string& path1,
|
||||
const Firebird::string& path2) {
|
||||
return stricmp(path1.c_str(), path2.c_str()) == 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user