1
votes

After compiling my win32 client/server application (using INDY and TMS Sparkle) with Delphi 10.4 I get an ssl error. I use Indy with and a self signed certificate on the server side and indy on the client side. The error message is (translated from german):

Error connection with SSL. EOF encountered violating the protocol.

I did not change any code or environment from 10.3 where it ran perfectly. I can break it down to the server side as the old server (compiled in 10.3) runs with the new client (compiled with 10.4) but the old client also breaks when trying to connect to the new server.

This is how I initialize SSL:

    SecureServer := TIndySparkleHTTPServer.create(nil);
    SecureServer.DefaultPort := SecurePort;
    // Initialize SSL with self signed certificate
    SSLHandler := TIdServerIOHandlerSSLOpenSSL.create(SecureServer);
    SSLHandler.SSLOptions.CertFile := SharedVals.ServerPath + 'appcert.pem';
    SSLHandler.SSLOptions.RootCertFile := SharedVals.ServerPath + 'approot.pem';
    SSLHandler.SSLOptions.KeyFile := SharedVals.ServerPath + 'appkey.pem';
    SSLHandler.SSLOptions.Method := sslvSSLv23;
    SecureServer.IOHandler := SSLHandler;

Emba managed to break Indy in 10.3, perhaps this is an other case like this?

1
EOF encountered violating the protocol means the server closes the TCP connection in the middle of an SSL/TLS handshake. Typically that can happen if the server doesn't like something in the handshake, but OpenSSL will usually send an alert to the client before closing the connection. Did you check if your server is raising an uncaught exception after the client connects? On a side note, you really should not be using the SSLOptions.Method property at all, use the SSLOptions.SSLVersions property instead, eg SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];Remy Lebeau
Embarcadero indeed broke OpenSSL support in Indy in 10.3, but they fixed it, and they just grabbed the latest Indy a few weeks ago for 10.4, and AFAIK there are no known issues with TIdHTTPServer or its use of OpenSSL in the latest Indy.Remy Lebeau
Thanks, I debugged the server and indeed I get EIdHttpErrorParsindCommand with "Fehler bei der Analyse einer Anweisung" whicht means something like "Error parsig a command" I have no Idea and think Irollback to D10.3...MichaSchumann
EIdHTTPErrorParsingCommand is raised when TIdHTTPServer receives a malformed HTTP request. Since TIdHTTPServer does not process decrypted HTTPS requests until after an SSL/TLS handshake has been completed first, that implies that your server is not actually trying to perform an SSL/TLS handshake at all and thus is trying to parse the client's SSL/TLS handshake request as if it were an HTTP request. Is your SecurePort set to a non-standard HTTPS port (something other than 443)? If so, make sure your server has an OnQuerySSLPort event handler that returns VUseSSL=True for that portRemy Lebeau
Remy: Thanks once more. I had been using non standard ports and it seems to work by setting vUseSSL to true using a small helper class. To me it seems that somehow 10.4 doesn't silently default to true here whereas 10.3 did. I saw that this non default port behaviour was already introduced in Indy in 2018 (Atozed Change log).MichaSchumann

1 Answers

2
votes

The credit belongs to Remy Lebau who pointed me in the correct direction. But I want to answer my question by supplying the code that made it work again in Delphi 10.4. As the change in Indy was done 2018(!) I still have no idea why it worked perfectly in 10.3 until the upgrade to 10.4.

Since I use the TMS Sparke Server for Indy directly in a service/daemon project I supply a small class to connect the OnQuerySSLPort Method that expects an object method.

type
  TSSLHelper = class
  // This helper class is neccessary to set ssl true
  // as it defaults to false on non standard ssl ports
    procedure QuerySSLPort(APort: Word; var VUseSSL: boolean);
  end;

...

procedure TSSLHelper.QuerySSLPort(APort: Word; var VUseSSL: boolean);
begin
  VUseSSL := true;
end;

...

SecureServer := TIndySparkleHTTPServer.create(nil);
SecureServer.DefaultPort := SecurePort;
// Initialize SSL with self signed certificate
SSLHandler := TIdServerIOHandlerSSLOpenSSL.create(SecureServer);
SSLHandler.SSLOptions.CertFile := SharedVals.ServerPath + 'appcert.pem';
SSLHandler.SSLOptions.RootCertFile := SharedVals.ServerPath + 'approot.pem';
SSLHandler.SSLOptions.KeyFile := SharedVals.ServerPath + 'appkey.pem';
SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
SecureServer.IOHandler := SSLHandler;
SSLHelper := TSSLHelper.Create;
SecureServer.OnQuerySSLPort := SSLHelper.QuerySSLPort;
...

Now it works like before.