Bläddra i källkod

Update Setup.

Martijn Laan 2 månader sedan
förälder
incheckning
00b8c7724b

+ 3 - 2
ISHelp/isxfunc.xml

@@ -1965,9 +1965,10 @@ end;</pre></example>
     <subcategory>
     <subcategory>
       <function>
       <function>
         <name>ISSigVerify</name>
         <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>
         <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
         <example><pre>var
   F: TFileStream;
   F: TFileStream;
 begin
 begin

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

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

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

@@ -1879,14 +1879,15 @@ var
     begin
     begin
       const ISSigAllowedKeys = ConvertAllowedKeysRuntimeIDsToISSigAllowedKeys(TStringList(Stack.GetClass(PStart-1)));
       const ISSigAllowedKeys = ConvertAllowedKeysRuntimeIDsToISSigAllowedKeys(TStringList(Stack.GetClass(PStart-1)));
       const Filename = Stack.GetString(PStart-2);
       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
       { Verify signature & file, keeping open afterwards if requested
         Also see TrustFunc's CheckFileTrust which can also keep open afterwards }
         Also see TrustFunc's CheckFileTrust which can also keep open afterwards }
       var F := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
       var F := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
       try
       try
         var ExpectedFileHash: TSHA256Digest;
         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 }
          { Couldn't get the SHA-256 while downloading so need to get and check it now }
         const ActualFileHash = ISSigCalcStreamHash(F);
         const ActualFileHash = ISSigCalcStreamHash(F);
         if not SHA256DigestsEqual(ActualFileHash, ExpectedFileHash) then
         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 StringJoin(const Separator: String; const Values: TArrayOfString): String;',
     'function StringSplit(const S: String; const Separators: TArrayOfString; const Typ: TSplitType): TArrayOfString;',
     '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 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}
   {$IFDEF COMPIL32PROJ}