2
0
Эх сурвалжийг харах

Remove catch all from LoadTrustedLibrary as well. This makes it show the failure reason in error messages instead of just saying 'not trusted'.

Martijn Laan 4 сар өмнө
parent
commit
8d86c33409

+ 7 - 3
Components/ScintInt.pas

@@ -1358,14 +1358,18 @@ const
 
 var
   IsscintLibrary: HMODULE;
-  IsscintLibraryTrustFail: Boolean;
+
+procedure InitIsscintLibrary;
 
 implementation
 
 uses
   PathFunc, TrustFunc;
 
-initialization
+procedure InitIsscintLibrary;
+begin
   var FileName := AddBackslash(PathExtractPath(ParamStr(0))) + IsscintDLL;
-  IsscintLibrary := LoadTrustedLibrary(PChar(FileName), IsscintLibraryTrustFail);
+  IsscintLibrary := LoadTrustedLibrary(PChar(FileName));
+end;
+
 end.

+ 52 - 62
Components/TrustFunc.pas

@@ -13,97 +13,87 @@ unit TrustFunc;
 
 interface
 
-function TrustedFileExists(const FileName: String; const CheckExists: Boolean = True): Boolean;
-function LoadTrustedLibrary(const FileName: String; out TrustFail: Boolean; const TrustAllOnDebug: Boolean = False): HMODULE;
+procedure CheckFileTrust(const FileName: String; const CheckExists: Boolean = True);
+function LoadTrustedLibrary(const FileName: String; const TrustAllOnDebug: Boolean = False): HMODULE;
 
 implementation
 
 uses
   Winapi.Windows, System.SysUtils {$IFNDEF TRUSTALL}, System.Classes, ECDSA, SHA256, ISSigFunc {$ENDIF};
 
-function TrustedFileExists(const FileName: String; const CheckExists: Boolean): Boolean;
+procedure CheckFileTrust(const FileName: String; const CheckExists: Boolean);
 begin
   if CheckExists then begin
     var Attr := GetFileAttributes(PChar(FileName));
-    Result := (Attr <> INVALID_FILE_ATTRIBUTES) and (Attr and faDirectory = 0);
-  end else
-    Result := True;
+    if (Attr = INVALID_FILE_ATTRIBUTES) or (Attr and faDirectory <> 0) then
+      raise Exception.CreateFmt('File "%s" does not exist.',
+        [FileName]);
+  end;
 {$IFNDEF TRUSTALL}
-  if Result then begin
-    var AllowedPublicKey1Text, AllowedPublicKey2Text: String;
-    {$I TrustFunc.AllowedPublicKeys.inc}
-    var Key1: TECDSAKey := nil;
-    var Key2: TECDSAKey := nil;
-    try
-      Key1 := TECDSAKey.Create;
-      if ISSigImportKeyText(Key1, AllowedPublicKey1Text, False) <> ikrSuccess then
+  var AllowedPublicKey1Text, AllowedPublicKey2Text: String;
+  {$I TrustFunc.AllowedPublicKeys.inc}
+  var Key1: TECDSAKey := nil;
+  var Key2: TECDSAKey := nil;
+  try
+    Key1 := TECDSAKey.Create;
+    if ISSigImportKeyText(Key1, AllowedPublicKey1Text, False) <> ikrSuccess then
+      raise Exception.Create('ISSigImportKeyText failed');
+    if AllowedPublicKey2Text <> '' then begin
+      Key2 := TECDSAKey.Create;
+      if ISSigImportKeyText(Key2, AllowedPublicKey2Text, False) <> ikrSuccess then
         raise Exception.Create('ISSigImportKeyText failed');
-      if AllowedPublicKey2Text <> '' then begin
-        Key2 := TECDSAKey.Create;
-        if ISSigImportKeyText(Key2, AllowedPublicKey2Text, False) <> ikrSuccess then
-          raise Exception.Create('ISSigImportKeyText failed');
-      end;
+    end;
 
