about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-03-30T09·18+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-03-30T09·39+0200
commit39a6abc0bc2f1986f29e52de15ccbdde9586bc08 (patch)
treeb1a52de72593225ef3601ad5ceab5aa494704bf3
parent88541569a2acded0e4999368a4724c96d6ed37e7 (diff)
nix verify: Support checking against signatures in other stores
Typical usage is to check local paths using the signatures from a
binary cache:

  $ nix verify-paths -r /run/current-system -s https://cache.nixos.org
  path ‘/nix/store/c1k4zqfb74wba5sn4yflb044gvap0x6k-nixos-system-mandark-16.03.git.fc2d7a5M’ is untrusted
  ...
  checked 844 paths, 119 untrusted
-rw-r--r--src/nix/verify.cc35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/nix/verify.cc b/src/nix/verify.cc
index 1bd2a000a3ee..0c05f450a493 100644
--- a/src/nix/verify.cc
+++ b/src/nix/verify.cc
@@ -14,17 +14,24 @@ struct MixVerify : virtual Args
 {
     bool noContents = false;
     bool noSigs = false;
+    Strings substituterUris;
 
     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('s', "substituter", {"store-uri"}, "use signatures from specified store", 1,
+            [&](Strings ss) { substituterUris.push_back(ss.front()); });
     }
 
     void verifyPaths(ref<Store> store, const Paths & storePaths)
     {
         restoreAffinity(); // FIXME
 
+        std::vector<ref<Store>> substituters;
+        for (auto & s : substituterUris)
+            substituters.push_back(openStoreAt(s));
+
         auto publicKeys = getDefaultPublicKeys();
 
         std::atomic<size_t> untrusted{0};
@@ -56,7 +63,9 @@ struct MixVerify : virtual Args
 
         auto doPath = [&](const Path & storePath) {
             try {
-                progressBar.startActivity(format("checking ‘%s’") % storePath);
+                checkInterrupt();
+
+                auto activity(progressBar.startActivity(format("checking ‘%s’") % storePath));
 
                 auto info = store->queryPathInfo(storePath);
 
@@ -78,7 +87,29 @@ struct MixVerify : virtual Args
 
                 if (!noSigs) {
 
-                    if (!info.ultimate && !info.checkSignatures(publicKeys)) {
+                    bool good = false;
+
+                    if (info.ultimate)
+                        good = true;
+
+                    if (!good && info.checkSignatures(publicKeys))
+                        good = true;
+
+                    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 (!good) {
                         untrusted++;
                         printMsg(lvlError, format("path ‘%s’ is untrusted") % storePath);
                     }