aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/openssl/ossl_ssl.c14
-rw-r--r--lib/openssl/ssl.rb5
-rw-r--r--test/test_ssl.rb22
3 files changed, 30 insertions, 11 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 87df7f9f..d5ea1304 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1601,23 +1601,17 @@ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
* call-seq:
* ssl.stop => nil
*
- * Stops the SSL connection and prepares it for another connection.
+ * Sends "close notify" to the peer and tries to shut down the SSL connection
+ * gracefully.
*/
static VALUE
ossl_ssl_stop(VALUE self)
{
SSL *ssl;
- /* ossl_ssl_data_get_struct() is not usable here because it may return
- * from this function; */
-
- GetSSL(self, ssl);
+ ossl_ssl_data_get_struct(self, ssl);
- if (ssl) {
- ossl_ssl_shutdown(ssl);
- SSL_free(ssl);
- }
- DATA_PTR(self) = NULL;
+ ossl_ssl_shutdown(ssl);
return Qnil;
}
diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb
index 57519f2c..98937570 100644
--- a/lib/openssl/ssl.rb
+++ b/lib/openssl/ssl.rb
@@ -290,7 +290,10 @@ module OpenSSL
# call-seq:
# ssl.sysclose => nil
#
- # Shuts down the SSL connection and prepares it for another connection.
+ # Sends "close notify" to the peer and tries to shut down the SSL
+ # connection gracefully.
+ #
+ # If sync_close is set to +true+, the underlying IO is also closed.
def sysclose
return if closed?
stop
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index 32f7cfde..cb119dcd 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -1169,6 +1169,28 @@ end
}
end
+ def test_close_and_socket_close_while_connecting
+ # test it doesn't cause a segmentation fault
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ciphers = "aNULL"
+
+ sock1, sock2 = socketpair
+ ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
+ ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx)
+
+ t = Thread.new { ssl1.connect }
+ ssl2.accept
+
+ ssl1.close
+ sock1.close
+ t.value rescue nil
+ ensure
+ ssl1.close if ssl1
+ ssl2.close if ssl2
+ sock1.close if sock1
+ sock2.close if sock2
+ end
+
def test_get_ephemeral_key
return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
pkey = OpenSSL::PKey