-      var AllowedKeys: array of TECDSAKey;
-      if Key2 <> nil then
-        AllowedKeys := [Key1, Key2]
-      else
-        AllowedKeys := [Key1];
+    var AllowedKeys: array of TECDSAKey;
+    if Key2 <> nil then
+      AllowedKeys := [Key1, Key2]
+    else
+      AllowedKeys := [Key1];
 
-      const SigFileName = FileName + '.issig';
-      const SigText = ISSigLoadTextFromFile(SigFileName);
+    const SigFileName = FileName + '.issig';
+    const SigText = ISSigLoadTextFromFile(SigFileName);
 
-      var ExpectedFileSize: Int64;
-      var ExpectedFileHash: TSHA256Digest;
-      if ISSigVerifySignatureText(AllowedKeys, SigText, ExpectedFileSize,
-         ExpectedFileHash) <> vsrSuccess then
-        raise Exception.CreateFmt('Signature file "%s" is not valid',
-          [SigFileName]);
+    var ExpectedFileSize: Int64;
+    var ExpectedFileHash: TSHA256Digest;
+    if ISSigVerifySignatureText(AllowedKeys, SigText, ExpectedFileSize,
+       ExpectedFileHash) <> vsrSuccess then
+      raise Exception.CreateFmt('Signature file "%s" is not valid',
+        [SigFileName]);
 
-      const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
-      try
-        if F.Size <> ExpectedFileSize then
-          raise Exception.CreateFmt('File "%s" is not trusted (incorrect size).',
-            [FileName]);
-        if not SHA256DigestsEqual(ISSigCalcStreamHash(F), ExpectedFileHash) then
-          raise Exception.CreateFmt('File "%s" is not trusted (incorrect hash).',
-            [FileName]);
-      finally
-        F.Free;
-      end;
+    const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+    try
+      if F.Size <> ExpectedFileSize then
+        raise Exception.CreateFmt('File "%s" is not trusted (incorrect size).',
+          [FileName]);
+      if not SHA256DigestsEqual(ISSigCalcStreamHash(F), ExpectedFileHash) then
+        raise Exception.CreateFmt('File "%s" is not trusted (incorrect hash).',
+          [FileName]);
     finally
-      Key2.Free;
-      Key1.Free;
+      F.Free;
     end;
+  finally
+    Key2.Free;
+    Key1.Free;
   end;
 {$ENDIF}
 end;
 
-function LoadTrustedLibrary(const FileName: String; out TrustFail: Boolean; const TrustAllOnDebug: Boolean): HMODULE;
+function LoadTrustedLibrary(const FileName: String; const TrustAllOnDebug: Boolean): HMODULE;
 begin
-  TrustFail := False;
 {$IFDEF DEBUG}
   if TrustAllOnDebug then begin
     Result := SafeLoadLibrary(PChar(FileName), SEM_NOOPENFILEERRORBOX);
     Exit;
   end;
 {$ENDIF}
+  { First open a temporary regular handle to the library to protect it from changes
+    between the trust check and the load }
+  const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
   try
-    { First open a temporary regular handle to the library to protect it from changes
-      between the trust check and the load }
-    const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
-    try
-      if TrustedFileExists(FileName, False) then
-        Result := SafeLoadLibrary(PChar(FileName), SEM_NOOPENFILEERRORBOX)
-      else begin
-        TrustFail := True;
-        Result := 0;
-      end;
-    finally
-      F.Free;
-    end;
-  except
-    Result := 0;
+    CheckFileTrust(FileName, False);
+    Result := SafeLoadLibrary(PChar(FileName), SEM_NOOPENFILEERRORBOX)
+  finally
+    F.Free;
   end;
 end;
 

+ 20 - 9
Projects/Compil32.dpr

@@ -13,7 +13,6 @@ uses
   SafeDLLPath in '..\Components\SafeDLLPath.pas',
   Windows,
   SysUtils,
-  StrUtils,
   Forms,
   PathFunc in '..\Components\PathFunc.pas',
   TrustFunc in '..\Components\TrustFunc.pas',
