4
votes

As you know the new poodle is in town, Witch barks got Twitter, Cloudflare to drop support to SSL3.

The Indy(TidHttp) 10.6.0.0 revives this nice exception:

EidOsslUnerlayingCryptoError message 'Error connecting with SSL. error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'

My question is what is the definition required to handle TLS?

update: here is a code that throw the exception: full working code.

var
  parameters:TStringList;
  keySecretBase64:string;
  stream:TStringStream;
  IdEncoderMIME1 : TIdEncoderMIME;
  idHttp1 : TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL1:TIdSSLIOHandlerSocketOpenSSL;//assume on Form
begin
  stream:=TStringStream.create;
  parameters:=TStringList.Create;
  IdEncoderMIME1 := TIdEncoderMIME.Create(nil);
  idHttp1 := TIdHTTP.Create(nil);
  IdSSLIOHandlerSocketOpenSSL1:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
    with IdSSLIOHandlerSocketOpenSSL1 do begin
      SSLOptions.Method := sslvSSLv3;
      SSLOptions.Mode :=  sslmUnassigned;
      SSLOptions.VerifyMode := [];
      SSLOptions.VerifyDepth := 2;
    end;
    with idHttp1 do begin
      IOHandler := IdSSLIOHandlerSocketOpenSSL1;
      ReadTimeout := 0;
      AllowCookies := True;
      ProxyParams.BasicAuthentication := False;
      ProxyParams.ProxyPort := 0;
      Request.ContentLength := -1;
      Request.ContentRangeEnd := 0;
      Request.ContentRangeStart := 0;
      Request.ContentType := 'application/x-www-form-urlencoded';
      Request.Accept := 'text/html, */*';

      Request.BasicAuthentication := False;
      Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
      HTTPOptions := [hoForceEncodeParams];
    end;
    parameters.Clear;
    idHttp1.Request.CustomHeaders.Clear;
    IdEncoderMIME1.FillChar:='=';

  try
    keySecretBase64 := TIdEncoderMIME.EncodeString(key+ ':' + secret, IndyTextEncoding_UTF8);// this is twitter provided key and secret
    parameters.Add('grant_type=client_credentials');
    idHttp1.Request.CustomHeaders.AddValue('Authorization','Basic '+keySecretBase64);
    idHttp1.post(URL,parameters,stream);
  finally
    stream.Free;
    parameters.Free;
    parameters.Free;
    IdSSLIOHandlerSocketOpenSSL1.Free;
  end;
end;
2
You are connecting with TLSv1 only, so you can only connect to servers using the SSLv23 wildcard or TLSv1 specifically, otherwise your TLSv1 handshake will fail. - Remy Lebeau
Your example code could be so much shorter - only IdHttp.Get('https://www.google.com') or a different https address and the SSLIOHandler part is required - mjn
true. however google does not deny ssl and force tls, as far as i know, check the second link about twitter and cloudflare. - none
@MSchenkel: The TIdTextEncoding class was replaced with a new IIdTextEncoding interface in Indy 10.6. See this blog article. - Remy Lebeau
@mjn: the code can be shortened even further if you take into account that TIdHTTP can now create its own SSLIOHandler (that defaults to TLSv1), if one has not already been assigned, when requesting an HTTPS url. See this blog article. - Remy Lebeau

2 Answers

3
votes

Your code selects TLS 1.2 in the SSLOptions property Method:

IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];

However, two lines later this value is overwritten with SSL 3:

with IdSSLIOHandlerSocketOpenSSL1 do begin
  SSLOptions.Method := sslvSSLv3;
  ...
end;

So the client will not connect with the newer TLS 1.2 protocol but with SSL 3, which is no longer supported by the server.

This explains the error message, which says that the SSL 3 handshake (which the client tried) failed:

SSL. error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'

If you remove the second assignment, the IdHTTP client will use TLS 1.2 for the connect.

1
votes

SSL2, SSL3 and TLS1.0 are all vulnerable for man-in-th-middle attacks. You should use TLS 1.1 and upper for secure connection. Unfortunately, Indy 9 does not support TLS 1.1 and upper.

This answer reports that there is an option TLSv1_2 for TLS 1.2 in Indy 10, but it is not presented in Indy 10 online documentation.