Add download+issigverify support. This finishes the branch, only whatsnew todo + making a new fresh messages commit + test username/password support.

This commit is contained in:
Martijn Laan 2025-06-08 20:27:45 +02:00
parent 5b4385bfa7
commit 813d024dd4
No known key found for this signature in database
GPG Key ID: E2DD568CF6098F6A
7 changed files with 44 additions and 10 deletions

View File

@ -70,6 +70,7 @@ function ISSigCalcStreamHash(const AStream: TStream): TSHA256Digest;
var
ISSigExt: String = '.issig';
ISSigEstimatedSize: Integer = 330;
implementation

View File

@ -1668,6 +1668,12 @@ ExternalSize: 1048576; Flags: external
<p>This parameter is ignored if the <tt>extractarchive</tt> flag isn't also specified.</p>
</param>
<param name="DownloadISSigSource">
<p>Specifies the URL of the .issig signature file which should be downloaded. This file is used to verify the file downloaded from the URL specified by the <tt>Source</tt> parameter.</p>
<p>This parameter is ignored if the <tt>download</tt> and <tt>issigverify</tt> flags aren't both also specified.</p>
<p>If this parameter is not set but both these flags are used, Setup will instead append ".issig" (without quotes) to the path portion of the URL specified by the <tt>Source</tt> parameter. It will then use the result as the URL to download the .issig signature file from.</p>
</param>
<param name="DownloadUserName">
<p>Specifies the basic authentication username to use for the file download.</p>
<p>This parameter is ignored if the <tt>download</tt> flag isn't also specified.</p>

View File

@ -1862,7 +1862,7 @@ end;</pre>
<name>DownloadTemporaryFileWithISSigVerify</name>
<prototype>function DownloadTemporaryFileWithISSigVerify(const Url, ISSigUrl, BaseName: String; const AllowedKeysRuntimeIDs: TStringList; const OnDownloadProgress: TOnDownloadProgress): Int64;</prototype>
<description><p>Like <link topic="isxfunc_DownloadTemporaryFile">DownloadTemporaryFile</link>, but downloads an .issig signature file first from the specified second URL and uses it to verify the main file downloaded from the first URL.</p>
<p>If the second URL is an empty string, Setup will instead append ".issig" (without quotes) to the path portion of the first URL and use the result as the URL to download the .issig signature file from.</p>
<p>If the second URL is an empty string, Setup will instead append ".issig" (without quotes) to the path portion of the first URL. It will then use the result as the URL to download the .issig signature file from.</p>
<p>Verification uses 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>.</p>
<p>An exception will be raised if there was an error. Otherwise, returns the number of bytes downloaded for the main file from the first URL. Returns 0 if the main file was already downloaded and still verified.</p></description>
<seealso><p><link topic="isxfunc_DownloadTemporaryFile">DownloadTemporaryFile</link><br/>

View File

