Simple code:
procedure TForm1.Button1Click(Sender: TObject);
//var
//h: tIdHTTP;
//SSL: TIdSSLIOHandlerSocketOpenSSL;
begin
h.IOHandler := SSL;
SSL.SSLOptions.Method := sslvTLSv1_2;
SSL.SLLOptions.SSLVersion := [sslvTLSv1_2]; //must be set automatically after SetMethod, but just to be sure
h.Get('https://www.deviantart.com/users/login');
end;
That simple code gives me an error:
Error connecting with SSL.
error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
I use Delphi XE3 and OpenSSL 1.0.2b libs. I can't figure it out, looking into sources, there is strings in connection initiation that disable not used versions:
if not (sslvSSLv2 in SSLVersions) then begin
SSL_CTX_set_options(fContext, SSL_OP_NO_SSLv2);
end;
if not (sslvSSLv3 in SSLVersions) then begin
SSL_CTX_set_options(fContext, SSL_OP_NO_SSLv3);
end;
if not (sslvTLSv1 in SSLVersions) then begin
SSL_CTX_set_options(fContext, SSL_OP_NO_TLSv1);
end;
But sslv3 operations still getting in somehow. Doesn't look like a component's bug. Something library internal, or indy doesn't consider something when setting up parameters?
Or it's actually me, who didn't notice something important? I really hope I don't need to go through a hell named "indy components update".
Test on (tried all methods including TLS1.2) https://www.deviantart.com/users/login
Resolving hostname www.deviantart.com.
Connecting to 54.230.96.81.
Handshake Start: before/connect initialization
Connect Loop: before/connect initialization
Connect Loop: SSLv3 write client hello A
fatal Read Alert: handshake failure
Connect Failed: SSLv3 read server hello A
ERROR: Error connecting with SSL.
error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
- for SSL3 and TLS1/1.1/1.2 result is identical;
- for SSLv23 answers SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure;
- for SSLv2 doesn't answer;
Test on similar resource (TLS1.2 ONLY) https://files.yande.re/image/da9afa6d9ca43a9f154fad69f76adb85.jpg
Resolving hostname files.yande.re.
Connecting to 5.39.10.56.
Handshake Start: before/connect initialization
Connect Loop: before/connect initialization
Connect Loop: SSLv3 write client hello A
Connect Loop: SSLv3 read server hello A
Connect Loop: SSLv3 read server certificate A
Connect Loop: SSLv3 read server key exchange A
Connect Loop: SSLv3 read server done A
Connect Loop: SSLv3 write client key exchange A
Connect Loop: SSLv3 write change cipher spec A
Connect Loop: SSLv3 write finished A
Connect Loop: SSLv3 flush data
Connect Loop: SSLv3 read server session ticket A
Connect Loop: SSLv3 read finished A
Handshake Done: SSL negotiation finished successfully
Connect Exit: SSL negotiation finished successfully
My WireShark tests:
- Indy:
http://imgur.com/BZ84Cl3
(response is handshake failure); - Firefox:
http://imgur.com/pkYJvnO
; - Response to Firefox request:
http://imgur.com/M9ni3TV
;
I fixed a handshake problem this morning, comparing the wireshark logs of google chrome (which worked fine) and my application (with handshake problems). It turned out I had to enable the "signature_algorithms" extension.
However, I use SecureBlackBox (and not indy and openssl) because I had to dynamically load a client certificate, but maybe this can help you (compare and debug it with wireshark!).
alert handshake failure means the initial handshake is failing on the server side, so it sends an alert to notify your client before then closing the connection. You probably did not setup a compatible certificate or cipher suite that the server is expecting. Or maybe the server simply does not support TLS 1.2. Try using TLS 1.0 or TLS 1.1 instead. Also, you can try using OpenSSL's own
s_client
tool to debug connection problems until you figure out the correct settings, and then apply them to Indy as needed. Or, use Wireshark to look at the actual handshake and see at which stage it is failing.