8
0
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:
alexpeshkoff 2003-03-15 20:20:41 +00:00
parent 65f00fcac9
commit 70c9d082ba
9 changed files with 331 additions and 10 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View 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;
}

View 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_

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}