THRIFT-4881 Allow TLS1.1 and TLS1.2 even when not configured as systemwide default
Client: Delphi
Patch: Jens Geyer
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 @@
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 @@
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 @@
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 @@
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 @@
FSendTimeout := 30 * 1000;
FReadTimeout := 30 * 1000;
+ FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS;
+
FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
FOutputMemoryStream := TMemoryStream.Create;
end;
@@ -133,6 +140,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
or WINHTTP_FLAG_ESCAPE_DISABLE;
+
type
IWinHTTPRequest = interface
['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}']
@@ -274,10 +436,11 @@
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 @@
// 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 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 @@
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);