Sfoglia il codice sorgente

Add issigverify support for extractarchive.

Martijn Laan 3 mesi fa
parent
commit
5016f1c1dc
1 ha cambiato i file con 113 aggiunte e 87 eliminazioni
  1. 113 87
      Projects/Src/Setup.Install.pas

+ 113 - 87
Projects/Src/Setup.Install.pas

@@ -250,25 +250,58 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure ISSigVerifyError(const AReason, AExceptionMessage: String);
+type
+  TISSigVerifySignatureError = (vseMissingFile, vseMalformedOrBadSignature, vseKeyNotFound,
+    vseUnknownVerifyResult, vseFileSizeIncorrect, vseFileHashIncorrect);
+
+procedure ISSigVerifyError(const AError: TISSigVerifySignatureError; const AExceptionMessage: String);
+const
+  ErrorStrings: array[TISSigVerifySignatureError] of String =
+    ('Signature file does not exist', 'Malformed or bad signature', 'No matching key found',
+      'Unknown verify result', 'File size incorrect', 'File hash incorrect');
 begin
 begin
-  Log('ISSig verification error: ' + AddPeriod(AReason));
+  Log('ISSig verification error: ' + AddPeriod(ErrorStrings[AError]));
   raise Exception.Create(AExceptionMessage);
   raise Exception.Create(AExceptionMessage);
 end;
 end;
 
 
+procedure DoISSigVerify(const SourceF: TFile; const SourceFilename: String;
+  const ISSigAllowedKeys: AnsiString; out ExpectedFileHash: TSHA256Digest);
+{ Caller must check ExpectedFileHash }
+begin
+  var ExpectedFileSize: Int64;
+  if not ISSigVerifySignature(SourceFilename,
+    GetISSigAllowedKeys(ISSigAvailableKeys, ISSigAllowedKeys),
+    ExpectedFileSize, ExpectedFileHash,
+    nil,
+    procedure(const Filename, SigFilename: String)
+    begin
+      ISSigVerifyError(vseMissingFile, FmtSetupMessage1(msgSourceDoesntExist, SigFilename));
+    end,
+    procedure(const SigFilename: String; const VerifyResult: TISSigVerifySignatureResult)
+    begin
+      var VerifyError: TISSigVerifySignatureError;
+      case VerifyResult of
+        vsrMalformed, vsrBadSignature: VerifyError := vseMalformedOrBadSignature;
+        vsrKeyNotFound: VerifyError := vseKeyNotFound;
+      else
+        VerifyError := vseUnknownVerifyResult;
+      end;
+      ISSigVerifyError(VerifyError, SetupMessages[msgSourceIsCorrupted]);
+    end
+  ) then
+    InternalError('Unexpected ISSigVerifySignature result');
+  if Int64(SourceF.Size) <> ExpectedFileSize then
+    ISSigVerifyError(vseFileSizeIncorrect, SetupMessages[msgSourceIsCorrupted]);
+end;
+
+const
+  ISSigVerificationSuccessfulLogMessage = 'ISSig verification successful.';
+
 procedure CopySourceFileToDestFile(const SourceF, DestF: TFile;
 procedure CopySourceFileToDestFile(const SourceF, DestF: TFile;
-  const ISSigVerify: Boolean; [ref] const ISSigAvailableKeys: TArrayOfECDSAKey;
-  const ISSigAllowedKeys: AnsiString; const ISSigSourceFilename: String;
+  const ISSigVerify: Boolean; const ISSigAllowedKeys: AnsiString; const ISSigSourceFilename: String;
   const AExpectedSize: Integer64);
   const AExpectedSize: Integer64);
 { Copies all bytes from SourceF to DestF, incrementing process meter as it
 { Copies all bytes from SourceF to DestF, incrementing process meter as it
   goes. Assumes file pointers of both are 0. }
   goes. Assumes file pointers of both are 0. }
-const
-  ISSigMissingFile = 'Signature file does not exist';
-  ISSigMalformedOrBadSignature = 'Malformed or bad signature';
-  ISSigKeyNotFound = 'No matching key found';
-  ISSigUnknownVerifyResult  = 'Unknown verify result';
-  ISSigFileSizeIncorrect = 'File size incorrect';
-  ISSigFileHashIncorrect = 'File hash incorrect';
 var
 var
   BytesLeft: Integer64;
   BytesLeft: Integer64;
   NewProgress: Integer64;
   NewProgress: Integer64;
@@ -278,32 +311,8 @@ var
 begin
 begin
   var ExpectedFileHash: TSHA256Digest;
   var ExpectedFileHash: TSHA256Digest;
   if ISSigVerify then begin
   if ISSigVerify then begin
