gpt4 book ai didi

delphi - TIdTCPServer 停止时 SSL_accept 中的 Indy/Libssl32 访问冲突

转载 作者:太空宇宙 更新时间:2023-11-03 14:32:44 26 4
gpt4 key购买 nike

我使用 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;

最佳答案

当 Putty 以 Raw 模式连接时,没有执行 SSL/TLS 握手,因此 SSL_accept() 被卡住,等待从未到达的握手请求。

TIdTCPServer 被停用时,它会断开事件的套接字连接,使其他线程中正在进行的任何阻塞套接字操作失败。在 SSL_accept() 的情况下,应该取消阻止它,以便它可以退出并返回一个错误代码,然后 TIdSSLSocket.Accept() 可以检测并包装到引发的异常中( EIdOSSLUnderlyingCryptoErrorEIdOSSLAcceptErrorEIdSocketError 等,具体取决于错误代码的性质)在等待握手的客户端线程的上下文中完成。

但是,当 TIdTCPServer 在停用期间断开套接字连接时,将调用 TIdTCPConnection.Disconnect(),这会调用 TIdIOHandler.Close()TIdSSLIOhandlerSocketOpenSSL 已覆盖以释放其内部 TIdSSLSocket 对象 - 与调用 SSL_accept() 的对象相同。因此很可能底层 OpenSSL SSL 对象在 TIdSSLSocket.Destroy() 中被释放(调用 SSL_shutdown()SSL_free()) 在停用线程的上下文中,同时仍在 TIdSSLObject.Accept()(调用 SSL_accept())中积极使用客户端线程的上下文,从而导致访问冲突。

如果不更改 Indy 的源代码,对此无能为力。例如,可以更改 TIdCustomTCPServer.DoTerminateContext() 以调用 AContext.Binding.CloseSocket() 而不是 AContext.Connection.Disconnect(False)所以 IOHandler 本身没有关闭,只是底层套接字(类似于 TIdCustomTCPServer.StopListening() 在终止其监听 accept() 时所做的线程)。

我已经在 Indy 的问题跟踪器中为您开了一张票:

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

关于delphi - TIdTCPServer 停止时 SSL_accept 中的 Indy/Libssl32 访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51150235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com