class OpenSSL::SSL::SSLSocket - RDoc Documentation (original) (raw)
Attributes
context[R]
The SSLContext object used in this connection.
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 click to toggle source
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.
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;
}
Private Class Methods
open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) click to toggle source
Creates a new instance of SSLSocket. _remote_host_ and _remote_port_ are used to open TCPSocket. If _local_host_ and _local_port_ 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
with SSLContext:
ctx = OpenSSL::SSL::SSLContext.new sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx) sock.connect
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
Public Instance Methods
accept → self click to toggle source
Waits for a SSL/TLS client to initiate a handshake. The handshake may be started after unencrypted data has been sent over the socket.
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 click to toggle source
Initiates the SSL/TLS handshake as a server in non-blocking manner.
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.
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_protocol → String | nil click to toggle source
Returns the ALPN protocol string that was finally selected by the server during the handshake.
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);
}
cert → cert or nil click to toggle source
The X509 certificate for this socket endpoint.
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);
}
cipher → nil or [name, version, bits, alg_bits] click to toggle source
Returns the cipher suite actually used in the current session, or nil if no session has been established.
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;
}
client_ca → [x509name, ...] click to toggle source
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.
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);
}
connect → self click to toggle source
Initiates an SSL/TLS handshake with a server. The handshake may be started after unencrypted data has been sent over the socket.
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 click to toggle source
Initiates the SSL/TLS handshake as a client in non-blocking manner.
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.
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);
}
finished_message → "finished message" click to toggle source
Returns the last Finished message sent
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);
}
hostname = hostname → hostname click to toggle source
Sets the server hostname used for SNI. This needs to be set before SSLSocket#connect.
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_protocol → String | nil click to toggle source
Returns the protocol string that was finally selected by the client during the handshake.
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_cert → cert or nil click to toggle source
The X509 certificate for this socket's peer.
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_chain → [cert, ...] or nil click to toggle source
The X509 certificate chain for this socket's peer.
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;
}
peer_finished_message → "peer finished message" click to toggle source
Returns the last Finished message received
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);
}
pending → Integer click to toggle source
The number of bytes that are immediately available for reading.
static VALUE ossl_ssl_pending(VALUE self) { SSL *ssl;
GetSSL(self, ssl);
return INT2NUM(SSL_pending(ssl));
}
post_connection_check(hostname) → true click to toggle source
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.
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
session → aSession click to toggle source
Returns the SSLSession object currently used, or nil if the session is not established.
def session SSL::Session.new(self) rescue SSL::Session::SessionError nil end
session = session → session click to toggle source
Sets the Session to be used when the connection is established.
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;
}
session_reused? → true | false click to toggle source
Returns true
if a reused session was negotiated during the handshake.
static VALUE ossl_ssl_session_reused(VALUE self) { SSL *ssl;
GetSSL(self, ssl);
return SSL_session_reused(ssl) ? Qtrue : Qfalse;
}
ssl_version → String click to toggle source
Returns a String representing the SSL/TLS version that was negotiated for the connection, for example “TLSv1.2”.
static VALUE ossl_ssl_get_version(VALUE self) { SSL *ssl;
GetSSL(self, ssl);
return rb_str_new2(SSL_get_version(ssl));
}
state → string click to toggle source
A description of the current connection state. This is for diagnostic purposes only.
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;
}
sysclose → nil click to toggle source
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 io.close if sync_close end
sysread(length) → string click to toggle source
sysread(length, buffer) → buffer
Reads length bytes from the SSL connection. If a pre-allocated buffer is provided the data will be written into it.
static VALUE ossl_ssl_read(int argc, VALUE *argv, VALUE self) { return ossl_ssl_read_internal(argc, argv, self, 0); }
syswrite(string) → Integer click to toggle source
Writes string to the SSL connection.
static VALUE ossl_ssl_write(VALUE self, VALUE str) { return ossl_ssl_write_internal(self, str, Qfalse); }
tmp_key → PKey or nil click to toggle source
Returns the ephemeral key used in case of forward secrecy cipher.
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_result → Integer click to toggle source
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.
static VALUE ossl_ssl_get_verify_result(VALUE self) { SSL *ssl;
GetSSL(self, ssl);
return LONG2NUM(SSL_get_verify_result(ssl));
}
Private Instance Methods
client_cert_cb() click to toggle source
def client_cert_cb @context.client_cert_cb end
session_get_cb() click to toggle source
def session_get_cb @context.session_get_cb end
session_new_cb() click to toggle source
def session_new_cb @context.session_new_cb end
stop → nil click to toggle source
Sends “close notify” to the peer and tries to shut down the SSL connection gracefully.
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;
}
sysread_nonblock(length) → string click to toggle source
sysread_nonblock(length, buffer) → buffer
sysread_nonblock(length[, buffer [, opts]) → buffer
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.
static VALUE ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self) { return ossl_ssl_read_internal(argc, argv, self, 1); }
syswrite_nonblock(string) → Integer click to toggle source
Writes string to the SSL connection in a non-blocking manner. Raises an SSLError if writing would block.
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);
}
tmp_dh_callback() click to toggle source
def tmp_dh_callback @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK end
tmp_ecdh_callback() click to toggle source
def tmp_ecdh_callback @context.tmp_ecdh_callback end
using_anon_cipher?() click to toggle source
def using_anon_cipher? ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" ctx.ciphers.include?(cipher) end