/changelog_unreleased/4647-validatepath-allows-lease-file-path-outside-dhcp-data-dir
- reworded to be more user friendly
/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
updated test
/src/lib/util/filesystem.cc
PathChecker::validatePath() - treat "." and ".." as always invalid
/src/lib/util/tests/filesystem_unittests.cc
updated test
-[bug] wlodek
- PathChecker::validatePath() now rejects "." and ".." file names,
- which previously bypassed parent-directory checks and could resolve
- paths outside the configured data directory (e.g. memfile lease
- database name "..").
+[bug] wlodek, tmark
+ Path validation now rejects now rejects "." and ".." file names
+ as invalid (e.g. memfile lease database name "..").
(Gitlab #4647)
ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
file::SecurityError, os.str());
- // Bare ".." must not resolve outside the data directory.
+ // Blank value should be rejected.
+ pmap["name"] = " ";
+ ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
+ BadValue, "path: '' has no filename");
+
+ // Empty value should be rejected.
+ pmap["name"] = "";
+ ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
+ BadValue, "path: '' has no filename");
+
+ // Bare "." should be rejected.
+ pmap["name"] = ".";
+ ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
+ BadValue, "path: '.' has no filename");
+
+ // Bare ".." should be rejected.
pmap["name"] = "..";
- std::ostringstream os2;
- os2 << "invalid path specified: '..', supported path is '"
- << CfgMgr::instance().getDataDir() << "'";
ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
- file::SecurityError, os2.str());
+ BadValue, "path: '..' has no filename");
}
/// @brief Verifies that the supported path may be overridden with
bool enforce_path /* = PathChecker::shouldEnforceSecurity() */) const {
Path input_path(trim(input_path_str));
auto filename = input_path.filename();
- if (filename.empty()) {
+ if (filename.empty() || (filename == ".") || (filename == "..")) {
isc_throw(BadValue, "path: '" << input_path.str() << "' has no filename");
}
- // A bare "." or ".." has an empty parent directory, so the check below would
- // otherwise accept it and append it to the supported path. For "..", that
- // resolves outside the supported directory (e.g. /var/lib/kea/..). The same
- // escape also occurs for "<supported-path>/..", whose parent matches.
- if ((filename == ".") || (filename == "..")) {
- std::ostringstream oss;
- oss << "invalid path specified: '"
- << filename
- << "', supported path is '"
- << path_ << "'";
-
- if (enforce_path) {
- isc_throw(SecurityError, oss.str());
- } else {
- isc_throw(SecurityWarn, oss.str());
- }
- }
-
auto parent_path = input_path.parentPath();
auto parent_dir = input_path.parentDirectory();
if (!parent_dir.empty()) {
__LINE__,
"..",
"",
- string("invalid path specified: '..', supported path is '" +
- def_path + "'"),
- true
+ "path: '..' has no filename",
+ false
},
{
// Bare "." refers to the supported directory itself.
__LINE__,
".",
"",
- string("invalid path specified: '.', supported path is '" +
- def_path + "'"),
- true
+ "path: '.' has no filename",
+ false
},
{
// Supported path plus ".." also escapes despite matching parent.
__LINE__,
def_path + "/..",
"",
- string("invalid path specified: '..', supported path is '" +
- def_path + "'"),
- true
+ string("path: '" + def_path + "/..' has no filename"),
+ false
}
};