4

We use WinInet and Delphi to communicate using HTTPS. Is there a function in WinInet that will return to me which protocol has been negotiated in the session, i.e. TLS1.1, TLS 1.2 etc.

1 Answers1

6

Unfortunately, apparently not (tested on Windows 7 with Internet Explorer 11).

Using InternetQueryOption with INTERNET_OPTION_SECURITY_CERTIFICATE or INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT was the closest I could find in WinInet documentation (see lpszProtocolName in INTERNET_CERTIFICATE_INFO), but they return empty strings (see output below).

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.

I couldn't find anything else suggesting that Wininet exposes the underlying SChannel connection properties.

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.

The above code produces the following output:

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)
Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128