-    var ExpectedFileSize: Int64;
-    if not ISSigVerifySignature(ISSigSourceFilename,
-      GetISSigAllowedKeys(ISSigAvailableKeys, ISSigAllowedKeys),
-      ExpectedFileSize, ExpectedFileHash,
-      nil,
-      procedure(const Filename, SigFilename: String)
-      begin
-        ISSigVerifyError(ISSigMissingFile, FmtSetupMessage1(msgSourceDoesntExist, SigFilename));
-      end,
-      procedure(const SigFilename: String; const VerifyResult: TISSigVerifySignatureResult)
-      begin
-        var VerifyResultAsString: String;
-        case VerifyResult of
-          vsrMalformed, vsrBadSignature: VerifyResultAsString := ISSigMalformedOrBadSignature;
-          vsrKeyNotFound: VerifyResultAsString := ISSigKeyNotFound;
-        else
-          VerifyResultAsString := ISSigUnknownVerifyResult;
-        end;
-        ISSigVerifyError(VerifyResultAsString, SetupMessages[msgSourceIsCorrupted]);
-      end
-    ) then
-      InternalError('Unexpected ISSigVerifySignature result');
-    if Int64(SourceF.Size) <> ExpectedFileSize then
-      ISSigVerifyError(ISSigFileSizeIncorrect, SetupMessages[msgSourceIsCorrupted]);
+    DoISSigVerify(SourceF, ISSigSourceFilename, ISSigAllowedKeys, ExpectedFileHash);
     { ExpectedFileHash checked below after copy }
     { ExpectedFileHash checked below after copy }
-
     SHA256Init(Context);
     SHA256Init(Context);
   end;
   end;
 
 
@@ -344,8 +353,8 @@ begin
 
 
   if ISSigVerify then begin
   if ISSigVerify then begin
     if not SHA256DigestsEqual(SHA256Final(Context), ExpectedFileHash) then
     if not SHA256DigestsEqual(SHA256Final(Context), ExpectedFileHash) then
