class OpenSSL::SSL::SSLSocket - Documentation for Ruby 4.0
Description: Documentation for the OpenSSL::SSL::SSLSocket class
Keywords: ruby,class,OpenSSL::SSL::SSLSocket

🔍

No recent searches

# class OpenSSL::SSL::SSLSocket

### Attributes

context [R]

The `SSLContext` object used in this connection.

hostname [R]
io [R]

The underlying `IO` object.

sync_close [RW]

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

to_io [R]

The underlying `IO` object.

### Public Class Methods

new(io) → aSSLSocket
new(io, ctx) → aSSLSocket
new(io, ctx, sync_close:) → aSSLSocket
Source

    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;

        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, &opts) == 1)
            v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);

        if (!kw_ids[0]) {
            kw_ids[0] = rb_intern_const("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]);
        }

        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);
        Check_Type(io, T_FILE);
        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);

        rb_call_super(0, NULL);

        return self;
    }

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; however, session management is still allowed in the frozen `SSLContext`.

open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 465
    def open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
      sock = ::TCPSocket.open(remote_host, remote_port, local_host, local_port)
      if context.nil?
        return OpenSSL::SSL::SSLSocket.new(sock)
      else
        return OpenSSL::SSL::SSLSocket.new(sock, context)
      end
    end

Creates a new instance of `SSLSocket`. remotehost_ and remoteport_ are used to open `TCPSocket`. If localhost_ and localport_ are specified, then those parameters are used on the local end to establish the connection. If context is provided, the `SSL` Sockets initial params will be taken from the context.

### Examples

    sock = OpenSSL::SSL::SSLSocket.open('localhost', 443)
    sock.connect # Initiates a connection to localhost:443

with SSLContext:

    ctx = OpenSSL::SSL::SSLContext.new
    sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx)
    sock.connect # Initiates a connection to localhost:443 with SSLContext

### Public Instance Methods

accept → self
Source

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

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

Waits for a SSL/TLS client to initiate a handshake.

accept_nonblock([options]) → self
Source

    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);
    }

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 a keyword argument exception to `false`, you can indicate that `accept_nonblock` should not raise an `IO::WaitReadable` or `IO::WaitWritable` exception, but return the symbol `:wait_readable` or `:wait_writable` instead.

alpn_protocol → String | nil
Source

    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);
    }

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

cert → cert or nil
Source

    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);
    }

The `X509` certificate for this socket endpoint.

cipher → nil or [name, version, bits, alg_bits]
Source

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

        GetSSL(self, ssl);
        cipher = SSL_get_current_cipher(ssl);
        return cipher ? ossl_ssl_cipher_to_ary(cipher) : Qnil;
    }

Returns the cipher suite actually used in the current session, or nil if no session has been established.

client_ca → [x509name, ...] or nil
Source

    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);
        if (!ca)
            return Qnil;
        return ossl_x509name_sk2ary(ca);
    }

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.

