Class: OpenSSL::SSL::SSLSocket

Inherits:
Object
  • Object
show all
Includes:
Buffering, SocketForwarder
Defined in:
lib/openssl/ssl.rb,
ext/rubysl/openssl/ossl_ssl.c

Constant Summary

Constants included from Buffering

Buffering::BLOCK_SIZE

Instance Attribute Summary collapse

Attributes included from Buffering

#sync

Instance Method Summary collapse

Methods included from SocketForwarder

#addr, #closed?, #do_not_reverse_lookup=, #fcntl, #getsockopt, #peeraddr, #setsockopt

Methods included from Buffering

#<<, #close, #each, #each_byte, #eof?, #flush, #getc, #gets, #print, #printf, #puts, #read, #read_nonblock, #readchar, #readline, #readlines, #readpartial, #ungetc, #write, #write_nonblock

Constructor Details

#new(io) ⇒ aSSLSocket #new(io, ctx) ⇒ 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 OpenSSL::Buffering module provides additional IO methods.

This method will freeze the SSLContext if one is provided; however, session management is still allowed in the frozen SSLContext.

Overloads:

  • #new(io) ⇒ aSSLSocket
  • #new(io, ctx) ⇒ aSSLSocket


1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1434

static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE io, v_ctx, verify_cb;
    SSL *ssl;
    SSL_CTX *ctx;

    TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
    if (ssl)
	ossl_raise(eSSLError, "SSL already initialized");

    if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 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 (rb_respond_to(io, rb_intern("nonblock=")))
	rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
    rb_ivar_set(self, id_i_io, io);

    ssl = SSL_new(ctx);
    if (!ssl)
	ossl_raise(eSSLError, NULL);
    RTYPEDDATA_DATA(self) = ssl;

    SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
    SSL_set_info_callback(ssl, ssl_info_cb);
    verify_cb = rb_attr_get(v_ctx, id_i_verify_callback);
    SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);

    rb_call_super(0, NULL);

    return self;
}

Instance Attribute Details

#contextObject (readonly)

The SSLContext object used in this connection.



256
257
258
# File 'lib/openssl/ssl.rb', line 256

def context
  @context
end

#hostnameObject (readonly)

Returns the value of attribute hostname.



248
249
250
# File 'lib/openssl/ssl.rb', line 248

def hostname
  @hostname
end

#ioObject (readonly) Also known as: to_io

The underlying IO object.



252
253
254
# File 'lib/openssl/ssl.rb', line 252

def io
  @io
end

#sync_closeObject

Whether to close the underlying socket as well, when the SSL/TLS connection is shut down. This defaults to false.



260
261
262
# File 'lib/openssl/ssl.rb', line 260

def sync_close
  @sync_close
end

Instance Method Details

#acceptself

Waits for a SSL/TLS client to initiate a handshake. The handshake may be started after unencrypted data has been sent over the socket.

Returns:

  • (self)


1625
1626
1627
1628
1629
1630
1631
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1625

static VALUE
ossl_ssl_accept(VALUE self)
{
    ossl_ssl_setup(self);

    return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
}

#accept_nonblock([options]) ⇒ self

Initiates the SSL/TLS handshake as a server in non-blocking manner.

# emulates blocking accept
begin
  ssl.accept_nonblock
rescue IO::WaitReadable
  IO.select([s2])
  retry
rescue IO::WaitWritable
  IO.select(nil, [s2])
  retry
end

By specifying ‘exception: false`, the options hash allows you to indicate that accept_nonblock should not raise an IO::WaitReadable or IO::WaitWritable exception, but return the symbol :wait_readable or :wait_writable instead.

Returns:

  • (self)


1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1655

static VALUE
ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
{
    VALUE opts;

    rb_scan_args(argc, argv, "0:", &opts);
    ossl_ssl_setup(self);

    return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
}

#alpn_protocolString | nil

Returns the ALPN protocol string that was finally selected by the server during the handshake.

Returns:

  • (String | nil)


2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2202

static VALUE
ossl_ssl_alpn_protocol(VALUE self)
{
    SSL *ssl;
    const unsigned char *out;
    unsigned int outlen;

    GetSSL(self, ssl);

    SSL_get0_alpn_selected(ssl, &out, &outlen);
    if (!outlen)
	return Qnil;
    else
	return rb_str_new((const char *) out, outlen);
}

#certnil

The X509 certificate for this socket endpoint.

Returns:

  • (nil)


1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1911

static VALUE
ossl_ssl_get_cert(VALUE self)
{
    SSL *ssl;
    X509 *cert = NULL;

    GetSSL(self, ssl);

    /*
     * Is this OpenSSL bug? Should add a ref?
     * TODO: Ask for.
     */
    cert = SSL_get_certificate(ssl); /* NO DUPs => DON'T FREE. */

    if (!cert) {
        return Qnil;
    }
    return ossl_x509_new(cert);
}

#cipherArray

The cipher being used for the current connection

Returns:

  • (Array)


2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2009

static VALUE
ossl_ssl_get_cipher(VALUE self)
{
    SSL *ssl;
    SSL_CIPHER *cipher;

    GetSSL(self, ssl);

    cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);

    return ossl_ssl_cipher_to_ary(cipher);
}

#client_caArray

Returns the list of client CAs. Please note that in contrast to SSLContext#client_ca= no array of X509::Certificate is returned but X509::Name instances of the CA’s subject distinguished name.

In server mode, returns the list set by SSLContext#client_ca=. In client mode, returns the list of client CAs sent from the server.

Returns:

  • (Array)


2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2157

static VALUE
ossl_ssl_get_client_ca_list(VALUE self)
{
    SSL *ssl;
    STACK_OF(X509_NAME) *ca;

    GetSSL(self, ssl);

    ca = SSL_get_client_CA_list(ssl);
    return ossl_x509name_sk2ary(ca);
}

#connectself

Initiates an SSL/TLS handshake with a server. The handshake may be started after unencrypted data has been sent over the socket.

Returns:

  • (self)


1577
1578
1579
1580
1581
1582
1583
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1577

static VALUE
ossl_ssl_connect(VALUE self)
{
    ossl_ssl_setup(self);

    return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
}

#connect_nonblock([options]) ⇒ self

Initiates the SSL/TLS handshake as a client in non-blocking manner.

# emulates blocking connect
begin
  ssl.connect_nonblock
rescue IO::WaitReadable
  IO.select([s2])
  retry
rescue IO::WaitWritable
  IO.select(nil, [s2])
  retry
end

By specifying ‘exception: false`, the options hash allows you to indicate that connect_nonblock should not raise an IO::WaitReadable or IO::WaitWritable exception, but return the symbol :wait_readable or :wait_writable instead.

Returns:

  • (self)


1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1607

static VALUE
ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
{
    VALUE opts;
    rb_scan_args(argc, argv, "0:", &opts);

    ossl_ssl_setup(self);

    return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
}

#hostname=(hostname) ⇒ Object (readonly)

Sets the server hostname used for SNI. This needs to be set before SSLSocket#connect.



2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2106

static VALUE
ossl_ssl_set_hostname(VALUE self, VALUE arg)
{
    SSL *ssl;
    char *hostname = NULL;

    GetSSL(self, ssl);

    if (!NIL_P(arg))
	hostname = StringValueCStr(arg);

    if (!SSL_set_tlsext_host_name(ssl, hostname))
	ossl_raise(eSSLError, NULL);

    /* for SSLSocket#hostname */
    rb_ivar_set(self, id_i_hostname, arg);

    return arg;
}

#npn_protocolString | nil

Returns the protocol string that was finally selected by the client during the handshake.

Returns:

  • (String | nil)


2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2177

static VALUE
ossl_ssl_npn_protocol(VALUE self)
{
    SSL *ssl;
    const unsigned char *out;
    unsigned int outlen;

    GetSSL(self, ssl);

    SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
    if (!outlen)
	return Qnil;
    else
	return rb_str_new((const char *) out, outlen);
}

#peer_certnil

The X509 certificate for this socket’s peer.

Returns:

  • (nil)


1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1937

static VALUE
ossl_ssl_get_peer_cert(VALUE self)
{
    SSL *ssl;
    X509 *cert = NULL;
    VALUE obj;

    GetSSL(self, ssl);

    cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */

    if (!cert) {
        return Qnil;
    }
    obj = ossl_x509_new(cert);
    X509_free(cert);

    return obj;
}

#peer_cert_chainArray?

The X509 certificate chain for this socket’s peer.

Returns:

  • (Array, nil)


1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1963

static VALUE
ossl_ssl_get_peer_cert_chain(VALUE self)
{
    SSL *ssl;
    STACK_OF(X509) *chain;
    X509 *cert;
    VALUE ary;
    int i, num;

    GetSSL(self, ssl);

    chain = SSL_get_peer_cert_chain(ssl);
    if(!chain) return Qnil;
    num = sk_X509_num(chain);
    ary = rb_ary_new2(num);
    for (i = 0; i < num; i++){
	cert = sk_X509_value(chain, i);
	rb_ary_push(ary, ossl_x509_new(cert));
    }

    return ary;
}

#pendingInteger

The number of bytes that are immediately available for reading.

Returns:



2051
2052
2053
2054
2055
2056
2057
2058
2059
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2051

static VALUE
ossl_ssl_pending(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return INT2NUM(SSL_pending(ssl));
}

#post_connection_check(hostname) ⇒ Object

call-seq:

ssl.post_connection_check(hostname) -> true

Perform hostname verification following RFC 6125.

This method MUST be called after calling #connect to ensure that the hostname of a remote peer has been verified.



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/openssl/ssl.rb', line 282

def post_connection_check(hostname)
  if peer_cert.nil?
    msg = "Peer verification enabled, but no certificate received."
    if using_anon_cipher?
      msg += " Anonymous cipher suite #{cipher[0]} was negotiated. " \
             "Anonymous suites must be disabled to use peer verification."
    end
    raise SSLError, msg
  end

  unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
    raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
  end
  return true
end

#sessionObject

call-seq:

ssl.session -> aSession

Returns the SSLSession object currently used, or nil if the session is not established.



303
304
305
306
307
# File 'lib/openssl/ssl.rb', line 303

def session
  SSL::Session.new(self)
rescue SSL::Session::SessionError
  nil
end

#session=(session) ⇒ Object

Sets the Session to be used when the connection is established.



2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2083

static VALUE
ossl_ssl_set_session(VALUE self, VALUE arg1)
{
    SSL *ssl;
    SSL_SESSION *sess;

    GetSSL(self, ssl);
    SafeGetSSLSession(arg1, sess);

    if (SSL_set_session(ssl, sess) != 1)
        ossl_raise(eSSLError, "SSL_set_session");

    return arg1;
}

#session_reused?Boolean

Returns true if a reused session was negotiated during the handshake.

Returns:

  • (Boolean)


2067
2068
2069
2070
2071
2072
2073
2074
2075
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2067

static VALUE
ossl_ssl_session_reused(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return SSL_session_reused(ssl) ? Qtrue : Qfalse;
}

#ssl_versionString

Returns a String representing the SSL/TLS version that was negotiated for the connection, for example “TLSv1.2”.

Returns:

  • (String)


1993
1994
1995
1996
1997
1998
1999
2000
2001
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1993

static VALUE
ossl_ssl_get_version(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return rb_str_new2(SSL_get_version(ssl));
}

#stateString

A description of the current connection state. This is for diagnostic purposes only.

Returns:

  • (String)


2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2029

static VALUE
ossl_ssl_get_state(VALUE self)
{
    SSL *ssl;
    VALUE ret;

    GetSSL(self, ssl);

    ret = rb_str_new2(SSL_state_string(ssl));
    if (ruby_verbose) {
        rb_str_cat2(ret, ": ");
        rb_str_cat2(ret, SSL_state_string_long(ssl));
    }
    return ret;
}

#syscloseObject

call-seq:

ssl.sysclose => nil

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.



269
270
271
272
273
# File 'lib/openssl/ssl.rb', line 269

def sysclose
  return if closed?
  stop
  io.close if sync_close
end

#sysread(length) ⇒ String #sysread(length, buffer) ⇒ Object

Reads length bytes from the SSL connection. If a pre-allocated buffer is provided the data will be written into it.

Overloads:

  • #sysread(length) ⇒ String

    Returns:

    • (String)


1762
1763
1764
1765
1766
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1762

static VALUE
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
{
    return ossl_ssl_read_internal(argc, argv, self, 0);
}

#syswrite(string) ⇒ Integer

Writes string to the SSL connection.

Returns:



1850
1851
1852
1853
1854
# File 'ext/rubysl/openssl/ossl_ssl.c', line 1850

static VALUE
ossl_ssl_write(VALUE self, VALUE str)
{
    return ossl_ssl_write_internal(self, str, Qfalse);
}

#tmp_keyPKey?

Returns the ephemeral key used in case of forward secrecy cipher.

Returns:



2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2226

static VALUE
ossl_ssl_tmp_key(VALUE self)
{
    SSL *ssl;
    EVP_PKEY *key;

    GetSSL(self, ssl);
    if (!SSL_get_server_tmp_key(ssl, &key))
	return Qnil;
    return ossl_pkey_new(key);
}

#verify_resultInteger

Returns the result of the peer certificates verification. See verify(1) for error values and descriptions.

If no peer certificate was presented X509_V_OK is returned.

Returns:



2136
2137
2138
2139
2140
2141
2142
2143
2144
# File 'ext/rubysl/openssl/ossl_ssl.c', line 2136

static VALUE
ossl_ssl_get_verify_result(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return INT2NUM(SSL_get_verify_result(ssl));
}