简体   繁体   English

SslStream.AuthenticateAsServer 挂起

[英]SslStream.AuthenticateAsServer hangs

Using VS 10 with .NET framework 4.0, I have written three c# unit tests to check the SslStream behaviour for different server / client protocol settings.使用 VS 10 和 .NET framework 4.0,我编写了三个 c# 单元测试来检查不同服务器/客户端协议设置的 SslStream 行为。

  private void InternalTestSsl(SslProtocols serverProtocols, SslProtocols clientProtocols)
  {
     X509Certificate2 certificate = RetrieveServerCertificate();
     var server = new TcpListener(new IPEndPoint(IPAddress.Any, 20000));
     server.Start();
     try
     {
        // create and execute a task for server operations
        var serverTask = new Task(() =>
        {
           TcpClient connectionToClient = server.AcceptTcpClient();
           var sslStream = new SslStream(connectionToClient.GetStream(), false, (a, b, c, d) => true, (a, b, c, d, e) => certificate);
           sslStream.AuthenticateAsServer(certificate, false, serverProtocols, true);
           Assert.IsTrue(sslStream.IsAuthenticated);
        });
        serverTask.Start();

        // create and execute a task for client operations
        var clientTask = new Task(() =>
        {
           var clientConnection = new TcpClient();
           clientConnection.Connect(new IPEndPoint(IPAddress.Loopback, 20000));
           var sslStream = new SslStream(clientConnection.GetStream(), false, (a, b, c, d) => true, (a, b, c, d, e) => null);
           sslStream.AuthenticateAsClient(Environment.MachineName, null, clientProtocols, true);
           Assert.IsTrue(sslStream.IsAuthenticated);
        });
        clientTask.Start();

        // wait for both server and client task to finish, check results
        if (!serverTask.Wait(TimeSpan.FromSeconds(1)))
        {
           throw new Exception("Server task did not end in time.");
        }
        if (!clientTask.Wait(TimeSpan.FromSeconds(1)))
        {
           throw new Exception("Client task did not end in time.");
        }
     }
     finally
     {
        server.Stop();
     }
  }

  [TestMethod]
  public void TestTlsTls()
  {
     InternalTestSsl(SslProtocols.Tls, SslProtocols.Tls);
  }

  [TestMethod]
  public void TestTlsSsl3()
  {
     InternalTestSsl(SslProtocols.Tls, SslProtocols.Ssl3);
  }

  [TestMethod]
  public void TestSsl3Tls()
  {
     InternalTestSsl(SslProtocols.Ssl3, SslProtocols.Tls);
  }

TestTlsTls passes as both server and client define the same protocols to be used (only TLS). TestTlsTls 传递,因为服务器和客户端都定义了要使用的相同协议(仅 TLS)。 The failure of TestTlsSsl3 is also completely understandable (an AuthenticationException is thrown because the server wants TLS to be used, but the client want´s to solely play SSL3). TestTlsSsl3 的失败也是完全可以理解的(抛出 AuthenticationException 是因为服务器想要使用 TLS,但客户端想要单独播放 SSL3)。

I expected the test "TestSsl3Tls" to fail with the same AuthenticationException, but instead, my custom exception "Server task did not end in time."我希望测试“TestSsl3Tls”失败并出现相同的 AuthenticationException,但相反,我的自定义异常“服务器任务没有及时结束”。 was fired.被解雇。 When debugging, I see that only the client task receives an AuthenticationException while the serverTask remains in the call of AuthenticateAsServer.调试时,我看到只有客户端任务收到 AuthenticationException 而 serverTask 保留在 AuthenticateAsServer 的调用中。 Swapping my Wait commands results in the opposite: AuthenticationException for "TestSsl3Tls", "Client did not end in time" for "TestTlsSsl3".交换我的等待命令导致相反的结果:“TestSsl3Tls”的 AuthenticationException,“TestTlsSsl3”的“客户端没有及时结束”。

Is that the normal behaviour, the AuthenticationException only being thrown on one side, the other side waiting (may be for a new authentication attempt or a disconnect)?这是正常行为吗, AuthenticationException 只在一侧抛出,另一侧等待(可能是新的身份验证尝试或断开连接)?

I dont know the answer to your question whether this behaviour is normal, but in my opinion this is a bug and I recently had the same issue and since I could not control the client security protocol, my server ended up freezing all the time.我不知道你的问题的答案这种行为是否正常,但在我看来这是一个错误,我最近遇到了同样的问题,由于我无法控制客户端安全协议,我的服务器最终一直冻结。

I solved it by Disposing the sslstream, which causes an Exception in the AuthenticateAsServer and thus allowed my server to continue.我通过处理 sslstream 解决了这个问题,这会导致 AuthenticateAsServer 出现异常,从而允许我的服务器继续运行。

here is the code fragment这是代码片段

    // wait for both server and client task to finish, check results
    if (!serverTask.Wait(TimeSpan.FromSeconds(1)))
    {
       sslStream.Dispose(); // this line will cause an exception in the server task (AuthenticateAsServer), which allows the server to continue ...
    }

Since your question led me to the root of my freezing issue, I though I will share my solution ...既然你的问题让我找到了我冻结问题的根源,我想我会分享我的解决方案......

Try:尝试:

socket.ReceiveTimeout = //some timeout in millis

I ran into this same issue, but the proposed dispose solution didn't work in my case.我遇到了同样的问题,但建议的处置解决方案在我的情况下不起作用。 My use case was a little different.我的用例有点不同。 I get a Socket from an async Begin/EndAcceptSocket off a TcpListener.我从 TcpListener 的异步 Begin/EndAcceptSocket 获得一个 Socket。 When I called AuthenticateAsServer with a client that had a protocol mismatch, it would never return, and disposing the stream didn't make it return either.当我使用协议不匹配的客户端调用 AuthenticateAsServer 时,它永远不会返回,并且处理流也不会使其返回。

What I found is that I had to set the socket.ReceiveTimeout as shown below.我发现我必须设置 socket.ReceiveTimeout 如下所示。

IAsyncResult asyncResult;//passed from BeginAcceptSocket callback
TcpListener listener = (TcpListener)asyncResult.AsyncState;
var socket = listener.EndAcceptSocket(asyncResult);
int timeoutInMillis;//set to whatever makes sense for your use case.

socket.ReceiveTimeout = timeoutInMillis; // This line fixed it for me

var stream = new SslStream(new NetworkStream(socket));
stream.AuthenticateAsServer(...); // This line doesn't hang any longer than the timeout.

Setting the receive timeout on the socket made sure that the AuthenticateAsServer call returned after the timeout instead of hanging forever in the case of a protocol mismatch.在套接字上设置接收超时可确保 AuthenticateAsServer 调用在超时后返回,而不是在协议不匹配的情况下永远挂起。 It may not be applicable in all scenarios, but in my case, I was never sending so much data that it should take longer than a few seconds.它可能并不适用于所有场景,但就我而言,我从未发送过如此多的数据,以至于它需要花费超过几秒钟的时间。

In all typical connect scenarios, it will just authenticate and I don't need the timeout, but it eliminated the edge case where it could hang forever.在所有典型的连接场景中,它只会进行身份验证而我不需要超时,但它消除了可能永远挂起的边缘情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SslStream.AuthenticateAsServer证书链 - SslStream.AuthenticateAsServer certificate chain sslStream.AuthenticateAsServer忽略RemoteCertificateValidationCallback - sslStream.AuthenticateAsServer ignores RemoteCertificateValidationCallback 如何为SslStream.AuthenticateAsServer()创建证书? - How to create certificate for SslStream.AuthenticateAsServer()? 为什么sslStream.AuthenticateAsServer不需要UAC和替代方法 - Why does sslStream.AuthenticateAsServer require no UAC and alternatives c#SSL TCPServer卡在SsLStream.AuthenticateAsServer() - c# SSL TCPServer stuck at SsLStream.AuthenticateAsServer() 在 C# 中,在服务器端使用 SslStream.AuthenticateAsServer() 有什么意义? - In C# what is the point of using SslStream.AuthenticateAsServer() on the server side? 为什么不支持在同一进程中使用同一证书调用 SslStream.AuthenticateAsServer 和 SslStream.AuthenticateAsClient? - Why is calling SslStream.AuthenticateAsServer and SslStream.AuthenticateAsClient with the same certificate in the same process not supported? 为什么SslStream.AuthenticateAsServer从Ubuntu失败但从Windows 10失败 - Why would SslStream.AuthenticateAsServer fail from Ubuntu but not from Windows 10 SslStream.AuthenticateAsServer异常-服务器模式SSL必须使用带有关联私钥的证书 - SslStream.AuthenticateAsServer exception - The server mode SSL must use a certificate with the associated private key 从SQL加载时,SslStream.AuthenticateAsServer证书失败,但从嵌入式文件加载时,SslStream.AuthenticateAsServer证书有效 - SslStream.AuthenticateAsServer certificate fails when loaded from SQL, but works when loaded from an embedded file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM