You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2019/06/07 20:27:19 UTC

[thrift] 01/02: THRIFT-4881 Allow TLS1.1 and TLS1.2 even when not configured as systemwide default Client: Delphi Patch: Jens Geyer

This is an automated email from the ASF dual-hosted git repository.

jensg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/thrift.git

commit 47f6317336b2d8fbd1249a1a49aa561ee052719f
Author: Jens Geyer <je...@apache.org>
AuthorDate: Thu Jun 6 22:42:58 2019 +0200

    THRIFT-4881 Allow TLS1.1 and TLS1.2 even when not configured as systemwide default
    Client: Delphi
    Patch: Jens Geyer
---
 lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas |  13 ++
 lib/delphi/src/Thrift.Transport.WinHTTP.pas   |  42 ++++++
 lib/delphi/src/Thrift.Transport.pas           |  14 +-
 lib/delphi/src/Thrift.WinHTTP.pas             | 177 +++++++++++++++++++++++++-
 lib/delphi/test/TestClient.pas                |   7 +-
 5 files changed, 249 insertions(+), 4 deletions(-)

diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
index cdfb541..620beba 100644
--- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
+++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
@@ -68,9 +68,12 @@ type
     function GetSendTimeout: Integer;
     procedure SetReadTimeout(const Value: Integer);
     function GetReadTimeout: Integer;
+    function GetSecureProtocols : TSecureProtocols;
+    procedure SetSecureProtocols( const value : TSecureProtocols);
 
     function GetCustomHeaders: IThriftDictionary<string,string>;
     procedure SendRequest;
+
     property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
     property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
     property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
@@ -173,6 +176,16 @@ begin
   FReadTimeout := Value;
 end;
 
+function TMsxmlHTTPClientImpl.GetSecureProtocols : TSecureProtocols;
+begin
+  Result := [];
+end;
+
+procedure TMsxmlHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols);
+begin
+  raise TTransportExceptionBadArgs.Create('SetSecureProtocols: Not supported with '+ClassName);
+end;
+
 function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
 begin
   Result := FCustomHeaders;
diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
index aac2aea..8b4a7bc 100644
--- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas
+++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
@@ -46,8 +46,10 @@ type
     FSendTimeout : Integer;
     FReadTimeout : Integer;
     FCustomHeaders : IThriftDictionary<string,string>;
+    FSecureProtocols : TSecureProtocols;
 
     function CreateRequest: IWinHTTPRequest;
+    function SecureProtocolsAsWinHTTPFlags : Cardinal;
 
   private type
       THTTPResponseStream = class( TThriftStreamImpl)
@@ -82,9 +84,12 @@ type
     function GetSendTimeout: Integer;
     procedure SetReadTimeout(const Value: Integer);
     function GetReadTimeout: Integer;
+    function GetSecureProtocols : TSecureProtocols;
+    procedure SetSecureProtocols( const value : TSecureProtocols);
 
     function GetCustomHeaders: IThriftDictionary<string,string>;
     procedure SendRequest;
+
     property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
     property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
     property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
@@ -111,6 +116,8 @@ begin
   FSendTimeout       := 30 * 1000;
   FReadTimeout       := 30 * 1000;
 
+  FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS;
+
   FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
   FOutputMemoryStream := TMemoryStream.Create;
 end;
@@ -133,6 +140,8 @@ begin
   url := TWinHTTPUrlImpl.Create( FUri);
 
   session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi Client');
+  session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags);
+
   connect := session.Connect( url.HostName, url.Port);
 
   sPath   := url.UrlPath + url.ExtraInfo;
@@ -148,6 +157,29 @@ begin
   end;
 end;
 
+
+function TWinHTTPClientImpl.SecureProtocolsAsWinHTTPFlags : Cardinal;
+const
+  PROTOCOL_MAPPING : array[TSecureProtocol] of Cardinal = (
+    WINHTTP_FLAG_SECURE_PROTOCOL_SSL2,
+    WINHTTP_FLAG_SECURE_PROTOCOL_SSL3,
+    WINHTTP_FLAG_SECURE_PROTOCOL_TLS1,
+    WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1,
+    WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
+  );
+var
+  prot : TSecureProtocol;
+  protos : TSecureProtocols;
+begin
+  result := 0;
+  protos := GetSecureProtocols;
+  for prot := Low(TSecureProtocol) to High(TSecureProtocol) do begin
+    if prot in protos
+    then result := result or PROTOCOL_MAPPING[prot];
+  end;
+end;
+
+
 function TWinHTTPClientImpl.GetDnsResolveTimeout: Integer;
 begin
   Result := FDnsResolveTimeout;
@@ -188,6 +220,16 @@ begin
   FReadTimeout := Value;
 end;
 
+function TWinHTTPClientImpl.GetSecureProtocols : TSecureProtocols;
+begin
+  Result := FSecureProtocols;
+end;
+
+procedure TWinHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols);
+begin
+  FSecureProtocols := Value;
+end;
+
 function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
 begin
   Result := FCustomHeaders;
diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas
index 1f8fdb0..c2071df 100644
--- a/lib/delphi/src/Thrift.Transport.pas
+++ b/lib/delphi/src/Thrift.Transport.pas
@@ -118,8 +118,15 @@ type
   TTransportExceptionBadArgs = class (TTransportExceptionSpecialized);
   TTransportExceptionInterrupted = class (TTransportExceptionSpecialized);
 
+  TSecureProtocol = (
+    SSL_2, SSL_3, TLS_1,   // outdated, for compatibilty only
+    TLS_1_1, TLS_1_2       // secure (as of today)
+  );
+
+  TSecureProtocols = set of TSecureProtocol;
+
   IHTTPClient = interface( ITransport )
-    ['{BA142D12-8AE6-4B50-9E33-6B7843B21D73}']
+    ['{7BF615DD-8680-4004-A5B2-88947BA3BA3D}']
     procedure SetDnsResolveTimeout(const Value: Integer);
     function GetDnsResolveTimeout: Integer;
     procedure SetConnectionTimeout(const Value: Integer);
@@ -130,12 +137,15 @@ type
     function GetReadTimeout: Integer;
     function GetCustomHeaders: IThriftDictionary<string,string>;
     procedure SendRequest;
+    function GetSecureProtocols : TSecureProtocols;
+    procedure SetSecureProtocols( const value : TSecureProtocols);
 
     property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
     property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
     property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
     property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
     property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
+    property SecureProtocols : TSecureProtocols read GetSecureProtocols write SetSecureProtocols;
   end;
 
   IServerTransport = interface
@@ -373,6 +383,8 @@ procedure TFramedTransportImpl_Initialize;
 
 const
   DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms
+  DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2];
+
 
 
 implementation
diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas
index 6ad8400..4b98f69 100644
--- a/lib/delphi/src/Thrift.WinHTTP.pas
+++ b/lib/delphi/src/Thrift.WinHTTP.pas
@@ -84,6 +84,16 @@ function WinHttpOpenRequest( const hConnect : HINTERNET;
                              const dwFlags : DWORD
                              ) : HINTERNET;  stdcall;
 
+function WinHttpQueryOption( const hInternet : HINTERNET;
+                             const dwOption : DWORD;
+                             const pBuffer : Pointer;
+                             var dwBufferLength : DWORD) : BOOL;  stdcall;
+
+function WinHttpSetOption( const hInternet : HINTERNET;
+                           const dwOption : DWORD;
+                           const pBuffer : Pointer;
+                           const dwBufferLength : DWORD) : BOOL;  stdcall;
+
 function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET;
                              const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32
                              ) : BOOL;  stdcall;
@@ -193,6 +203,157 @@ const
   INTERNET_SCHEME_HTTP  = INTERNET_SCHEME(1);
   INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
 
+  WINHTTP_NO_CLIENT_CERT_CONTEXT = nil;
+
+  // options manifests for WinHttp{Query|Set}Option
+  WINHTTP_OPTION_CALLBACK = 1;
+  WINHTTP_OPTION_RESOLVE_TIMEOUT = 2;
+  WINHTTP_OPTION_CONNECT_TIMEOUT = 3;
+  WINHTTP_OPTION_CONNECT_RETRIES = 4;
+  WINHTTP_OPTION_SEND_TIMEOUT = 5;
+  WINHTTP_OPTION_RECEIVE_TIMEOUT = 6;
+  WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7;
+  WINHTTP_OPTION_HANDLE_TYPE = 9;
+  WINHTTP_OPTION_READ_BUFFER_SIZE = 12;
+  WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13;
+  WINHTTP_OPTION_PARENT_HANDLE = 21;
+  WINHTTP_OPTION_EXTENDED_ERROR = 24;
+  WINHTTP_OPTION_SECURITY_FLAGS = 31;
+  WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
+  WINHTTP_OPTION_URL = 34;
+  WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36;
+  WINHTTP_OPTION_PROXY = 38;
+  WINHTTP_OPTION_USER_AGENT = 41;
+  WINHTTP_OPTION_CONTEXT_VALUE = 45;
+  WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47;
+  WINHTTP_OPTION_REQUEST_PRIORITY = 58;
+  WINHTTP_OPTION_HTTP_VERSION = 59;
+  WINHTTP_OPTION_DISABLE_FEATURE = 63;
+  WINHTTP_OPTION_CODEPAGE = 68;
+  WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73;
+  WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
+  WINHTTP_OPTION_AUTOLOGON_POLICY = 77;
+  WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78;
+  WINHTTP_OPTION_ENABLE_FEATURE = 79;
+  WINHTTP_OPTION_WORKER_THREAD_COUNT = 80;
+  WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81;
+  WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82;
+  WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83;
+  WINHTTP_OPTION_SECURE_PROTOCOLS = 84;
+  WINHTTP_OPTION_ENABLETRACING = 85;
+  WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86;
+  WINHTTP_OPTION_PASSPORT_RETURN_URL = 87;
+  WINHTTP_OPTION_REDIRECT_POLICY = 88;
+  WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89;
+  WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90;
+  WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91;
+  WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92;
+  WINHTTP_OPTION_CONNECTION_INFO = 93;
+  WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94;
+  WINHTTP_OPTION_SPN = 96;
+  WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97;
+  WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98;
+  WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99;
+  WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100;
+  WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101;
+  WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103;
+  WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104;
+  WINHTTP_OPTION_SERVER_SPN_USED = 106;
+  WINHTTP_OPTION_PROXY_SPN_USED = 107;
+  WINHTTP_OPTION_SERVER_CBT = 108;
+  //
+  WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
+  WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT;
+
+  WINHTTP_OPTION_USERNAME = $1000;
+  WINHTTP_OPTION_PASSWORD = $1001;
+  WINHTTP_OPTION_PROXY_USERNAME = $1002;
+  WINHTTP_OPTION_PROXY_PASSWORD = $1003;
+
+  // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
+  WINHTTP_CONNS_PER_SERVER_UNLIMITED    = $FFFFFFFF;
+
+  // values for WINHTTP_OPTION_AUTOLOGON_POLICY
+  WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM  = 0;
+  WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW     = 1;
+  WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH    = 2;
+
+  WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
+
+  // values for WINHTTP_OPTION_REDIRECT_POLICY
+  WINHTTP_OPTION_REDIRECT_POLICY_NEVER                  = 0;
+  WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
+  WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS                 = 2;
+
+  WINHTTP_OPTION_REDIRECT_POLICY_LAST      = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
+  WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT   = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
+
+  WINHTTP_DISABLE_PASSPORT_AUTH      = $00000000;
+  WINHTTP_ENABLE_PASSPORT_AUTH       = $10000000;
+  WINHTTP_DISABLE_PASSPORT_KEYRING   = $20000000;
+  WINHTTP_ENABLE_PASSPORT_KEYRING    = $40000000;
+
+  // values for WINHTTP_OPTION_DISABLE_FEATURE
+  WINHTTP_DISABLE_COOKIES            = $00000001;
+  WINHTTP_DISABLE_REDIRECTS          = $00000002;
+  WINHTTP_DISABLE_AUTHENTICATION     = $00000004;
+  WINHTTP_DISABLE_KEEP_ALIVE         = $00000008;
+
+  // values for WINHTTP_OPTION_ENABLE_FEATURE
+  WINHTTP_ENABLE_SSL_REVOCATION            = $00000001;
+  WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION  = $00000002;
+
+  // values for WINHTTP_OPTION_SPN
+  WINHTTP_DISABLE_SPN_SERVER_PORT    = $00000000;
+  WINHTTP_ENABLE_SPN_SERVER_PORT     = $00000001;
+  WINHTTP_OPTION_SPN_MASK            = WINHTTP_ENABLE_SPN_SERVER_PORT;
+
+  // winhttp handle types
+  WINHTTP_HANDLE_TYPE_SESSION  = 1;
+  WINHTTP_HANDLE_TYPE_CONNECT  = 2;
+  WINHTTP_HANDLE_TYPE_REQUEST  = 3;
+
+  // values for auth schemes
+  WINHTTP_AUTH_SCHEME_BASIC      = $00000001;
+  WINHTTP_AUTH_SCHEME_NTLM       = $00000002;
+  WINHTTP_AUTH_SCHEME_PASSPORT   = $00000004;
+  WINHTTP_AUTH_SCHEME_DIGEST     = $00000008;
+  WINHTTP_AUTH_SCHEME_NEGOTIATE  = $00000010;
+
+  // WinHttp supported Authentication Targets
+  WINHTTP_AUTH_TARGET_SERVER     = $00000000;
+  WINHTTP_AUTH_TARGET_PROXY      = $00000001;
+
+  // values for WINHTTP_OPTION_SECURITY_FLAGS
+
+  // query only
+  SECURITY_FLAG_SECURE           = $00000001; // can query only
+  SECURITY_FLAG_STRENGTH_WEAK    = $10000000;
+  SECURITY_FLAG_STRENGTH_MEDIUM  = $40000000;
+  SECURITY_FLAG_STRENGTH_STRONG  = $20000000;
+
+  // Secure connection error status flags
+  WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED         = $00000001;
+  WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT            = $00000002;
+  WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED            = $00000004;
+  WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA              = $00000008;
+  WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID         = $00000010;
+  WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID       = $00000020;
+  WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE        = $00000040;
+  WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR  = $80000000;
+
+  WINHTTP_FLAG_SECURE_PROTOCOL_SSL2   = $00000008;
+  WINHTTP_FLAG_SECURE_PROTOCOL_SSL3   = $00000020;
+  WINHTTP_FLAG_SECURE_PROTOCOL_TLS1   = $00000080;
+  WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
+  WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
+
+  // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher!
+  WINHTTP_FLAG_SECURE_PROTOCOL_ALL    = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
+                                     or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
+                                     or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
+
+
 const
   WINHTTP_ERROR_BASE                      = 12000;
   ERROR_WINHTTP_OUT_OF_HANDLES            = WINHTTP_ERROR_BASE + 1;
@@ -254,6 +415,7 @@ const
                          or WINHTTP_FLAG_ESCAPE_DISABLE;
 
 
+
 type
   IWinHTTPRequest = interface
     ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}']
@@ -274,10 +436,11 @@ type
   end;
 
   IWinHTTPSession = interface
-    ['{B6F8BD98-0605-4A9E-B671-4CB191D74A5E}']
+    ['{261ADCB7-5465-4407-8840-468C17F009F0}']
     function  Handle : HINTERNET;
     function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+    function  EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
   end;
 
   IWinHTTPUrl = interface
@@ -339,7 +502,7 @@ type
     // IWinHTTPSession
     function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
-
+    function  EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
   public
     constructor Create( const aAgent : UnicodeString;
                         const aAccessType : DWORD          = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
@@ -444,6 +607,8 @@ function WinHttpConnect;  stdcall; external WINHTTP_DLL;
 function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
 function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
 function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
+function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
+function WinHttpSetOption; stdcall; external WINHTTP_DLL;
 function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
 function WinHttpWriteData; stdcall; external WINHTTP_DLL;
 function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
@@ -521,6 +686,14 @@ begin
 end;
 
 
+function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
+var dwSize : DWORD;
+begin
+  dwSize := SizeOf(aFlagSet);
+  result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
+end;
+
+
 { TWinHTTPConnectionImpl }
 
 constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas
index 55bf92b..ebda7c6 100644
--- a/lib/delphi/test/TestClient.pas
+++ b/lib/delphi/test/TestClient.pas
@@ -29,6 +29,8 @@ unit TestClient;
 {$DEFINE SupportsAsync}
 {$ifend}
 
+{$WARN SYMBOL_PLATFORM OFF}  // Win32Check
+
 interface
 
 uses
@@ -1354,6 +1356,7 @@ end;
 
 procedure TClientThread.InitializeProtocolTransportStack;
 var streamtrans : IStreamTransport;
+    canSSL : Boolean;
 const
   DEBUG_TIMEOUT   = 30 * 1000;
   RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT;
@@ -1363,6 +1366,7 @@ begin
   // needed for HTTP clients as they utilize the MSXML COM components
   OleCheck( CoInitialize( nil));
 
+  canSSL := FALSE;
   case FSetup.endpoint of
     trns_Sockets: begin
       Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')');
@@ -1374,6 +1378,7 @@ begin
     trns_WinHttp: begin
       Console.WriteLine('Using HTTPClient');
       FTransport := InitializeHttpTransport( HTTP_TIMEOUTS);
+      canSSL := TRUE;
     end;
 
     trns_EvHttp: begin
@@ -1403,7 +1408,7 @@ begin
     FTransport := TBufferedTransportImpl.Create( streamtrans, 32);  // small buffer to test read()
   end;
 
-  if FSetup.useSSL then begin
+  if FSetup.useSSL and not canSSL then begin
     raise Exception.Create('SSL/TLS not implemented');
   end;