From c99d24cee96b775f1d899d70ee49a16d810b2ebb Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 22 Apr 2024 20:48:40 +1200 Subject: [PATCH 1/3] Introduce basic support for `close_read` and `close_write`. --- lib/openssl/ssl.rb | 11 +++++++++++ test/openssl/test_ssl.rb | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index 75a74a3f5..0568276a1 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -459,6 +459,17 @@ def session nil end + # Close the stream for reading. + def close_read + # Unsupported and ignored. + # Just don't read any more. + end + + # Close the stream for writing. + def close_write + stop + end + private def using_anon_cipher? diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 66d63a981..3df391fac 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -117,6 +117,30 @@ def test_socket_open_with_local_address_port_context } end + def test_socket_close_write + server_proc = proc do |ctx, ssl| + message = ssl.read + ssl.write(message) + ssl.close_write + ensure + ssl.close + end + + start_server(server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, context: ctx) + ssl.sync_close = true + ssl.connect + + message = "abc"*1024 + ssl.write message + ssl.close_write + assert_equal message, ssl.read + ensure + ssl&.close + end + end + def test_add_certificate ctx_proc = -> ctx { # Unset values set by start_server From c8377eaf8de82d2962d953a71e706d057da7871b Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sun, 28 Apr 2024 00:06:26 +1200 Subject: [PATCH 2/3] More documentation. --- lib/openssl/ssl.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index 0568276a1..787d6e01f 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -460,12 +460,27 @@ def session end # Close the stream for reading. + # This method is ignored by OpenSSL as there is no reasonable way to + # implement it, but exists for compatibility with IO. def close_read # Unsupported and ignored. # Just don't read any more. end - # Close the stream for writing. + # Closes the stream for writing. The behavior of this method depends on + # the version of OpenSSL and the TLS protocol in use. + # + # In TLS 1.3 and later: + # - Sends a 'close_notify' alert to the peer. + # - Does not wait for the peer's 'close_notify' alert in response. + # + # In TLS 1.2 and earlier: + # - Sends a 'close_notify' alert to the peer. + # - Waits for the peer's 'close_notify' alert in response. + # + # Therefore, on TLS 1.2, this method will cause the connection to be + # completely shut down. On TLS 1.3, the connection will remain open for + # reading only. def close_write stop end From 0697f2f8b4a8d812def1c34b4d6e2b03811026a5 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sun, 28 Apr 2024 18:09:49 +1200 Subject: [PATCH 3/3] Further clarification of documentation. --- lib/openssl/ssl.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index 787d6e01f..d28bf1a37 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -469,15 +469,15 @@ def close_read # Closes the stream for writing. The behavior of this method depends on # the version of OpenSSL and the TLS protocol in use. - # - # In TLS 1.3 and later: + # # - Sends a 'close_notify' alert to the peer. # - Does not wait for the peer's 'close_notify' alert in response. - # + # # In TLS 1.2 and earlier: - # - Sends a 'close_notify' alert to the peer. - # - Waits for the peer's 'close_notify' alert in response. - # + # - On receipt of a 'close_notify' alert, responds with a 'close_notify' + # alert of its own and close down the connection immediately, + # discarding any pending writes. + # # Therefore, on TLS 1.2, this method will cause the connection to be # completely shut down. On TLS 1.3, the connection will remain open for # reading only.