@@ -207,17 +206,29 @@ end;
 
 begin
   {$IFNDEF STATICCOMPILER}
-  if ISCmplrLibrary = 0 then begin
-    MessageBox(0, PChar(Format('Could not load %s%s.',
-      [ISCmplrDLL, IfThen(ISCmplrLibraryTrustFail, ' (not trusted)', '')])), nil, MB_OK or MB_ICONSTOP);
-    Halt(3);
+  try
+    InitISCmplrLibrary;
+    if ISCmplrLibrary = 0 then
+      raise Exception.Create(Win32ErrorString(GetLastError));
+  except on E: Exception do
+    begin
+      MessageBox(0, PChar(Format('Could not load %s: %s.',
+        [ISCmplrDLL, E.Message])), nil, MB_OK or MB_ICONSTOP);
+      Halt(3);
+    end;
   end;
   {$ENDIF}
 
-  if IsscintLibrary = 0 then begin
-    MessageBox(0, PChar(Format('Could not load %s%s.' {$IFDEF DEBUG} + #13#10#13#10'Did you run Projects\Bin\synch-isfiles.bat as instructed in README.md?' {$ENDIF} ,
-      [IsscintDLL, IfThen(IsscintLibraryTrustFail, ' (not trusted)', '')])), nil, MB_OK or MB_ICONSTOP);
-    Halt(4);
+  try
+    InitIsscintLibrary;
+    if IsscintLibrary = 0 then
+      raise Exception.Create(Win32ErrorString(GetLastError));
+  except on E: Exception do
+    begin
+      MessageBox(0, PChar(Format('Could not load %s: %s' {$IFDEF DEBUG} + #13#10#13#10'Did you run Projects\Bin\synch-isfiles.bat as instructed in README.md?' {$ENDIF},
+        [IsscintDLL, E.Message])), nil, MB_OK or MB_ICONSTOP);
+      Halt(4);
+    end;
   end;
 
   {$IFDEF DEBUG}

+ 9 - 4
Projects/ISCC.dpr

@@ -20,7 +20,6 @@ uses
   SafeDLLPath in '..\Components\SafeDLLPath.pas',
   Windows,
   SysUtils,
-  StrUtils,
   Classes,
   {$IFDEF STATICCOMPILER} Compiler.Compile, {$ENDIF}
   PathFunc in '..\Components\PathFunc.pas',
@@ -566,9 +565,15 @@ begin
   end;
 
   {$IFNDEF STATICCOMPILER}
-  if ISCmplrLibrary = 0 then begin
-    WriteStdErr(Format('Could not load %s%s.', [ISCmplrDLL, IfThen(ISCmplrLibraryTrustFail, ' (not trusted)', '')]), True);
-    Halt(1);
+  try
+    InitISCmplrLibrary;
+    if ISCmplrLibrary = 0 then
+      raise Exception.Create(Win32ErrorString(GetLastError));
+  except on E: Exception do
+    begin
+      WriteStdErr(Format('Could not load %s: %s.', [ISCmplrDLL, E.Message]), True);
+      Halt(1);
+    end;
   end;
   Ver := ISDllGetVersion;
   {$ELSE}

+ 18 - 24
Projects/Src/Compiler.SetupCompiler.pas

@@ -502,6 +502,20 @@ begin
   end;
 end;
 
+function LoadCompilerDLL(const Filename: String; const TrustAllOnDebug: Boolean = False): HMODULE;
+begin
+  try
+    Result := LoadTrustedLibrary(FileName, TrustAllOnDebug);
+    if Result = 0 then
+      raise Exception.Create(Win32ErrorString(GetLastError));
+  except on E: Exception do
+    begin
+      TSetupCompiler.AbortCompileFmt('Failed to load %s: %s.', [PathExtractName(Filename), E.Message]);
+      Result := 0; //silence compiler
+    end;
+  end;
+end;
+
 procedure TSetupCompiler.InitPreprocessor;
 begin
   if PreprocessorInitialized then
@@ -509,12 +523,7 @@ begin
 {$IFNDEF STATICPREPROC}
   var Filename := CompilerDir + 'ISPP.dll';
   if NewFileExists(Filename) then begin
