我使用Delphi 10.1 Update 2和Indy 10.6.2.5341。
我们遇到SSL_accept中的访问冲突。如果使用SSL设置了TIdTCPServer,并且TIdTCPServer停止,则存在尚未协商TLS的开放连接。
这看起来像Libssl32或Indy中的问题。使用RAW连接,可以使用以下代码和Putty简单地复制此代码。有谁知道防止这些崩溃的解决方案(或解决方法)?
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;
答案 0 :(得分:0)
当Putty以Raw模式连接时,没有执行SSL / TLS握手,因此SSL_accept()
被困在等待从未到达的握手请求。
停用TIdTCPServer
时,它将断开活动的套接字连接,从而使其他线程中正在进行的任何阻塞套接字操作失败。在SSL_accept()
的情况下,应该对其进行解锁,以便它退出并显示错误代码,然后TIdSSLSocket.Accept()
可以检测并包装为引发的异常(EIdOSSLUnderlyingCryptoError
,EIdOSSLAcceptError
, EIdSocketError
,具体取决于错误代码的性质)在等待握手完成的客户端线程的上下文中。
但是,当TIdTCPServer
在停用期间断开套接字连接时,将调用TIdTCPConnection.Disconnect()
,TIdIOHandler.Close()
被TIdSSLIOhandlerSocketOpenSSL
覆盖以释放其内部{{1 }}对象-调用TIdSSLSocket
的对象。因此,很有可能在停用线程的上下文中,底层的OpenSSL SSL_accept()
对象在SSL
(调用TIdSSLSocket.Destroy()
和SSL_shutdown()
)中被释放,同时仍在活跃地被释放。在客户端线程的上下文中用在SSL_free()
(调用TIdSSLObject.Accept()
)中,从而导致访问冲突。
在不更改Indy的源代码的情况下,无法做很多事情。例如,也许将SSL_accept()
更改为调用TIdCustomTCPServer.DoTerminateContext()
而不是AContext.Binding.CloseSocket()
,这样AContext.Connection.Disconnect(False)
本身就不会被关闭,只是底层套接字(类似于IOHandler
的作用)终止其正在监听的TIdCustomTCPServer.StopListening()
线程时)。
我已经在Indy的问题跟踪器中为您打开了一张票证:
#218: Access Violation in SSL_accept() when deactivating TIdTCPServer