Ver Fonte

Update Setup.

Martijn Laan há 2 meses atrás
pai
commit
00b8c7724b

+ 3 - 2
ISHelp/isxfunc.xml

@@ -1965,9 +1965,10 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>ISSigVerify</name>
-        <prototype>function ISSigVerify(const AllowedKeysRuntimeIDs: TStringList; const Filename: String; const KeepOpen: Boolean): TFileStream;</prototype>
+        <prototype>function ISSigVerify(const AllowedKeysRuntimeIDs: TStringList; const Filename: String; const VerifyFilename: Boolean; const KeepOpen: Boolean): TFileStream;</prototype>
         <description><p>Verifies the signature of the specified file using the specified allowed keys, looked up using <link topic="issigkeyssection">[ISSigKeys] section</link> parameter <tt>RuntimeID</tt>. To allow all keys set AllowedKeysRuntimeIDs to <tt>nil</tt>. An exception will be raised upon failure.</p>
-<p>Returns a handle to the still open file if True is specified in the KeepOpen parameter, <tt>nil</tt> otherwise. It is recommended that you always specify True if you plan to use the file for anything after verification. Otherwise, you risk creating a Time-Of-Check to Time-Of-Use (TOCTOU) problem.</p></description>
+<p>If VerifyFilename is set to False the verification allows signatures for a different filename. It is recommended that you only set it to False if you don't know the name the file had when it the signature was created. The size and hash of the file must always match.</p>        
+<p>Returns a handle to the still open file if KeepOpen is set to True, <tt>nil</tt> otherwise. It is recommended that you always set it to True if you plan to use the file for anything after verification. Otherwise, you risk creating a Time-Of-Check to Time-Of-Use (TOCTOU) problem.</p></description>
         <example><pre>var
   F: TFileStream;
 begin

+ 17 - 11
Projects/Src/Setup.Install.pas

@@ -20,7 +20,7 @@ procedure VerificationError(const AError: TVerificationError;
   const ASigFilename: String = '');
 
 procedure DoISSigVerify(const SourceF: TFile; const SourceFS: TFileStream;
-  const SourceFilename: String; const ISSigAllowedKeys: AnsiString;
+  const SourceFilename: String; const VerifySourceFilename: Boolean; const ISSigAllowedKeys: AnsiString;
   out ExpectedFileHash: TSHA256Digest);
 
 procedure PerformInstall(var Succeeded: Boolean; const ChangesEnvironment,
@@ -301,10 +301,11 @@ procedure VerificationError(const AError: TVerificationError;
 const
   LogMessages: array[TVerificationError] of String =
     ('Signature file does not exist', 'Signature is malformed', 'No matching key found',
-     'Signature is bad', 'File size is incorrect', 'File hash is incorrect');
+     'Signature is bad', 'File name is incorrect', 'File size is incorrect', 'File hash is incorrect');
   SetupMessageIDs: array[TVerificationError] of TSetupMessageID =
     (msgVerificationSignatureDoesntExist, msgVerificationSignatureInvalid, msgVerificationKeyNotFound,
-     msgVerificationSignatureInvalid, msgVerificationFileSizeIncorrect, msgVerificationFileHashIncorrect);
+     msgVerificationSignatureInvalid, msgVerificationFileNameIncorrect, msgVerificationFileSizeIncorrect,
+     msgVerificationFileHashIncorrect);
 begin
   { Also see Compiler.SetupCompiler for a similar function }
   Log('Verification error: ' + AddPeriod(LogMessages[AError]));
@@ -313,7 +314,7 @@ begin
 end;
 
 procedure DoISSigVerify(const SourceF: TFile; const SourceFS: TFileStream;
-  const SourceFilename: String; const ISSigAllowedKeys: AnsiString;
+  const SourceFilename: String; const VerifySourceFilename: Boolean; const ISSigAllowedKeys: AnsiString;
   out ExpectedFileHash: TSHA256Digest);
 { Does not disable FS redirection. Either SourceF or SourceFS must be set, which
   may be opened for writing instead of reading.  }
@@ -321,10 +322,11 @@ begin
   if ((SourceF = nil) and (SourceFS = nil)) or ((SourceF <> nil) and (SourceFS <> nil)) then
     InternalError('DoISSigVerify: Invalid SourceF / SourceFS combination');
 
+  var ExpectedFileName: String;
   var ExpectedFileSize: Int64;
   if not ISSigVerifySignature(SourceFilename,
     GetISSigAllowedKeys(ISSigAvailableKeys, ISSigAllowedKeys),
-    ExpectedFileSize, ExpectedFileHash,
+    ExpectedFileName, ExpectedFileSize, ExpectedFileHash,
     nil,
     procedure(const Filename, SigFilename: String)
     begin
@@ -342,6 +344,8 @@ begin
     end
   ) then
     InternalError('Unexpected ISSigVerifySignature result');
+  if VerifySourceFilename and (ExpectedFileName <> '') and not PathSame(PathExtractName(SourceFilename), ExpectedFileName) then
+    VerificationError(veFileNameIncorrect);
   var FileSize: Int64;
   if SourceF <> nil then
     FileSize := Int64(SourceF.Size)
@@ -371,7 +375,7 @@ begin
     if Verification.Typ = fvHash then
       ExpectedFileHash := Verification.Hash
     else
-      DoISSigVerify(SourceF, nil, ISSigSourceFilename, Verification.ISSigAllowedKeys, ExpectedFileHash);
+      DoISSigVerify(SourceF, nil, ISSigSourceFilename, True, Verification.ISSigAllowedKeys, ExpectedFileHash);
     { ExpectedFileHash checked below after copy }
     SHA256Init(Context);
   end;
@@ -2052,8 +2056,8 @@ var
               if CurFile^.Verification.Typ = fvHash then
                 ExpectedFileHash := CurFile^.Verification.Hash
               else begin
-                DoISSigVerify(VerifySourceF, nil, ArchiveFilename, CurFile^.Verification.ISSigAllowedKeys,
-                ExpectedFileHash);
+                DoISSigVerify(VerifySourceF, nil, ArchiveFilename, True, CurFile^.Verification.ISSigAllowedKeys,
+                  ExpectedFileHash);
               end;
               { Can't get the SHA-256 while extracting so need to get and check it now }
               const ActualFileHash = GetSHA256OfFile(VerifySourceF);
@@ -3874,7 +3878,7 @@ begin
         if Verification.Typ = fvHash then
           ExpectedFileHash := Verification.Hash
         else
-          DoISSigVerify(DestF, nil, ISSigSourceFilename, Verification.ISSigAllowedKeys, ExpectedFileHash);
+          DoISSigVerify(DestF, nil, ISSigSourceFilename, False, Verification.ISSigAllowedKeys, ExpectedFileHash);
         const FileHash = GetSHA256OfFile(DestF);
         if not SHA256DigestsEqual(FileHash, ExpectedFileHash) then
           VerificationError(veFileHashIncorrect);
@@ -3931,12 +3935,14 @@ begin
         Exit;
       end;
     end else if Verification.Typ = fvISSig then begin
+      var ExistingFileName: String;
       var ExistingFileSize: Int64;
       var ExistingFileHash: TSHA256Digest;
       if ISSigVerifySignature(DestFile, GetISSigAllowedKeys(ISSigAvailableKeys, Verification.ISSigAllowedKeys),
-           ExistingFileSize, ExistingFileHash, nil, nil, nil) then begin
+           ExistingFileName, ExistingFileSize, ExistingFileHash, nil, nil, nil) then begin
         const DestF = TFile.Create(DestFile, fdOpenExisting, faRead, fsReadWrite);
         try
+          { Not checking ExistingFileName because we can't be sure what the original filename was }
           if (Int64(DestF.Size) = ExistingFileSize) and
              (SHA256DigestsEqual(GetSHA256OfFile(DestF), ExistingFileHash)) then begin
             Log('  File already downloaded.');
@@ -4013,7 +4019,7 @@ begin
         if Verification.Typ = fvHash then
           ExpectedFileHash := Verification.Hash
         else
-          DoISSigVerify(TempF, nil, DestFile, Verification.ISSigAllowedKeys, ExpectedFileHash);
+          DoISSigVerify(TempF, nil, DestFile, False, Verification.ISSigAllowedKeys, ExpectedFileHash);
         FreeAndNil(TempF);
         const FileHash = GetSHA256OfFile(False, TempFile);
         if not SHA256DigestsEqual(FileHash, ExpectedFileHash) then

+ 3 - 2
Projects/Src/Setup.ScriptFunc.pas

@@ -1879,14 +1879,15 @@ var
     begin
       const ISSigAllowedKeys = ConvertAllowedKeysRuntimeIDsToISSigAllowedKeys(TStringList(Stack.GetClass(PStart-1)));
       const Filename = Stack.GetString(PStart-2);
-      const KeepOpen = Stack.GetBool(PStart-3);
+      const VerifyFilename = Stack.GetBool(PStart-3);
+      const KeepOpen = Stack.GetBool(PStart-4);
 
       { Verify signature & file, keeping open afterwards if requested
         Also see TrustFunc's CheckFileTrust which can also keep open afterwards }
       var F := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
       try
         var ExpectedFileHash: TSHA256Digest;
-        DoISSigVerify(nil, F, Filename, ISSigAllowedKeys, ExpectedFileHash);
+        DoISSigVerify(nil, F, Filename, VerifyFilename, ISSigAllowedKeys, ExpectedFileHash);
          { Couldn't get the SHA-256 while downloading so need to get and check it now }
         const ActualFileHash = ISSigCalcStreamHash(F);
         if not SHA256DigestsEqual(ActualFileHash, ExpectedFileHash) then

+ 1 - 1
Projects/Src/Shared.ScriptFunc.pas

@@ -547,7 +547,7 @@ initialization
     'function StringJoin(const Separator: String; const Values: TArrayOfString): String;',
     'function StringSplit(const S: String; const Separators: TArrayOfString; const Typ: TSplitType): TArrayOfString;',
     'function StringSplitEx(const S: String; const Separators: TArrayOfString; const Quote: Char; const Typ: TSplitType): TArrayOfString;',
-    'function ISSigVerify(const AllowedKeysRuntimeIDs: TStringList; const Filename: String; const KeepOpen: Boolean): TFileStream;'
+    'function ISSigVerify(const AllowedKeysRuntimeIDs: TStringList; const Filename: String; const VerifyFilename: Boolean; const KeepOpen: Boolean): TFileStream;'
   ];
 
   {$IFDEF COMPIL32PROJ}