IndySockets / Indy

Indy - Internet Direct
https://www.indyproject.org
456 stars 155 forks source link

Delphi 10.4 error:1408F10B:SSL SSL3_GET_RECORD:wrong version number #372

Closed Serraniel closed 3 years ago

Serraniel commented 3 years ago

Hi,

with the Indy version of Delphi 10.4 we are having issues using TLS for a TCP server / client system. I have a testtool which works perfectly when compiled with Delphi 10.3. With 10.4 we are getting an error, if the clients wants to connect: image image

The code of the server app is

procedure TForm1.FormCreate(Sender: TObject);
begin
  IdServerIOHandlerSSLOpenSSL.SSLOptions.CertFile := 'S:\certs\pc.pfx';
  IdServerIOHandlerSSLOpenSSL.SSLOptions.KeyFile := 'S:\certs\pc.pfx';
  IdServerIOHandlerSSLOpenSSL.SSLOptions.RootCertFile := 'S:\certs\ca.cer';
  IdServerIOHandlerSSLOpenSSL.SSLOptions.Mode := sslmServer;
  IdServerIOHandlerSSLOpenSSL.SSLOptions.SSLVersions := [sslvTLSv1_2];

  IdTCPServer.DefaultPort := 8888;
  IdTCPServer.Active := true;
end;

procedure TForm1.IdServerIOHandlerSSLOpenSSLGetPassword(var Password: string);
begin
  Password := 'Password';
end;

procedure TForm1.IdTCPServerConnect(AContext: TIdContext);
begin
  if AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := false;

  memLog.Lines.Add('Connect: ' + AContext.Binding.PeerIP);
end;

procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
begin
  // print to log
end;

For the client it looks like this:

procedure TForm2.FormCreate(Sender: TObject);
begin
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;

  IdSSLIOHandlerSocketOpenSSL.SSLOptions.SSLVersions := [sslvTLSv1_2];
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;

  IdTCPClient.Host := '192.168.122.7';
  IdTCPClient.Port := 8888;
  IdTCPClient.ReadTimeout := 50;

  IdTCPClient.Connect;
end;

The SSL IO handler is set via DFM to the server/client.

What I have found out so far: There is no exception and apps can communicate, if I do not set the Passthrough to false in the connect event in the server. But if the Passthrough property is not set to false, the tcp connection is not secured and I can read sent messages in Wireshark in plain text.

I also think the issue is in the client. I come to this conclusion as I tried running the client and server compiled with the different Delphi versions: Delphi version used to compile client Delphi version used to compile server Result
10.3 10.3 ✔️
10.3 10.4 ✔️
10.4 10.3
10.4 10.4

Do you have any idea about changes which may cause that behaviour? Anything I could do to provide more information about the issue?

rlebeau commented 3 years ago

The error message indicates there is a version mismatch in the TLS handshake. I have no way of diagnosing the root problem given the limited information so far. I suggest you use Wireshark to look for any problems in the TLS handshake. Even though you are requesting TLS 1.2 in your code, it is possible that maybe Indy/OpenSSL is falling back to TLS 1.1 or even 1.0 instead. Which version of the OpenSSL DLLs are you trying to use? Does the IsOpenSSL_TLSv1_2_Available() function in the IdSSLOpenSSLHeaders unit return true or false after the error occurs?

Serraniel commented 3 years ago

A colleague just sent me this: https://quality.embarcadero.com/browse/RSP-29900

I tried it and it seems to be the solution.

The reason of this trouble is the PassThrough property of the TIdSSLIOHandlerSocketOpenSSL: In Delphi 10.3.3 is by default false but in Delphi 10.4 it is by default true. Having this property with a true value, the TIdSSLIOHandlerSocketOpenSSL does not handle the encrypted connection and no encrypted connection is created, resulting in disconnection from the server.

So just setting it to false on the client IO Handler was the fix. Sorry for the inconvenience.