nix verify-paths: Add ‘--sigs-needed <N>’ flag
This specifies the number of distinct signatures required to consider each path "trusted". Also renamed ‘--no-sigs’ to ‘--no-trust’ for the flag that disables verifying whether a path is trusted (since a path can also be trusted if it has no signatures, but was built locally).
This commit is contained in:
parent
6b2ae52808
commit
05fbc606fc
3 changed files with 41 additions and 16 deletions
|
@ -333,12 +333,18 @@ unsigned int ValidPathInfo::checkSignatures(const PublicKeys & publicKeys) const
|
||||||
{
|
{
|
||||||
unsigned int good = 0;
|
unsigned int good = 0;
|
||||||
for (auto & sig : sigs)
|
for (auto & sig : sigs)
|
||||||
if (verifyDetached(fingerprint(), sig, publicKeys))
|
if (checkSignature(publicKeys, sig))
|
||||||
good++;
|
good++;
|
||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ValidPathInfo::checkSignature(const PublicKeys & publicKeys, const std::string & sig) const
|
||||||
|
{
|
||||||
|
return verifyDetached(fingerprint(), sig, publicKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,9 @@ struct ValidPathInfo
|
||||||
/* Return the number of signatures on this .narinfo that were
|
/* Return the number of signatures on this .narinfo that were
|
||||||
produced by one of the specified keys. */
|
produced by one of the specified keys. */
|
||||||
unsigned int checkSignatures(const PublicKeys & publicKeys) const;
|
unsigned int checkSignatures(const PublicKeys & publicKeys) const;
|
||||||
|
|
||||||
|
/* Verify a single signature. */
|
||||||
|
bool checkSignature(const PublicKeys & publicKeys, const std::string & sig) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef list<ValidPathInfo> ValidPathInfos;
|
typedef list<ValidPathInfo> ValidPathInfos;
|
||||||
|
|
|
@ -13,15 +13,17 @@ using namespace nix;
|
||||||
struct MixVerify : virtual Args
|
struct MixVerify : virtual Args
|
||||||
{
|
{
|
||||||
bool noContents = false;
|
bool noContents = false;
|
||||||
bool noSigs = false;
|
bool noTrust = false;
|
||||||
Strings substituterUris;
|
Strings substituterUris;
|
||||||
|
size_t sigsNeeded;
|
||||||
|
|
||||||
MixVerify()
|
MixVerify()
|
||||||
{
|
{
|
||||||
mkFlag(0, "no-contents", "do not verify the contents of each store path", &noContents);
|
mkFlag(0, "no-contents", "do not verify the contents of each store path", &noContents);
|
||||||
mkFlag(0, "no-sigs", "do not verify whether each store path has a valid signature", &noSigs);
|
mkFlag(0, "no-trust", "do not verify whether each store path is trusted", &noTrust);
|
||||||
mkFlag('s', "substituter", {"store-uri"}, "use signatures from specified store", 1,
|
mkFlag('s', "substituter", {"store-uri"}, "use signatures from specified store", 1,
|
||||||
[&](Strings ss) { substituterUris.push_back(ss.front()); });
|
[&](Strings ss) { substituterUris.push_back(ss.front()); });
|
||||||
|
mkIntFlag('n', "sigs-needed", "require that each path has at least N valid signatures", &sigsNeeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifyPaths(ref<Store> store, const Paths & storePaths)
|
void verifyPaths(ref<Store> store, const Paths & storePaths)
|
||||||
|
@ -85,28 +87,42 @@ struct MixVerify : virtual Args
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noSigs) {
|
if (!noTrust) {
|
||||||
|
|
||||||
bool good = false;
|
bool good = false;
|
||||||
|
|
||||||
if (info.ultimate)
|
if (info.ultimate && !sigsNeeded)
|
||||||
good = true;
|
good = true;
|
||||||
|
|
||||||
if (!good && info.checkSignatures(publicKeys))
|
else {
|
||||||
good = true;
|
|
||||||
|
StringSet sigsSeen;
|
||||||
|
size_t actualSigsNeeded = sigsNeeded ? sigsNeeded : 1;
|
||||||
|
size_t validSigs = 0;
|
||||||
|
|
||||||
|
auto doSigs = [&](StringSet sigs) {
|
||||||
|
for (auto sig : sigs) {
|
||||||
|
if (sigsSeen.count(sig)) continue;
|
||||||
|
sigsSeen.insert(sig);
|
||||||
|
if (info.checkSignature(publicKeys, sig))
|
||||||
|
validSigs++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
doSigs(info.sigs);
|
||||||
|
|
||||||
if (!good) {
|
|
||||||
for (auto & store2 : substituters) {
|
for (auto & store2 : substituters) {
|
||||||
// FIXME: catch errors?
|
if (validSigs >= actualSigsNeeded) break;
|
||||||
|
try {
|
||||||
if (!store2->isValidPath(storePath)) continue;
|
if (!store2->isValidPath(storePath)) continue;
|
||||||
auto info2 = store2->queryPathInfo(storePath);
|
doSigs(store2->queryPathInfo(storePath).sigs);
|
||||||
auto info3(info);
|
} catch (Error & e) {
|
||||||
info3.sigs = info2.sigs;
|
printMsg(lvlError, format(ANSI_RED "error:" ANSI_NORMAL " %s") % e.what());
|
||||||
if (info3.checkSignatures(publicKeys)) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validSigs >= actualSigsNeeded)
|
||||||
good = true;
|
good = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!good) {
|
if (!good) {
|
||||||
|
|
Loading…
Reference in a new issue