@ -4670,7 +4670,7 @@ type
paPermissions, paFontInstall, paExcludes, paExternalSize, paExtractArchivePassword,
paStrongAssemblyName, paISSigAllowedKeys, paComponents, paTasks, paLanguages,
paCheck, paBeforeInstall, paAfterInstall, paMinVersion, paOnlyBelowVersion,
paDownloadUserName, paDownloadPassword);
paDownloadISSigSource, paDownloadUserName, paDownloadPassword);
const
ParamFilesSource = 'Source';
ParamFilesDestDir = 'DestDir';
@ -4684,6 +4684,7 @@ const
ParamFilesExtractArchivePassword = 'ExtractArchivePassword';
ParamFilesStrongAssemblyName = 'StrongAssemblyName';
ParamFilesISSigAllowedKeys = 'ISSigAllowedKeys';
ParamFilesDownloadISSigSource = 'DownloadISSigSource';
ParamFilesDownloadUserName = 'DownloadUserName';
ParamFilesDownloadPassword = 'DownloadPassword';
ParamInfo: array[TParam] of TParamInfo = (
@ -4700,6 +4701,7 @@ const
(Name: ParamFilesExtractArchivePassword; Flags: []),
(Name: ParamFilesStrongAssemblyName; Flags: [piNoEmpty]),
(Name: ParamFilesISSigAllowedKeys; Flags: [piNoEmpty]),
(Name: ParamFilesDownloadISSigSource; Flags: []),
(Name: ParamFilesDownloadUserName; Flags: [piNoEmpty]),
(Name: ParamFilesDownloadPassword; Flags: [piNoEmpty]),
(Name: ParamCommonComponents; Flags: []),
@ -5350,6 +5352,9 @@ begin
Include(Options, foExternalSizePreset);
end;
{ DownloadISSigSource }
DownloadISSigSource := Values[paDownloadISSigSource].Data;
{ DownloadUserName }
DownloadUserName := Values[paDownloadUserName].Data;

View File

@ -32,6 +32,7 @@ procedure ExtractTemporaryFile(const BaseName: String);
function ExtractTemporaryFiles(const Pattern: String): Integer;
function DownloadFile(const Url, CustomUserName, CustomPassword: String;
const DestF: TFile; const ISSigVerify: Boolean; const ISSigAllowedKeys: AnsiString;
const ISSigSourceFilename: String;
const OnSimpleDownloadProgress: TOnSimpleDownloadProgress): Int64;
function DownloadTemporaryFile(const Url, BaseName, RequiredSHA256OfFile: String;
const ISSigVerify: Boolean; const ISSigAllowedKeys: AnsiString;
@ -1561,16 +1562,35 @@ var
not (foDontVerifyChecksum in CurFile^.Options));
end
else if foExtractArchive in CurFile^.Options then begin
{ Extract a file from archive. Note: foISSigVerify for archive has
{ Extract a file from archive. Note: ISSigVerify for archive has
already been handled by RecurseExternalArchiveCopyFiles. }
LastOperation := SetupMessages[msgErrorExtracting];
ArchiveFindExtract(StrToInt(SourceFile), DestF, ExtractorProgressProc);
end
else if foDownload in CurFile^.Options then begin
{ Download a file }
{ Download a file with or without ISSigVerify. Note: estimate of
extra .issig size has already been added to CurFile's ExternalSize. }
LastOperation := SetupMessages[msgErrorDownloading];
DownloadFile(SourceFile, CurFile^.DownloadUserName, CurFile^.DownloadPassword,
DestF, foISSigVerify in CurFile^.Options, CurFile^.ISSigAllowedKeys, ExtractorProgressProc);
if foISSigVerify in CurFile^.Options then begin
const ISSigTempFile = TempFile + ISSigExt;
const ISSigDestF = TFileRedir.Create(DisableFsRedir, ISSigTempFile, fdCreateAlways, faReadWrite, fsNone);
try
{ Download the .issig file }
const ISSigUrl = GetISSigUrl(SourceFile, CurFile^.DownloadISSigSource);
DownloadFile(ISSigUrl, CurFile^.DownloadUserName, CurFile^.DownloadPassword,
ISSigDestF, False, '', '', ExtractorProgressProc);
FreeAndNil(ISSigDestF);
{ Download and verify the actual file }
DownloadFile(SourceFile, CurFile^.DownloadUserName, CurFile^.DownloadPassword,
DestF, True, CurFile^.ISSigAllowedKeys, TempFile, ExtractorProgressProc);
finally
ISSigDestF.Free;
{ Delete the .issig file }
DeleteFileRedir(DisableFsRedir, ISSigTempFile);
end;
end else
DownloadFile(SourceFile, CurFile^.DownloadUserName, CurFile^.DownloadPassword,
DestF, False, '', '', ExtractorProgressProc);
end
else begin
{ Copy a duplicated non-external file, or an external file }
@ -3768,9 +3788,9 @@ end;
function DownloadFile(const Url, CustomUserName, CustomPassword: String;
const DestF: TFile; const ISSigVerify: Boolean; const ISSigAllowedKeys: AnsiString;
const ISSigSourceFilename: String;
const OnSimpleDownloadProgress: TOnSimpleDownloadProgress): Int64;
var
DestFile: String;
HandleStream: THandleStream;
HTTPDataReceiver: THTTPDataReceiver;
HTTPClient: THTTPClient;
@ -3824,7 +3844,7 @@ begin
{ Check .issig if specified, otherwise check everything else we can check }
if ISSigVerify then begin
var ExpectedFileHash: TSHA256Digest;
DoISSigVerify(DestF, nil, DestFile, ISSigAllowedKeys, ExpectedFileHash);
DoISSigVerify(DestF, nil, ISSigSourceFilename, ISSigAllowedKeys, ExpectedFileHash);
const FileHash = GetSHA256OfFile(DestF);
if not SHA256DigestsEqual(FileHash, ExpectedFileHash) then
ISSigVerifyError(vseFileHashIncorrect, SetupMessages[msgSourceIsCorrupted]);

View File

@ -3550,6 +3550,8 @@ begin
(ESevenZipError). Also see EnumFiles. }
end;
end;
if (foDownload in Options) and (foISSigVerify in Options) then
Inc6464(ExternalSize, Integer64(UInt64(ISSigEstimatedSize)));
if Components = '' then { no types or a file that doesn't belong to any component }
if (Tasks = '') and (Check = '') then {don't count tasks or scripted entries}
Inc6464(MinimumSpace, ExternalSize);

View File

@ -227,14 +227,14 @@ type
PublicX, PublicY, RuntimeID: String;
end;
const
SetupFileEntryStrings = 14;
SetupFileEntryStrings = 15;
SetupFileEntryAnsiStrings = 1;
type
PSetupFileEntry = ^TSetupFileEntry;
TSetupFileEntry = packed record
SourceFilename, DestName, InstallFontName, StrongAssemblyName, Components,
Tasks, Languages, Check, AfterInstall, BeforeInstall, Excludes,
DownloadUserName, DownloadPassword, ExtractArchivePassword: String;
DownloadISSigSource, DownloadUserName, DownloadPassword, ExtractArchivePassword: String;
ISSigAllowedKeys: AnsiString;
MinVersion, OnlyBelowVersion: TSetupVersionData;
LocationEntry: Integer;