1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-01 06:31:00 +01:00

Check the CA hash when importing stuff in the local store

When adding a path to the local store (via `LocalStore::addToStore`),
ensure that the `ca` field of the provided `ValidPathInfo` does indeed
correspond to the content of the path.
Otherwise any untrusted user (or any binary cache) can add arbitrary
content-addressed paths to the store (as content-addressed paths don’t
need a signature).
This commit is contained in:
regnat 2021-05-27 13:25:25 +02:00 committed by Eelco Dolstra
parent 5713ff48c3
commit 3dbd83b9a1
4 changed files with 97 additions and 2 deletions

View file

@ -1029,6 +1029,40 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s",
info.path, info.narSize, hashResult.second);
if (!info.ca.empty()) {
auto ca = info.ca;
if (hasPrefix(ca, "fixed:")) {
bool recursive = ca.compare(6, 2, "r:") == 0;
Hash expectedHash(std::string(ca, recursive ? 8 : 6));
if (info.references.empty()) {
auto actualFoHash = hashCAPath(
recursive,
expectedHash.type,
info.path
);
if (ca != actualFoHash) {
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
info.path,
ca,
actualFoHash);
}
} else {
throw Error("path '%s' claims to be content-addressed, but has references. This isnt allowed",
info.path);
}
} else if (hasPrefix(ca, "text:")) {
Hash textHash(std::string(ca, 5));
auto actualTextHash = hashString(htSHA256, readFile(realPath));
if (textHash != actualTextHash) {
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
info.path,
textHash.to_string(Base32, true),
actualTextHash.to_string(Base32, true));
}
}
}
autoGC();
canonicalisePathMetaData(realPath, -1);
@ -1450,4 +1484,20 @@ void LocalStore::createUser(const std::string & userName, uid_t userId)
}
std::string LocalStore::hashCAPath(
bool recursive,
const HashType & hashType,
const Path & path
)
{
HashSink caSink(hashType);
if (recursive) {
dumpPath(path, caSink);
} else {
readFile(path, caSink);
}
auto hash = caSink.finish().first;
return makeFixedOutputCA(recursive, hash);
}
}

View file

@ -295,8 +295,14 @@ private:
void createUser(const std::string & userName, uid_t userId) override;
friend class DerivationGoal;
friend class SubstitutionGoal;
std::string hashCAPath(
bool recursive,
const HashType & hashType,
const Path & path
);
friend struct DerivationGoal;
friend struct SubstitutionGoal;
};