Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback;
static ID id_i_io, id_i_context, id_i_hostname;
static ID id_i_io, id_i_context, id_i_hostname, id_i_sync_close;

static int ossl_ssl_ex_ptr_idx;
static int ossl_sslctx_ex_ptr_idx;
Expand Down Expand Up @@ -1616,13 +1616,18 @@ peeraddr_ip_str(VALUE self)
* call-seq:
* SSLSocket.new(io) => aSSLSocket
* SSLSocket.new(io, ctx) => aSSLSocket
* SSLSocket.new(io, ctx, sync_close:) => aSSLSocket
*
* Creates a new SSL socket from _io_ which must be a real IO object (not an
* IO-like object that responds to read/write).
*
* If _ctx_ is provided the SSL Sockets initial params will be taken from
* the context.
*
* The optional _sync_close_ keyword parameter sets the _sync_close_ instance
* variable. Setting this to +true+ will cause the underlying socket to be
* closed when the SSL/TLS connection is shut down.
*
* The OpenSSL::Buffering module provides additional IO methods.
*
* This method will freeze the SSLContext if one is provided;
Expand All @@ -1631,6 +1636,10 @@ peeraddr_ip_str(VALUE self)
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
static ID kw_ids[1];
VALUE kw_args[1];
VALUE opts;

VALUE io, v_ctx;
SSL *ssl;
SSL_CTX *ctx;
Expand All @@ -1639,13 +1648,25 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
if (ssl)
ossl_raise(eSSLError, "SSL already initialized");

if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
if (rb_scan_args(argc, argv, "11:", &io, &v_ctx, &opts) == 1)
v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);

GetSSLCTX(v_ctx, ctx);
rb_ivar_set(self, id_i_context, v_ctx);
ossl_sslctx_setup(v_ctx);

if (!NIL_P(opts)) {
if (!kw_ids[0]) {
CONST_ID(kw_ids[0], "sync_close");
}

rb_get_kwargs(opts, kw_ids, 0, 1, kw_args);
if (kw_args[0] != Qundef) {
rb_ivar_set(self, id_i_sync_close, kw_args[0]);
}
}


if (rb_respond_to(io, rb_intern("nonblock=")))
rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
Check_Type(io, T_FILE);
Expand Down Expand Up @@ -3300,5 +3321,6 @@ Init_ossl_ssl(void)
DefIVarID(io);
DefIVarID(context);
DefIVarID(hostname);
DefIVarID(sync_close);
#endif /* !defined(OPENSSL_NO_SOCK) */
}
16 changes: 16 additions & 0 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,22 @@ def test_sync_close
end
end

def test_sync_close_initialize_opt
start_server do |port|
begin
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, sync_close: true)
assert_equal true, ssl.sync_close
ssl.connect
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
ssl.close
assert_predicate sock, :closed?
ensure
sock&.close
end
end
end

def test_copy_stream
start_server do |port|
server_connect(port) do |ssl|
Expand Down