close_read ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 400
    def close_read
      # Unsupported and ignored.
      # Just don't read any more.
    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`.

close_write ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 419
    def close_write
      stop
    end

Closes the stream for writing. The behavior of this method depends on the version of `OpenSSL` and the TLS protocol in use.

- 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:

- 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.

connect → self
Source

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

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

Initiates an SSL/TLS handshake with a server.

connect_nonblock([options]) → self
Source

    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);
    }

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 a keyword argument exception to `false`, you can indicate that `connect_nonblock` should not raise an `IO::WaitReadable` or `IO::WaitWritable` exception, but return the symbol `:wait_readable` or `:wait_writable` instead.

export_keying_material(label, length) → String
Source

    static VALUE
    ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self)
    {
        SSL *ssl;
        VALUE str;
        VALUE label;
        VALUE length;
        VALUE context;
        unsigned char *p;
        size_t len;
        int use_ctx = 0;
        unsigned char *ctx = NULL;
        size_t ctx_len = 0;
        int ret;

        rb_scan_args(argc, argv, "21", &label, &length, &context);
        StringValue(label);

        GetSSL(self, ssl);

        len = (size_t)NUM2LONG(length);
        str = rb_str_new(0, len);
        p = (unsigned char *)RSTRING_PTR(str);
        if (!NIL_P(context)) {
            use_ctx = 1;
            StringValue(context);
            ctx = (unsigned char *)RSTRING_PTR(context);
            ctx_len = RSTRING_LEN(context);
        }
        ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label),
                                         RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
        if (ret == 0 || ret == -1) {
            ossl_raise(eSSLError, "SSL_export_keying_material");
        }
        return str;
    }

Enables use of shared session key material in accordance with RFC 5705.

finished_message → "finished message"
Source

    static VALUE
    ossl_ssl_get_finished(VALUE self)
    {
        SSL *ssl;
        char sizer[1], *buf;
        size_t len;

        GetSSL(self, ssl);

        len = SSL_get_finished(ssl, sizer, 0);
        if (len == 0)
            return Qnil;

        buf = ALLOCA_N(char, len);
        SSL_get_finished(ssl, buf, len);
        return rb_str_new(buf, len);
    }

Returns the last Finished message sent

group → String or nil
Source

    static VALUE
    ossl_ssl_get_group(VALUE self)
    {
        SSL *ssl;
        const char *name;

        GetSSL(self, ssl);
        if (!(name = SSL_get0_group_name(ssl)))
            return Qnil;
        return rb_str_new_cstr(name);
    }

Returns the name of the group that was used for the key agreement of the current TLS session establishment.

hostname = hostname → hostname
Source

    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;
    }

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

npn_protocol → String | nil
Source

    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);
    }

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

peer_cert → cert or nil
Source

    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;
    }

The `X509` certificate for this socket’s peer.

peer_cert_chain → [cert, ...] or nil
Source

    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;
    }

The `X509` certificate chain for this socket’s peer.

peer_finished_message → "peer finished message"
Source

    static VALUE
    ossl_ssl_get_peer_finished(VALUE self)
    {
        SSL *ssl;
        char sizer[1], *buf;
        size_t len;

        GetSSL(self, ssl);

        len = SSL_get_peer_finished(ssl, sizer, 0);
        if (len == 0)
            return Qnil;

        buf = ALLOCA_N(char, len);
        SSL_get_peer_finished(ssl, buf, len);
        return rb_str_new(buf, len);
    }

Returns the last Finished message received

peer_sigalg → String or nil
Source

    static VALUE
    ossl_ssl_get_peer_sigalg(VALUE self)
    {
        SSL *ssl;
        const char *name;

        GetSSL(self, ssl);
        if (!SSL_get0_peer_signature_name(ssl, &name))
            return Qnil;
        return rb_str_new_cstr(name);
    }

Returns the signature algorithm name, the IANA name of the signature scheme used by the peer to sign the TLS handshake.

pending → Integer
Source

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

        GetSSL(self, ssl);

        return INT2NUM(SSL_pending(ssl));
    }

The number of bytes that are immediately available for reading.

post_connection_check(hostname) → true
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 370
    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

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.

session → aSession
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 391
    def session
      SSL::Session.new(self)
    rescue SSL::Session::SessionError
      nil
    end

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

session = session → session
Source

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

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

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

        return arg1;
    }

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

session_reused? → true | false
Source

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

        GetSSL(self, ssl);

        return SSL_session_reused(ssl) ? Qtrue : Qfalse;
    }

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

sigalg → String or nil
Source

    static VALUE
    ossl_ssl_get_sigalg(VALUE self)
    {
        SSL *ssl;
        const char *name;

        GetSSL(self, ssl);
        if (!SSL_get0_signature_name(ssl, &name))
            return Qnil;
        return rb_str_new_cstr(name);
    }

Returns the signature algorithm name, the IANA name of the signature scheme used by the local to sign the TLS handshake.

ssl_version → String
Source

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

        GetSSL(self, ssl);

        return rb_str_new2(SSL_get_version(ssl));
    }

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

state → string
Source

    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;
    }

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

sysclose → nil
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 357
    def sysclose
      return if closed?
      stop
      io.close if sync_close
    end

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.

sysread(length) → string
sysread(length, buffer) → buffer
Source

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

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

syswrite(string) → Integer
Source

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

Writes string to the `SSL` connection.

tmp_key → PKey or nil
Source

    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_wrap(key);
    }

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

verify_result → Integer
Source

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

        GetSSL(self, ssl);

        return LONG2NUM(SSL_get_verify_result(ssl));
    }

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.

### Private Instance Methods

client_cert_cb ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 431
    def client_cert_cb
      @context.client_cert_cb
    end

session_get_cb ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 439
    def session_get_cb
      @context.session_get_cb
    end

session_new_cb ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 435
    def session_new_cb
      @context.session_new_cb
    end

stop → nil
Source

    static VALUE
    ossl_ssl_stop(VALUE self)
    {
        SSL *ssl;
        int ret;

        GetSSL(self, ssl);
        if (!ssl_started(ssl))
            return Qnil;
        ret = SSL_shutdown(ssl);
        if (ret == 1) /* Have already received close_notify */
            return Qnil;
        if (ret == 0) /* Sent close_notify, but we don't wait for reply */
            return Qnil;

        /*
         * XXX: Something happened. Possibly it failed because the underlying socket
         * is not writable/readable, since it is in non-blocking mode. We should do
         * some proper error handling using SSL_get_error() and maybe retry, but we
         * can't block here. Give up for now.
         */
        ossl_clear_error();
        return Qnil;
    }

Sends “close notify” to the peer and tries to shut down the `SSL` connection gracefully.

sysread_nonblock(length) → string
sysread_nonblock(length, buffer) → buffer
sysread_nonblock(length[, buffer [, opts]) → buffer
Source

    static VALUE
    ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
    {
        return ossl_ssl_read_internal(argc, argv, self, 1);
    }

A non-blocking version of `sysread`. Raises an `SSLError` if reading would block. If “exception: false” is passed, this method returns a symbol of :wait_readable, :wait_writable, or nil, rather than raising an exception.

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

syswrite_nonblock(string) → Integer
Source

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

        rb_scan_args(argc, argv, "1:", &str, &opts);

        return ossl_ssl_write_internal(self, str, opts);
    }

Writes string to the `SSL` connection in a non-blocking manner. Raises an `SSLError` if writing would block.

using_anon_cipher? ()
Source

    # File ext/openssl/lib/openssl/ssl.rb, line 425
    def using_anon_cipher?
      ctx = OpenSSL::SSL::SSLContext.new
      ctx.ciphers = "aNULL"
      ctx.ciphers.include?(cipher)
    end