-    var TrustFail: Boolean;
-    var M := LoadTrustedLibrary(Filename, TrustFail, True);
-    if TrustFail then
-      AbortCompile('Failed to load ISPP.dll (not trusted)')
-    else if M = 0 then
-      AbortCompileFmt('Failed to load ISPP.dll (%d)', [GetLastError]);
+    var M := LoadCompilerDLL(Filename, True);
     PreprocessScriptProc := GetProcAddress(M, 'ISPreprocessScriptW');
     if not Assigned(PreprocessScriptProc) then
       AbortCompile('Failed to get address of functions in ISPP.dll');
@@ -530,12 +539,7 @@ begin
   if ZipInitialized then
     Exit;
   var Filename := CompilerDir + 'iszlib.dll';
-  var TrustFail: Boolean;
-  var M := LoadTrustedLibrary(Filename, TrustFail);
-  if TrustFail then
-    AbortCompile('Failed to load iszlib.dll (not trusted)')
-  else if M = 0 then
-    AbortCompileFmt('Failed to load iszlib.dll (%d)', [GetLastError]);
+  var M := LoadCompilerDLL(Filename);
   if not ZlibInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in iszlib.dll');
   ZipInitialized := True;
@@ -546,12 +550,7 @@ begin
   if BzipInitialized then
     Exit;
   var Filename := CompilerDir + 'isbzip.dll';
-  var TrustFail: Boolean;
-  var M := LoadTrustedLibrary(Filename, TrustFail);
-  if TrustFail then
-    AbortCompile('Failed to load isbzip.dll (not trusted)')
-  else if M = 0 then
-    AbortCompileFmt('Failed to load isbzip.dll (%d)', [GetLastError]);
+  var M := LoadCompilerDLL(Filename);
   if not BZInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in isbzip.dll');
   BzipInitialized := True;
@@ -562,12 +561,7 @@ begin
   if LZMAInitialized then
     Exit;
   var Filename := CompilerDir + 'islzma.dll';
-  var TrustFail: Boolean;
-  var M := LoadTrustedLibrary(Filename, TrustFail);
-  if TrustFail then
-    AbortCompile('Failed to load islzma.dll (not trusted)')
-  else if M = 0 then
-    AbortCompileFmt('Failed to load islzma.dll (%d)', [GetLastError]);
+  var M := LoadCompilerDLL(Filename);
   if not LZMAInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in islzma.dll');
   LZMAInitialized := True;

+ 7 - 3
Projects/Src/Shared.CompilerInt.pas

@@ -19,7 +19,6 @@ const
 
 var
   ISCmplrLibrary: HMODULE;
-  ISCmplrLibraryTrustFail: Boolean;
 
 { The ISDllCompileScript function begins compilation of a script. See the above
   description of the TCompileScriptParams record. Return value is one of the
@@ -30,6 +29,8 @@ var
   contains information about the compiler version. }
   ISDllGetVersion: function: PCompilerVersionInfo; stdcall;
 
+procedure InitISCmplrLibrary;
+
 implementation
 
 uses
@@ -37,9 +38,10 @@ uses
   SysUtils,
   PathFunc, TrustFunc;
 
-initialization
+procedure InitISCmplrLibrary;
+begin
   var FileName := AddBackslash(PathExtractPath(ParamStr(0))) + ISCmplrDLL;
-  ISCmplrLibrary := LoadTrustedLibrary(FileName, ISCmplrLibraryTrustFail, True);
+  ISCmplrLibrary := LoadTrustedLibrary(FileName, True);
   if ISCmplrLibrary <> 0 then begin
     ISDllCompileScript := GetProcAddress(ISCmplrLibrary, 'ISDllCompileScriptW');
     ISDllGetVersion := GetProcAddress(ISCmplrLibrary, 'ISDllGetVersion');
@@ -50,4 +52,6 @@ initialization
       ISDllGetVersion := nil;
     end;
   end;
+end;
+
 end.