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; | ||||||
|                             if (!store2->isValidPath(storePath)) continue; |                             try { | ||||||
|                             auto info2 = store2->queryPathInfo(storePath); |                                 if (!store2->isValidPath(storePath)) continue; | ||||||
|                             auto info3(info); |                                 doSigs(store2->queryPathInfo(storePath).sigs); | ||||||
|                             info3.sigs = info2.sigs; |                             } catch (Error & e) { | ||||||
|                             if (info3.checkSignatures(publicKeys)) { |                                 printMsg(lvlError, format(ANSI_RED "error:" ANSI_NORMAL " %s") % e.what()); | ||||||
|                                 good = true; |  | ||||||
|                                 break; |  | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  | 
 | ||||||
|  |                         if (validSigs >= actualSigsNeeded) | ||||||
|  |                             good = true; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     if (!good) { |                     if (!good) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue