[ 
https://issues.apache.org/jira/browse/THRIFT-6120?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Dmytro Shteflyuk resolved THRIFT-6120.
--------------------------------------
    Fix Version/s: 0.25.0
       Resolution: Fixed

> Ruby SSLServerSocket client timeout does not cover the TLS handshake
> --------------------------------------------------------------------
>
>                 Key: THRIFT-6120
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6120
>             Project: Thrift
>          Issue Type: Bug
>          Components: Ruby - Library
>            Reporter: Dmytro Shteflyuk
>            Assignee: Dmytro Shteflyuk
>            Priority: Major
>             Fix For: 0.25.0
>
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> h3. Problem
> {{Thrift::SSLServerSocket}} applies {{client_timeout}} only after 
> {{OpenSSL::SSL::SSLServer#accept}} has completed. That accept call performs 
> the TLS handshake before the accepted connection is wrapped in a 
> {{Thrift::Socket}}, so the configured timeout cannot interrupt a client that 
> opens TCP but does not finish TLS negotiation.
> h3. Client impact
> A client that connects and then sends no TLS handshake data, or sends only a 
> partial handshake, can leave the server blocked in {{accept}} beyond the 
> configured client timeout. In {{SimpleServer}}, accepting connections happens 
> on the server thread, so no later client can be accepted until that handshake 
> completes or the peer disconnects.
> Successful TLS connections are unaffected; the problem is that the timeout 
> begins too late to cover the TLS setup it is expected to bound.
> h3. Reproduction
> From {{lib/rb}}, run the following against the current implementation:
> {code:ruby}
> require "openssl"
> require "socket"
> require "thrift"
> context = OpenSSL::SSL::SSLContext.new
> context.cert = OpenSSL::X509::Certificate.new(
>   File.read("../../test/keys/server.crt")
> )
> context.key = OpenSSL::PKey::RSA.new(
>   File.read("../../test/keys/server.key")
> )
> server = Thrift::SSLServerSocket.new(
>   "127.0.0.1",
>   0,
>   context,
>   client_timeout: 0.05
> )
> server.listen
> client = TCPSocket.new(
>   "127.0.0.1",
>   server.to_io.local_address.ip_port
> )
> accept_thread = Thread.new { server.accept }
> sleep 0.2
> puts(
>   "configured_client_timeout=0.05 " \
>   "accept_still_blocked_after=0.2 " \
>   "timed_out=#{accept_thread.alive?}"
> )
> client.close
> accept_thread.join
> server.close
> {code}
> The configured timeout is 50 milliseconds, but after 200 milliseconds the 
> accept operation is still blocked:
> {code}
> configured_client_timeout=0.05 accept_still_blocked_after=0.2 timed_out=true
> {code}
> The same behavior occurs when the peer sends an incomplete TLS handshake and 
> then stops.
> h3. Expected behavior
> The configured client timeout should apply to TLS negotiation as one 
> monotonic deadline. If the handshake does not complete in time, the accepted 
> socket should be closed and {{accept}} should raise a typed TLS error so the 
> server can continue accepting other connections. A completed TLS handshake 
> should still return a normal {{Thrift::Socket}} with the configured timeout.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to