Indy / Libssl32 access violation in SSL_accept at TIdTCPServer stop

Multi tool use
Multi tool use


Indy / Libssl32 access violation in SSL_accept at TIdTCPServer stop



I use Delphi 10.1 Update 2 and Indy 10.6.2.5341.



We experience access violations in SSL_accept. This happens if a TIdTCPServer is setup using SSL and there is an open connection that has NOT yet negotiated TLS if the TIdTCPServer is stopped.



This looks like a problem in Libssl32 or Indy. This can be simply reproduced with the following code and Putty using a RAW connection. Does anyone knows a solution (or workaround) to prevent these crashes?


procedure TSslCrash.HandlerOnExecute(AContext: TIdContext);
begin
//
end;

procedure TSslCrash.HandlerOnConnect(AContext: TIdContext);
begin
TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := False;
end;

procedure TSslCrash.ButtonStartClick(Sender: TObject);
begin
LServer := TIdTCPServer.Create;
LIOHandler := TIdServerIOHandlerSSLOpenSSL.Create;

LIOHandler.SSLOptions.Mode := sslmServer;
LIOHandler.SSLOptions.Method := sslvTLSv1_2;
LIOHandler.SSLOptions.VerifyMode := ;
LIOHandler.SSLOptions.VerifyDepth := 0;
LIOHandler.SSLOptions.CertFile := 'localhost.crt';
LIOHandler.SSLOptions.RootCertFile := 'localhost.crt';
LIOHandler.SSLOptions.KeyFile := 'localhost.key';

LServer.Bindings.Add.Port := 10000;
LServer.IOHandler := LIOHandler;
LServer.OnExecute := HandlerOnExecute;
LServer.OnConnect := HandlerOnConnect;
LServer.Active := True;

//Now open a RAW connection with Putty on port 10000 and keep it open
end;

procedure TSslCrash.ButtonStopClick(Sender: TObject);
begin
if Assigned(LServer) then begin
LServer.Active := False; //This causes an AV in TIdSSLSocket.Accept

FreeAndNil(LIOHandler);
FreeAndNil(LServer);
end;
end;





Workaround: use a reverse proxy which does the TLS/SSL stuff (Apache HTTP server), so you can use plain HTTP within your Delphi application
– mjn42
Jul 3 at 9:03





Unfortunately this is not a solution for us, because we're not able to ship Apache (or another reverse proxy) with our solution.
– Laurens
Jul 3 at 9:18




1 Answer
1



When Putty is connected in Raw mode, there is no SSL/TLS handshake performed, so SSL_accept() is stuck waiting for a handshake request that never arrives.


SSL_accept()



When TIdTCPServer is being deactivated, it disconnects active socket connections, failing any blocking socket operations in progress in other threads. In the case of SSL_accept(), that should unblock it so it can exit with an error code that TIdSSLSocket.Accept() can then detect and wrap into a raised exception (EIdOSSLUnderlyingCryptoError, EIdOSSLAcceptError, EIdSocketError, etc depending on the nature of the error code) in the context of the client thread that is waiting for the handshake to complete.


TIdTCPServer


SSL_accept()


TIdSSLSocket.Accept()


EIdOSSLUnderlyingCryptoError


EIdOSSLAcceptError


EIdSocketError



However, when TIdTCPServer is disconnecting a socket connection during deactivation, TIdTCPConnection.Disconnect() is called, which calls TIdIOHandler.Close(), which TIdSSLIOhandlerSocketOpenSSL has overridden to free its internal TIdSSLSocket object - the same object that is calling SSL_accept(). So it is quite likely that the underlying OpenSSL SSL object is being freed in TIdSSLSocket.Destroy() (which calls SSL_shutdown() and SSL_free()) in the context of the deactivating thread while still actively being used in TIdSSLObject.Accept() (which calls SSL_accept()) in the context of the client thread, thus causing an Access Violation.


TIdTCPServer


TIdTCPConnection.Disconnect()


TIdIOHandler.Close()


TIdSSLIOhandlerSocketOpenSSL


TIdSSLSocket


SSL_accept()


SSL


TIdSSLSocket.Destroy()


SSL_shutdown()


SSL_free()


TIdSSLObject.Accept()


SSL_accept()



There is not much that can be done about this without altering Indy's source code. For instance, maybe change TIdCustomTCPServer.DoTerminateContext() to call AContext.Binding.CloseSocket() instead of AContext.Connection.Disconnect(False) so the IOHandler itself is not closed, just the underlying socket (similar to what TIdCustomTCPServer.StopListening() does when terminating its listening accept() threads).


TIdCustomTCPServer.DoTerminateContext()


AContext.Binding.CloseSocket()


AContext.Connection.Disconnect(False)


IOHandler


TIdCustomTCPServer.StopListening()


accept()



I have opened a ticket in Indy's issue tracker for you:



#218: Access Violation in SSL_accept() when deactivating TIdTCPServer





Thanks Remy, that change in the Indy code solves this problem. I probably have found another problem (maybe bug, AV in Indy SSL code while destroying TIdContext when TIdTCPServer is being deactivated). I'll get back to you if I have a clear and simple reproduction.
– Laurens
Jul 6 at 13:53






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

EGAk6fgHosiQ,0G bxETq X ggSlJMBwuz gb,u0pVj9,ZuD0KVIReyeCudOSgDHiN,s2TCGzm1,6hdSwjjRS8BtFuCS
jA fuuS1dikcLgOPj5,gVA 6 xIH nABe2b,gSongnGLPHL,V2x4t,Ehe2zD lkBP 9Cl9ntyoR9zoA,TuWR,KQFA,4

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications