diff --git a/Components/ISSigFunc.pas b/Components/ISSigFunc.pas index e80c1ae5..04b2acb2 100644 --- a/Components/ISSigFunc.pas +++ b/Components/ISSigFunc.pas @@ -70,6 +70,7 @@ function ISSigCalcStreamHash(const AStream: TStream): TSHA256Digest; var ISSigExt: String = '.issig'; + ISSigEstimatedSize: Integer = 330; implementation diff --git a/ISHelp/isetup.xml b/ISHelp/isetup.xml index 925cabb8..f79a8f15 100644 --- a/ISHelp/isetup.xml +++ b/ISHelp/isetup.xml @@ -1668,6 +1668,12 @@ ExternalSize: 1048576; Flags: external
This parameter is ignored if the extractarchive flag isn't also specified.
+ +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 Source parameter.
+This parameter is ignored if the download and issigverify flags aren't both also specified.
+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 Source parameter. It will then use the result as the URL to download the .issig signature file from.
+ +Specifies the basic authentication username to use for the file download.
This parameter is ignored if the download flag isn't also specified.
diff --git a/ISHelp/isxfunc.xml b/ISHelp/isxfunc.xml index eed631d7..0504edf1 100644 --- a/ISHelp/isxfunc.xml +++ b/ISHelp/isxfunc.xml @@ -1862,7 +1862,7 @@ end;Like DownloadTemporaryFile, 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.
-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.
+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.
Verification uses the specified allowed keys, looked up using [ISSigKeys] section parameter RuntimeID. To allow all keys set AllowedKeysRuntimeIDs to nil.
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.
DownloadTemporaryFile
diff --git a/Projects/Src/Compiler.SetupCompiler.pas b/Projects/Src/Compiler.SetupCompiler.pas
index 536d0d14..4f2e76b1 100644
--- a/Projects/Src/Compiler.SetupCompiler.pas
+++ b/Projects/Src/Compiler.SetupCompiler.pas
@@ -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;
diff --git a/Projects/Src/Setup.Install.pas b/Projects/Src/Setup.Install.pas
index 6a05bbb6..b8550959 100644
--- a/Projects/Src/Setup.Install.pas
+++ b/Projects/Src/Setup.Install.pas
@@ -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]);
diff --git a/Projects/Src/Setup.MainFunc.pas b/Projects/Src/Setup.MainFunc.pas
index 4a369809..ea7a0122 100644
--- a/Projects/Src/Setup.MainFunc.pas
+++ b/Projects/Src/Setup.MainFunc.pas
@@ -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);
diff --git a/Projects/Src/Shared.Struct.pas b/Projects/Src/Shared.Struct.pas
index 84605683..4e2e17de 100644
--- a/Projects/Src/Shared.Struct.pas
+++ b/Projects/Src/Shared.Struct.pas
@@ -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;