mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-12-01 18:16:14 +02:00
130 lines
3.5 KiB
C++
130 lines
3.5 KiB
C++
#include "fs-input-accessor.hh"
|
|
#include "posix-source-accessor.hh"
|
|
#include "store-api.hh"
|
|
|
|
namespace nix {
|
|
|
|
struct FSInputAccessorImpl : FSInputAccessor, PosixSourceAccessor
|
|
{
|
|
CanonPath root;
|
|
std::optional<std::set<CanonPath>> allowedPaths;
|
|
MakeNotAllowedError makeNotAllowedError;
|
|
|
|
FSInputAccessorImpl(
|
|
const CanonPath & root,
|
|
std::optional<std::set<CanonPath>> && allowedPaths,
|
|
MakeNotAllowedError && makeNotAllowedError)
|
|
: root(root)
|
|
, allowedPaths(std::move(allowedPaths))
|
|
, makeNotAllowedError(std::move(makeNotAllowedError))
|
|
{
|
|
}
|
|
|
|
void readFile(
|
|
const CanonPath & path,
|
|
Sink & sink,
|
|
std::function<void(uint64_t)> sizeCallback) override
|
|
{
|
|
auto absPath = makeAbsPath(path);
|
|
checkAllowed(absPath);
|
|
PosixSourceAccessor::readFile(absPath, sink, sizeCallback);
|
|
}
|
|
|
|
bool pathExists(const CanonPath & path) override
|
|
{
|
|
auto absPath = makeAbsPath(path);
|
|
return isAllowed(absPath) && PosixSourceAccessor::pathExists(absPath);
|
|
}
|
|
|
|
std::optional<Stat> maybeLstat(const CanonPath & path) override
|
|
{
|
|
auto absPath = makeAbsPath(path);
|
|
checkAllowed(absPath);
|
|
return PosixSourceAccessor::maybeLstat(absPath);
|
|
}
|
|
|
|
DirEntries readDirectory(const CanonPath & path) override
|
|
{
|
|
auto absPath = makeAbsPath(path);
|
|
checkAllowed(absPath);
|
|
DirEntries res;
|
|
for (auto & entry : PosixSourceAccessor::readDirectory(absPath))
|
|
if (isAllowed(absPath + entry.first))
|
|
res.emplace(entry);
|
|
return res;
|
|
}
|
|
|
|
std::string readLink(const CanonPath & path) override
|
|
{
|
|
auto absPath = makeAbsPath(path);
|
|
checkAllowed(absPath);
|
|
return PosixSourceAccessor::readLink(absPath);
|
|
}
|
|
|
|
CanonPath makeAbsPath(const CanonPath & path)
|
|
{
|
|
return root + path;
|
|
}
|
|
|
|
void checkAllowed(const CanonPath & absPath) override
|
|
{
|
|
if (!isAllowed(absPath))
|
|
throw makeNotAllowedError
|
|
? makeNotAllowedError(absPath)
|
|
: RestrictedPathError("access to path '%s' is forbidden", absPath);
|
|
}
|
|
|
|
bool isAllowed(const CanonPath & absPath)
|
|
{
|
|
if (!absPath.isWithin(root))
|
|
return false;
|
|
|
|
if (allowedPaths) {
|
|
auto p = absPath.removePrefix(root);
|
|
if (!p.isAllowed(*allowedPaths))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void allowPath(CanonPath path) override
|
|
{
|
|
if (allowedPaths)
|
|
allowedPaths->insert(std::move(path));
|
|
}
|
|
|
|
bool hasAccessControl() override
|
|
{
|
|
return (bool) allowedPaths;
|
|
}
|
|
|
|
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override
|
|
{
|
|
return makeAbsPath(path);
|
|
}
|
|
};
|
|
|
|
ref<FSInputAccessor> makeFSInputAccessor(
|
|
const CanonPath & root,
|
|
std::optional<std::set<CanonPath>> && allowedPaths,
|
|
MakeNotAllowedError && makeNotAllowedError)
|
|
{
|
|
return make_ref<FSInputAccessorImpl>(root, std::move(allowedPaths), std::move(makeNotAllowedError));
|
|
}
|
|
|
|
ref<FSInputAccessor> makeStorePathAccessor(
|
|
ref<Store> store,
|
|
const StorePath & storePath,
|
|
MakeNotAllowedError && makeNotAllowedError)
|
|
{
|
|
return makeFSInputAccessor(CanonPath(store->toRealPath(storePath)), {}, std::move(makeNotAllowedError));
|
|
}
|
|
|
|
SourcePath getUnfilteredRootPath(CanonPath path)
|
|
{
|
|
static auto rootFS = makeFSInputAccessor(CanonPath::root);
|
|
return {rootFS, path};
|
|
}
|
|
|
|
}
|