93 lines
2.4 KiB
C++
93 lines
2.4 KiB
C++
#include "filtering-input-accessor.hh"
|
|
|
|
namespace nix {
|
|
|
|
std::string FilteringInputAccessor::readFile(const CanonPath & path)
|
|
{
|
|
checkAccess(path);
|
|
return next->readFile(prefix / path);
|
|
}
|
|
|
|
bool FilteringInputAccessor::pathExists(const CanonPath & path)
|
|
{
|
|
return isAllowed(path) && next->pathExists(prefix / path);
|
|
}
|
|
|
|
std::optional<InputAccessor::Stat> FilteringInputAccessor::maybeLstat(const CanonPath & path)
|
|
{
|
|
checkAccess(path);
|
|
return next->maybeLstat(prefix / path);
|
|
}
|
|
|
|
InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path)
|
|
{
|
|
checkAccess(path);
|
|
DirEntries entries;
|
|
for (auto & entry : next->readDirectory(prefix / path)) {
|
|
if (isAllowed(path / entry.first))
|
|
entries.insert(std::move(entry));
|
|
}
|
|
return entries;
|
|
}
|
|
|
|
std::string FilteringInputAccessor::readLink(const CanonPath & path)
|
|
{
|
|
checkAccess(path);
|
|
return next->readLink(prefix / path);
|
|
}
|
|
|
|
std::string FilteringInputAccessor::showPath(const CanonPath & path)
|
|
{
|
|
return next->showPath(prefix / path);
|
|
}
|
|
|
|
void FilteringInputAccessor::checkAccess(const CanonPath & path)
|
|
{
|
|
if (!isAllowed(path))
|
|
throw makeNotAllowedError
|
|
? makeNotAllowedError(path)
|
|
: RestrictedPathError("access to path '%s' is forbidden", showPath(path));
|
|
}
|
|
|
|
struct AllowListInputAccessorImpl : AllowListInputAccessor
|
|
{
|
|
std::set<CanonPath> allowedPaths;
|
|
|
|
AllowListInputAccessorImpl(
|
|
ref<InputAccessor> next,
|
|
std::set<CanonPath> && allowedPaths,
|
|
MakeNotAllowedError && makeNotAllowedError)
|
|
: AllowListInputAccessor(SourcePath(next), std::move(makeNotAllowedError))
|
|
, allowedPaths(std::move(allowedPaths))
|
|
{ }
|
|
|
|
bool isAllowed(const CanonPath & path) override
|
|
{
|
|
return path.isAllowed(allowedPaths);
|
|
}
|
|
|
|
void allowPath(CanonPath path) override
|
|
{
|
|
allowedPaths.insert(std::move(path));
|
|
}
|
|
};
|
|
|
|
ref<AllowListInputAccessor> AllowListInputAccessor::create(
|
|
ref<InputAccessor> next,
|
|
std::set<CanonPath> && allowedPaths,
|
|
MakeNotAllowedError && makeNotAllowedError)
|
|
{
|
|
return make_ref<AllowListInputAccessorImpl>(next, std::move(allowedPaths), std::move(makeNotAllowedError));
|
|
}
|
|
|
|
bool CachingFilteringInputAccessor::isAllowed(const CanonPath & path)
|
|
{
|
|
auto i = cache.find(path);
|
|
if (i != cache.end()) return i->second;
|
|
auto res = isAllowedUncached(path);
|
|
cache.emplace(path, res);
|
|
return res;
|
|
}
|
|
|
|
}
|