delphi - WinInet 能否返回正在使用的 TLS

标签 delphi wininet

我们使用 WinInet 和 Delphi 通过 HTTPS 进行通信。 WinInet 中是否有一个函数可以返回 session 中协商的协议(protocol),即 TLS1.1、TLS 1.2 等。

最佳答案

不幸的是,显然不是(在 Windows 7 上使用 Internet Explorer 11 进行测试)。

使用 InternetQueryOption INTERNET_OPTION_SECURITY_CERTIFICATEINTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT是我在 WinInet 文档中可以找到的最接近的(请参阅 lpszProtocolName 中的 INTERNET_CERTIFICATE_INFO ),但它们返回空字符串(请参阅下面的输出)。

lpszProtocolName

Pointer to a buffer that contains the name of the protocol used to provide the
secure connection. The application must call LocalFree to release the resources
allocated for this parameter.

我找不到任何其他内容表明 Wininet 公开了底层 SChannel 连接属性。

program test_wininet;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  Winapi.Wininet;

type
  // fixed declaration
  PInternetCertificateInfo = ^TInternetCertificateInfo;
  TInternetCertificateInfo = record
    ftExpiry: TFileTime;
    ftStart: TFileTime;
    lpszSubjectInfo: PAnsiChar;
    lpszIssuerInfo: PAnsiChar;
    lpszProtocolName: PAnsiChar;
    lpszSignatureAlgName: PAnsiChar;
    lpszEncryptionAlgName: PAnsiChar;
    dwKeySize: DWORD;
  end;

procedure FreeCertificateInfo(var Info: TInternetCertificateInfo);
begin
  if Assigned(Info.lpszSubjectInfo) then
    LocalFree(NativeUInt(Info.lpszSubjectInfo));
  if Assigned(Info.lpszIssuerInfo) then
    LocalFree(NativeUInt(Info.lpszIssuerInfo));
  if Assigned(Info.lpszProtocolName) then
    LocalFree(NativeUInt(Info.lpszProtocolName));
  if Assigned(Info.lpszSignatureAlgName) then
    LocalFree(NativeUInt(Info.lpszSignatureAlgName));
  if Assigned(Info.lpszEncryptionAlgName) then
    LocalFree(NativeUInt(Info.lpszEncryptionAlgName));
end;

function GetCertificateInfo(H: HINTERNET): TInternetCertificateInfo;
var
  Size: Cardinal;
begin
  Size := SizeOf(Result);
  FillChar(Result, Size, 0);
  Win32Check(InternetQueryOption(H, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, @Result, Size));
end;

function GetCertificateInfoStr(H: HINTERNET): AnsiString;
var
  Buffer: array[0..1024] of AnsiChar;
  BufferSize: Cardinal;
  L: Integer;
begin
  Result := '';
  BufferSize := SizeOf(Buffer);
  FillChar(Buffer, BufferSize, 0);
  Win32Check(InternetQueryOption(H, INTERNET_OPTION_SECURITY_CERTIFICATE, @Buffer[0], BufferSize));
  L := StrLen(PAnsiChar(@Buffer[0]));
  if L > 0 then
    SetString(Result, Buffer, L);
end;

procedure Main;
var
  H, H2: HINTERNET;
  Info: TInternetCertificateInfo;
  SysTime: TSystemTime;
begin
  H := InternetOpen('test', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    H2 := InternetOpenUrl(H, 'https://www.microsoft.com', nil, 0, INTERNET_FLAG_NO_UI or INTERNET_FLAG_SECURE, 0);
    try
      Writeln('InternetQueryOption with INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: ');
      Info := GetCertificateInfo(H2);
      try
        Writeln('Subject:');
        Writeln(Info.lpszSubjectInfo);
        Writeln('Issuer:');
        Writeln(Info.lpszIssuerInfo);
        Writeln(Format('Security Protocol: %s', [Info.lpszProtocolName]));
        Writeln(Format('Signature Type: %s', [Info.lpszSignatureAlgName]));
        Writeln(Format('Encryption Type: %s', [Info.lpszEncryptionAlgName]));
        FileTimeToSystemTime(Info.ftStart, SysTime);
        Writeln(Format('Effective Date: %s', [FormatDateTime('dd/mmm/yy hh:nn:ss', SystemTimeToDateTime(SysTime))]));
        FileTimeToSystemTime(Info.ftExpiry, SysTime);
        Writeln(Format('Expiration Date: %s', [FormatDateTime('dd/mmm/yy hh:nn:ss', SystemTimeToDateTime(SysTime))]));
        Writeln(Format('Key size: %d', [Info.dwKeySize]));
        Writeln;
      finally
        FreeCertificateInfo(Info);
      end;

      Writeln('InternetQueryOption with INTERNET_OPTION_SECURITY_CERTIFICATE:');
      Writeln(GetCertificateInfoStr(H2));
      Writeln;
    finally
      InternetCloseHandle(H2);
    end;
  finally
    InternetCloseHandle(H);
  end;
end;

begin
  try
    Main;
    Readln;
  except
    on E: Exception do
    begin
      ExitCode := 1;
      Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
    end;
  end;
end.

上面的代码产生以下输出:

InternetQueryOption with INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT:
Subject:
US
Washington
Private Organization
600413485
US
98052
Washington
Redmond
1 Microsoft Way
Microsoft Corporation
www.microsoft.com
Issuer:
US
Symantec Corporation
Symantec Trust Network
Symantec Class 3 EV SSL CA - G3
Security Protocol:
Signature Type:
Encryption Type:
Effective Date: 24-Mar-16 00:00:00
Expiration Date: 25-Mar-18 23:59:59
Key size: 256

InternetQueryOption with INTERNET_OPTION_SECURITY_CERTIFICATE:
Subject:
US
Washington
Private Organization
600413485
US
98052
Washington
Redmond
1 Microsoft Way
Microsoft Corporation
www.microsoft.com
Issuer:
US
Symantec Corporation
Symantec Trust Network
Symantec Class 3 EV SSL CA - G3
Effective Date: 24-Mar-16 00:00:00
Expiration Date:        25-Mar-18 23:59:59
Security Protocol:      (null)
Signature Type: (null)
Encryption Type:        (null)
Privacy Strength:       High (256 bits)

关于delphi - WinInet 能否返回正在使用的 TLS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37275395/

相关文章:

delphi - 类型转换 : what is difference between below 2 lines of code?

delphi - 在接口(interface)定义中使用相同的 GUID 有危险吗?

delphi - 如何通过 TADODataset 创建和使用聚合字段?

wininet - 以编程方式清除 IE 缓存与 InetCpl.cpl,ClearMyTracksByProcess

c++ - CInternetSession 关闭线程句柄

delphi - 谁在设计时绘制 TTimer?

delphi - 如何将 TImageList 中的图片分配给 TImage?

delphi - WinInet+SSL : Can't make abbreviated SSL handshake

Delphi - 文件大小按 URL - 错误 12150