diff --git a/src/jrd/ext.cpp b/src/jrd/ext.cpp index be3affde92a..534a4f0a0c6 100644 --- a/src/jrd/ext.cpp +++ b/src/jrd/ext.cpp @@ -115,6 +115,27 @@ namespace Jrd using namespace Jrd; +namespace Jrd { + +// Validate that an external file path is allowed by the configured +// ExternalFileAccess policy. Raises isc_conf_access_denied otherwise. +// Used at metadata load time (met.epp) and at file open time so that +// paths escaping the allowed directory list are rejected consistently, +// regardless of whether the external table was just created or loaded +// from an existing database. +void checkExternalFileAccess(Database* dbb, const Firebird::PathName& fileName) +{ + ExternalFileDirectoryList::create(dbb); + + if (!dbb->dbb_external_file_directory_list->isPathInList(fileName)) + { + ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("external file") << + Arg::Str(fileName.c_str())); + } +} + +} // namespace Jrd + namespace { #ifdef WIN_NT @@ -131,13 +152,7 @@ void ExternalFile::open(Database* dbb) { fb_assert(ext_sync.locked()); - ExternalFileDirectoryList::create(dbb); - - if (!dbb->dbb_external_file_directory_list->isPathInList(ext_filename)) - { - ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("external file") << - Arg::Str(ext_filename)); - } + checkExternalFileAccess(dbb, Firebird::PathName(static_cast(ext_filename))); // If the database is updateable then try opening the external files in RW mode. ext_flags = 0; diff --git a/src/jrd/ext_proto.h b/src/jrd/ext_proto.h index fbb18312877..000dbb3aa0e 100644 --- a/src/jrd/ext_proto.h +++ b/src/jrd/ext_proto.h @@ -27,6 +27,7 @@ #include "fb_blk.h" #include "../common/classes/alloc.h" #include "../common/classes/locks.h" +#include "../common/classes/fb_string.h" #ifndef JRD_EXT_PROTO_H #define JRD_EXT_PROTO_H @@ -43,6 +44,10 @@ class thread_db; // External file access block +// Validate external file path against ExternalFileAccess policy, +// raise isc_conf_access_denied if not allowed. +void checkExternalFileAccess(Database* dbb, const Firebird::PathName& fileName); + class ExternalFile : public pool_alloc_rpt { private: diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 45941cf2937..8b90dcf7a64 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -3310,6 +3310,7 @@ ScanResult jrd_rel::scan(thread_db* tdbb, ObjectBase::Flag& flags) if (REL.RDB$EXTERNAL_FILE[0] && !rel_perm->getExtFile()) { + checkExternalFileAccess(tdbb->getDatabase(), REL.RDB$EXTERNAL_FILE); rel_perm->setExtFile(ExternalFile::create(getPool(), REL.RDB$EXTERNAL_FILE)); }