Spec-Zone.ru › Ruby 4.0
  1. OpenSSL::
  2. SSL::
  3. SSLSocket

класс OpenSSL::SSL::SSLSocket

Родительский класс:
Object
Подключённые модули:
OpenSSL::Buffering, OpenSSL::SSL::SocketForwarder

Атрибуты

context [R]

Объект SSLContext, используемый в этом соединении.

hostname [R]
io [R]

Базовый объект IO.

sync_close [RW]

Закрывать ли также базовый сокет при завершении соединения SSL/TLS. По умолчанию значение равно false.

to_io [R]

Базовый объект IO.

Открытые методы класса

new(io) → aSSLSocket Показать исходный код
new(io, ctx) → aSSLSocket
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
    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) == 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);
    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;
}

Создаёт новый сокет SSL из io, который должен быть настоящим объектом IO (а не объектом, подобным IO, который поддерживает методы read/write).

Если указан ctx, начальные параметры сокета SSL будут взяты из контекста.

Модуль OpenSSL::Buffering предоставляет дополнительные методы IO.

Этот метод заморозит объект SSLContext, если он указан; однако управление сеансами по-прежнему допускается в замороженном объекте SSLContext.

open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) Показать исходный код
# 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

Создаёт новый экземпляр SSLSocket. Параметры remotehost_ и remoteport_ используются для открытия TCPSocket. Если указаны localhost_ и localport_, эти параметры используются на локальном конце для установки соединения. Если указан context, начальные параметры сокета SSL будут взяты из контекста.

Примеры

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

с 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

Открытые методы экземпляра

accept → self Показать исходный код
static VALUE
ossl_ssl_accept(VALUE self)
{
    ossl_ssl_setup(self);

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

Ожидает, пока клиент SSL/TLS инициирует рукопожатие.

accept_nonblock([options]) → self Показать исходный код
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);
}

Инициирует рукопожатие SSL/TLS в качестве сервера в неблокирующем режиме.

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

Указав ключевой аргумент exception в false, можно задать, чтобы accept_nonblock не вызывал исключение IO::WaitReadable или IO::WaitWritable, а вместо этого возвращал символ :wait_readable или :wait_writable.

alpn_protocol → String | nil Показать исходный код
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);
}

Возвращает строку протокола ALPN, окончательно выбранного сервером во время рукопожатия.

cert → cert or nil Показать исходный код
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);
}

Сертификат X509 для этого конца сокета.

cipher → nil or [name, version, bits, alg_bits] Показать исходный код
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;
}

Возвращает набор шифров, фактически использованный в текущем сеансе, или nil, если сеанс не был установлен.

client_ca → [x509name, ...] or nil Показать исходный код
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);
}

Возвращает список центров сертификации клиента. Обратите внимание: в отличие от SSLContext#client_ca=, возвращается не массив объектов X509::Certificate, а экземпляры X509::Name, представляющие различающееся имя субъекта центра сертификации.

В режиме сервера возвращает список, заданный с помощью SSLContext#client_ca=. В режиме клиента возвращает список центров сертификации клиента, полученный от сервера.

close_read () Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 400
def close_read
  # Unsupported and ignored.
  # Just don't read any more.
end

Закрывает поток для чтения. Этот метод игнорируется в OpenSSL, поскольку разумного способа реализовать его нет, но он существует для совместимости с IO.

close_write () Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 419
def close_write
  stop
end

Закрывает поток для записи. Поведение этого метода зависит от версии OpenSSL и используемого протокола TLS.

  • Отправляет узлу-партнёру оповещение ‘close_notify’.

  • Не ожидает в ответ оповещение ‘close_notify’ от узла-партнёра.

В TLS 1.2 и более ранних версиях:

  • При получении оповещения ‘close_notify’ отправляет собственное оповещение ‘close_notify’ и немедленно закрывает соединение, отбрасывая все ожидающие записи.

Таким образом, в TLS 1.2 этот метод полностью закрывает соединение. В TLS 1.3 соединение остаётся открытым только для чтения.

connect → self Показать исходный код
static VALUE
ossl_ssl_connect(VALUE self)
{
    ossl_ssl_setup(self);

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

Инициирует рукопожатие SSL/TLS с сервером.

connect_nonblock([options]) → self Показать исходный код
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);
}

Инициирует рукопожатие SSL/TLS в качестве клиента в неблокирующем режиме.

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

Указав ключевой аргумент exception в false, можно задать, чтобы connect_nonblock не вызывал исключение IO::WaitReadable или IO::WaitWritable, а вместо этого возвращал символ :wait_readable или :wait_writable.

export_keying_material(label, length) → String Показать исходный код
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;
}

Позволяет использовать общий материал ключа сеанса в соответствии с RFC 5705.

finished_message → "finished message" Показать исходный код
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);
}

Возвращает последнее отправленное сообщение Finished

group → String or nil Показать исходный код
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);
}

