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; | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<ValidPathInfo> ValidPathInfos; | ||||
|  |  | |||
|  | @ -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> 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) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue