mirror of
https://github.com/NixOS/nix.git
synced 2025-12-01 14:41: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:
parent
5713ff48c3
commit
3dbd83b9a1
4 changed files with 97 additions and 2 deletions
|
|
@ -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 isn’t 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue