I have a problem with Indy components in Delphi 10.1 Berlin on OS X. I'm using TIdHTTP
to connect to a webservice using HTTPS. The problem is connecting to a server from an OS X client. When running on OS X, I get this same error all the time:
Project raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL. error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'.
I set the TIdHTTP.IOHandler
property to use OpenSSL:
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
On OS X, when I run this command in a terminal:
openssl version
It returns OpenSSL 0.9, which is the default version that comes with OS X.
Even if I install the latest version of OpenSSL using Homebrew or MacPort, it does not help. It give me the same error every time.
I have OS X installed in VMWare, if this helps. I also tried two versions of OS X: Yosemite and El Capitan. Same problem.
This is code I use:
unit uApiClient1; interface uses IdHTTP, System.JSON, IdSSLOpenSSLHeaders, System.Classes, IdCTypes, System.SysUtils, IdSSLOpenSSL; const API_URL = 'https://www.myserver.com/ws.php'; WS_METHOD = 'validate_status'; type TAPIClient = class(TObject) function ValidateStatus(userId, deviceId: string): TJSONObject; private procedure PrepareHTTPObject(var IdHTTP: TIdHTTP); end; implementation { APIClient } procedure TAPIClient.PrepareHTTPObject(var IdHTTP: TIdHTTP); begin IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); TIdSSLIOHandlerSocketOpenSSL(IdHTTP.IOHandler).SSLOptions.Method := sslvTLSv1_2; // IdHTTP.Request.Accept := 'text/javascript'; IdHTTP.Request.ContentType := 'application/json'; IdHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0'; end; function TAPIClient.ValidateStatus(userId, deviceId: string): TJSONObject; var IdHTTP: TIdHTTP; LJSONObject: TJSONObject; dataResult: string; begin LJSONObject := nil; IdHTTP := TIdHTTP.Create(nil); try try PrepareHTTPObject(IdHTTP); dataResult := IdHTTP.Get(API_URL + format('?action=%s&user_id=%s&device_id=%s', [WS_METHOD, userId, deviceid])); LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(dataResult), 0) as TJSONObject; except end; finally IdHTTP.Free; end; Result := LJSONObject; end; end.
I tried to compare packets from WireShark generated by my application and by Safari and this is what I get:
My application:
Handshake Protocol: Client Hello Handshake Type: Client Hello (1) Length: 114 Version: TLS 1.0 (0x0301) Random GMT Unix Time: Aug 24, 2016 20:26:07.000000000 EEST Random Bytes: 49c48ba758048a2429dd01ee2e390ed06eb320e5248d016d... Session ID Length: 0 Cipher Suites Length: 46 Cipher Suites (23 suites) Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039) Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016) Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013) Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a) Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033) Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) Cipher Suite: TLS_DHE_RSA_WITH_SEED_CBC_SHA (0x009a) Cipher Suite: TLS_DHE_DSS_WITH_SEED_CBC_SHA (0x0099) Cipher Suite: TLS_RSA_WITH_SEED_CBC_SHA (0x0096) Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005) Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004) Cipher Suite: TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015) Cipher Suite: TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012) Cipher Suite: TLS_RSA_WITH_DES_CBC_SHA (0x0009) Cipher Suite: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014) Cipher Suite: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011) Cipher Suite: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008) Cipher Suite: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006) Cipher Suite: TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003) Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff) Compression Methods Length: 1 Compression Methods (1 method) Extensions Length: 27 Extension: server_name Extension: SessionTicket TLS Type: SessionTicket TLS (0x0023) Length: 0 Data (0 bytes)
Safari browser:
Handshake Protocol: Client Hello Handshake Type: Client Hello (1) Length: 229 Version: TLS 1.2 (0x0303) Random GMT Unix Time: Aug 24, 2016 20:35:07.000000000 EEST Random Bytes: d0f0bc116fd51dff15c739bb76f7e6032a931d07e2e56a56... Session ID Length: 0 Cipher Suites Length: 44 Cipher Suites (22 suites) Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009) Cipher Suite: TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc008) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) Cipher Suite: TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012) Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d) Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a) Compression Methods Length: 1 Compression Methods (1 method) Extensions Length: 144 Extension: server_name Extension: elliptic_curves Extension: ec_point_formats Extension: signature_algorithms Type: signature_algorithms (0x000d) Length: 14 Signature Hash Algorithms Length: 12 Signature Hash Algorithms (6 algorithms) Extension: next_protocol_negotiation Type: next_protocol_negotiation (0x3374) Length: 0 Extension: Application Layer Protocol Negotiation Type: Application Layer Protocol Negotiation (0x0010) Length: 48 ALPN Extension Length: 46 ALPN Protocol Extension: status_request Type: status_request (0x0005) Length: 5 Certificate Status Type: OCSP (1) Responder ID list Length: 0 Request Extensions Length: 0 Extension: signed_certificate_timestamp Type: signed_certificate_timestamp (0x0012) Length: 0 Data (0 bytes)
In protocol column of the WireShark, for Savari is TLSv1.2
, and for my application is TLSv1
, even I set method to sslvTLSv1_2
in code.
For both SNI is set correctly.
This is TLS alert from WireShark:
Secure Sockets Layer TLSv1 Record Layer: Alert (Level: Fatal, Description: Handshake Failure) Content Type: Alert (21) Version: TLS 1.0 (0x0301) Length: 2 Alert Message Level: Fatal (2) Description: Handshake Failure (40)