From 05fbc606fc1ce4a764276b7dee6ed49859de9d57 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Apr 2016 15:14:12 +0200 Subject: [PATCH] =?UTF-8?q?nix=20verify-paths:=20Add=20=E2=80=98--sigs-nee?= =?UTF-8?q?ded=20=E2=80=99=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- src/libstore/store-api.cc | 8 ++++++- src/libstore/store-api.hh | 3 +++ src/nix/verify.cc | 46 ++++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b9939feda..cc91ed287 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -333,12 +333,18 @@ unsigned int ValidPathInfo::checkSignatures(const PublicKeys & publicKeys) const { unsigned int good = 0; for (auto & sig : sigs) - if (verifyDetached(fingerprint(), sig, publicKeys)) + if (checkSignature(publicKeys, sig)) good++; return good; } +bool ValidPathInfo::checkSignature(const PublicKeys & publicKeys, const std::string & sig) const +{ + return verifyDetached(fingerprint(), sig, publicKeys); +} + + } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 4ea360b9d..798054d16 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -127,6 +127,9 @@ struct ValidPathInfo /* Return the number of signatures on this .narinfo that were produced by one of the specified keys. */ unsigned int checkSignatures(const PublicKeys & publicKeys) const; + + /* Verify a single signature. */ + bool checkSignature(const PublicKeys & publicKeys, const std::string & sig) const; }; typedef list ValidPathInfos; diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 0c05f450a..9214d3b65 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -13,15 +13,17 @@ using namespace nix; struct MixVerify : virtual Args { bool noContents = false; - bool noSigs = false; + bool noTrust = false; Strings substituterUris; + size_t sigsNeeded; MixVerify() { 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, [&](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, const Paths & storePaths) @@ -85,28 +87,42 @@ struct MixVerify : virtual Args } - if (!noSigs) { + if (!noTrust) { bool good = false; - if (info.ultimate) + if (info.ultimate && !sigsNeeded) good = true; - if (!good && info.checkSignatures(publicKeys)) - good = true; + else { + + 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) { - // FIXME: catch errors? - if (!store2->isValidPath(storePath)) continue; - auto info2 = store2->queryPathInfo(storePath); - auto info3(info); - info3.sigs = info2.sigs; - if (info3.checkSignatures(publicKeys)) { - good = true; - break; + if (validSigs >= actualSigsNeeded) break; + try { + if (!store2->isValidPath(storePath)) continue; + doSigs(store2->queryPathInfo(storePath).sigs); + } catch (Error & e) { + printMsg(lvlError, format(ANSI_RED "error:" ANSI_NORMAL " %s") % e.what()); } } + + if (validSigs >= actualSigsNeeded) + good = true; } if (!good) {