-      ISSigVerifyError(ISSigFileHashIncorrect, SetupMessages[msgSourceIsCorrupted]);
-    Log('ISSig verification successful.');
+      ISSigVerifyError(vseFileHashIncorrect, SetupMessages[msgSourceIsCorrupted]);
+    Log(ISSigVerificationSuccessfulLogMessage);
   end;
   end;
 
 
   { In case the source file was shorter than we thought it was, bump the
   { In case the source file was shorter than we thought it was, bump the
@@ -1520,10 +1529,10 @@ var
                 LastOperation := SetupMessages[msgErrorCopying];
                 LastOperation := SetupMessages[msgErrorCopying];
                 if Assigned(CurFileLocation) then
                 if Assigned(CurFileLocation) then
                   CopySourceFileToDestFile(SourceF, DestF, False,
                   CopySourceFileToDestFile(SourceF, DestF, False,
-                    [], '', '', CurFileLocation^.OriginalSize)
+                    '', '', CurFileLocation^.OriginalSize)
                 else
                 else
                   CopySourceFileToDestFile(SourceF, DestF, foISSigVerify in CurFile^.Options,
                   CopySourceFileToDestFile(SourceF, DestF, foISSigVerify in CurFile^.Options,
-                    ISSigAvailableKeys, CurFile^.ISSigAllowedKeys, SourceFile, AExternalSize);
+                    CurFile^.ISSigAllowedKeys, SourceFile, AExternalSize);
               finally
               finally
                 SourceF.Free;
                 SourceF.Free;
               end;
               end;
@@ -1923,58 +1932,75 @@ var
         InternalError('Unexpected custom DestName');
         InternalError('Unexpected custom DestName');
       const DestDir = ExpandConst(CurFile^.DestName);
       const DestDir = ExpandConst(CurFile^.DestName);
 
 
-      {!!!} {foISSigVerify}
+      var ISSigVerifySourceF: TFile := nil;
+      try
+        var FindData: TWin32FindData;
+        var H: TArchiveFindHandle := INVALID_HANDLE_VALUE;
+        var Failed: String;
+        repeat
+          try
+            if foISSigVerify in CurFile^.Options then begin
+              if ISSigVerifySourceF = nil then
+                ISSigVerifySourceF := TFileRedir.Create(DisableFsRedir, ArchiveFilename, fdOpenExisting, faRead, fsRead);
+              var ExpectedFileHash: TSHA256Digest;
+              DoISSigVerify(ISSigVerifySourceF, ArchiveFilename, CurFile^.ISSigAllowedKeys,
+                ExpectedFileHash);
+              { Can't get the SHA-256 while extracting so need to get and check it now }
+              const FileHash = GetSHA256OfFile(DisableFsRedir, ArchiveFilename);
+              if not SHA256DigestsEqual(FileHash, ExpectedFileHash) then
+                ISSigVerifyError(vseFileHashIncorrect, SetupMessages[msgSourceIsCorrupted]);
+              Log(ISSigVerificationSuccessfulLogMessage);
+              { Keeping ISSigVerifySourceF open until extraction has completed }
+            end;
 
 
-      var FindData: TWin32FindData;
-      var H: TArchiveFindHandle := INVALID_HANDLE_VALUE;
-      var Failed: String;
-      repeat
-        try
-          H := ArchiveFindFirstFileRedir(DisableFsRedir, ArchiveFilename, DestDir,
-            Password, foRecurseSubDirsExternal in CurFile^.Options, True, FindData);
-          Failed := '';
-        except
-          if ExceptObject is EAbort then
-            raise;
-          Failed := GetExceptMessage;
-        end;
-      until (Failed = '') or
-            AbortRetryIgnoreTaskDialogMsgBox(
-              ArchiveFilename + SNewLine2 + SetupMessages[msgErrorReadingSource] + SNewLine + Failed,
-              [SetupMessages[msgAbortRetryIgnoreRetry], SetupMessages[msgFileAbortRetryIgnoreSkipNotRecommended], SetupMessages[msgAbortRetryIgnoreCancel]]);
-      if H <> INVALID_HANDLE_VALUE then begin
-        try
-          repeat
-            if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
+            H := ArchiveFindFirstFileRedir(DisableFsRedir, ArchiveFilename, DestDir,
+              Password, foRecurseSubDirsExternal in CurFile^.Options, True, FindData);
+            Failed := '';
+          except
+            if ExceptObject is EAbort then
+              raise;
+            Failed := GetExceptMessage;
+          end;
+        until (Failed = '') or
+              AbortRetryIgnoreTaskDialogMsgBox(
+                ArchiveFilename + SNewLine2 + SetupMessages[msgErrorReadingSource] + SNewLine + Failed,
+                [SetupMessages[msgAbortRetryIgnoreRetry], SetupMessages[msgFileAbortRetryIgnoreSkipNotRecommended], SetupMessages[msgAbortRetryIgnoreCancel]]);
+        if H <> INVALID_HANDLE_VALUE then begin
+          try
+            repeat
+              if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
 
 
-              if IsExcluded(FindData.cFileName, Excludes) then
-                Continue;
+                if IsExcluded(FindData.cFileName, Excludes) then
+                  Continue;
 
 
-              var SourceFile := IntToStr(H);
-              const DestFile = DestDir + FindData.cFileName;
-              var Size: Integer64;
-              Size.Hi := FindData.nFileSizeHigh;
-              Size.Lo := FindData.nFileSizeLow;
-              if Compare64(Size, ExpectedBytesLeft) > 0 then begin
-                { Don't allow the progress bar to overflow if the size of the
-                  files is greater than when we last checked }
-                Size := ExpectedBytesLeft;
+                var SourceFile := IntToStr(H);
+                const DestFile = DestDir + FindData.cFileName;
+                var Size: Integer64;
+                Size.Hi := FindData.nFileSizeHigh;
+                Size.Lo := FindData.nFileSizeLow;
+                if Compare64(Size, ExpectedBytesLeft) > 0 then begin
+                  { Don't allow the progress bar to overflow if the size of the
+                    files is greater than when we last checked }
+                  Size := ExpectedBytesLeft;
+                end;
+                ProcessFileEntry(CurFile, DisableFsRedir, SourceFile, DestFile,
+                  nil, Size, ConfirmOverwriteOverwriteAll, PromptIfOlderOverwriteAll,
+                  WarnedPerUserFonts, @FindData.ftLastWriteTime);
+                Dec6464(ExpectedBytesLeft, Size);
+              end else if foCreateAllSubDirs in CurFile.Options then begin
+                var Flags: TMakeDirFlags := [];
+                if foUninsNeverUninstall in CurFile^.Options then Include(Flags, mdNoUninstall);
+                if foDeleteAfterInstall in CurFile^.Options then Include(Flags, mdDeleteAfterInstall);
+                MakeDir(DisableFsRedir, DestDir + FindData.cFileName, Flags);
+                Result := True;
               end;
               end;
-              ProcessFileEntry(CurFile, DisableFsRedir, SourceFile, DestFile,
-                nil, Size, ConfirmOverwriteOverwriteAll, PromptIfOlderOverwriteAll,
-                WarnedPerUserFonts, @FindData.ftLastWriteTime);
-              Dec6464(ExpectedBytesLeft, Size);
-            end else if foCreateAllSubDirs in CurFile.Options then begin
-              var Flags: TMakeDirFlags := [];
-              if foUninsNeverUninstall in CurFile^.Options then Include(Flags, mdNoUninstall);
-              if foDeleteAfterInstall in CurFile^.Options then Include(Flags, mdDeleteAfterInstall);
-              MakeDir(DisableFsRedir, DestDir + FindData.cFileName, Flags);
-              Result := True;
-            end;
-          until not ArchiveFindNextFile(H, FindData);
-        finally
-          ArchiveFindClose(H);
+            until not ArchiveFindNextFile(H, FindData);
+          finally
+            ArchiveFindClose(H);
+          end;
         end;
         end;
+      finally
+        ISSigVerifySourceF.Free;
       end;
       end;
     end;
     end;