Возвращает имя группы, использованной для согласования ключа при установлении текущего сеанса TLS.

hostname = hostname → hostname Показать исходный код
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;
}

Задаёт имя узла сервера, используемое для SNI. Это значение необходимо установить до вызова SSLSocket#connect.

npn_protocol → String | nil Показать исходный код
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 Показать исходный код
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;
}

Сертификат X509 узла-партнёра этого сокета.

peer_cert_chain → [cert, ...] or nil Показать исходный код
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;
}

Цепочка сертификатов X509 узла-партнёра этого сокета.

peer_finished_message → "peer finished message" Показать исходный код
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);
}

Возвращает последнее полученное сообщение Finished

peer_sigalg → String or nil Показать исходный код
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);
}

Возвращает имя алгоритма подписи — имя схемы подписи IANA, использованной узлом-партнёром для подписания рукопожатия TLS.

pending → Integer Показать исходный код
static VALUE
ossl_ssl_pending(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return INT2NUM(SSL_pending(ssl));
}

Количество байтов, доступных для немедленного чтения.

post_connection_check(hostname) → true Показать исходный код
# 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

Проверяет имя узла согласно RFC 6125.

Этот метод НЕОБХОДИМО вызвать после connect, чтобы убедиться, что имя узла удалённого партнёра проверено.

session → aSession Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 391
def session
  SSL::Session.new(self)
rescue SSL::Session::SessionError
  nil
end

Возвращает используемый в данный момент объект SSLSession или nil, если сеанс не установлен.

session = session → session Показать исходный код
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, который будет использоваться при установлении соединения.

session_reused? → true | false Показать исходный код
static VALUE
ossl_ssl_session_reused(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return SSL_session_reused(ssl) ? Qtrue : Qfalse;
}

Возвращает true, если во время рукопожатия было согласовано повторное использование сеанса.

sigalg → String or nil Показать исходный код
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);
}

Возвращает имя алгоритма подписи — имя схемы подписи IANA, использованной локальной стороной для подписания рукопожатия TLS.

ssl_version → String Показать исходный код
static VALUE
ossl_ssl_get_version(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return rb_str_new2(SSL_get_version(ssl));
}

Возвращает String, представляющую согласованную для соединения версию SSL/TLS, например «TLSv1.2».

state → string Показать исходный код
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 Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 357
def sysclose
  return if closed?
  stop
  io.close if sync_close
end

Отправляет узлу-партнёру уведомление «close notify» и пытается корректно завершить соединение SSL.

Если для sync_close установлено значение true, базовый объект IO также закрывается.

sysread(length) → string Показать исходный код
sysread(length, buffer) → buffer
static VALUE
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
{
    return ossl_ssl_read_internal(argc, argv, self, 0);
}

Читает length байт из соединения SSL. Если указан предварительно выделенный buffer, данные будут записаны в него.

syswrite(string) → Integer Показать исходный код
static VALUE
ossl_ssl_write(VALUE self, VALUE str)
{
    return ossl_ssl_write_internal(self, str, Qfalse);
}

Записывает string в соединение SSL.

tmp_key → PKey or nil Показать исходный код
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);
}

Возвращает эфемерный ключ, использованный при шифровании с прямой секретностью.

verify_result → Integer Показать исходный код
static VALUE
ossl_ssl_get_verify_result(VALUE self)
{
    SSL *ssl;

    GetSSL(self, ssl);

    return LONG2NUM(SSL_get_verify_result(ssl));
}

Возвращает результат проверки сертификатов узла-партнёра. Список кодов ошибок и их описания см. в verify(1).

Если сертификат узла-партнёра не был предоставлен, возвращается X509_V_OK.

Закрытые методы экземпляра

client_cert_cb () Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 431
def client_cert_cb
  @context.client_cert_cb
end
session_get_cb () Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 439
def session_get_cb
  @context.session_get_cb
end
session_new_cb () Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 435
def session_new_cb
  @context.session_new_cb
end
stop → nil Показать исходный код
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;
}

Отправляет узлу-партнёру уведомление «close notify» и пытается корректно завершить соединение SSL.

sysread_nonblock(length) → string Показать исходный код
sysread_nonblock(length, buffer) → buffer
sysread_nonblock(length[, buffer [, opts]) → buffer
static VALUE
ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
{
    return ossl_ssl_read_internal(argc, argv, self, 1);
}

Неблокирующая версия sysread. Вызывает исключение SSLError, если чтение приведёт к блокировке. Если передан аргумент «exception: false», этот метод возвращает символ :wait_readable, :wait_writable или nil вместо вызова исключения.

Читает length байт из соединения SSL. Если указан предварительно выделенный buffer, данные будут записаны в него.

syswrite_nonblock(string) → Integer Показать исходный код
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);
}

Неблокирующим образом записывает string в соединение SSL. Вызывает исключение SSLError, если запись приведёт к блокировке.

using_anon_cipher? () Показать исходный код
# 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

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API