Spec-Zone.ru › Ruby 3.4
  1. OpenSSL::
  2. SSL::
  3. SSLContext

class OpenSSL::SSL::SSLContext

Родительский класс:
Object

SSLContext используется для настройки различных параметров сертификатов, алгоритмов, проверки, кэширования сеансов и т. д. SSLContext используется для создания SSLSocket.

Все атрибуты необходимо задать до создания SSLSocket, поскольку после этого SSLContext будет заморожен.

Константы

DH_ffdhe2048
METHODS

Список доступных методов SSL/TLS. Эта константа предоставляется только для обратной совместимости.

METHODS_MAP
SESSION_CACHE_BOTH

Сеансы клиента и сервера добавляются в кэш сеансов

SESSION_CACHE_CLIENT

Сеансы клиента добавляются в кэш сеансов

SESSION_CACHE_NO_AUTO_CLEAR

Обычно кэш сеансов проверяется на наличие истёкших сеансов каждые 255 подключений. Поскольку это может привести к задержке, которую нельзя контролировать, автоматическую очистку можно отключить и явно вызвать flush_sessions.

SESSION_CACHE_NO_INTERNAL

Включает параметры SESSION_CACHE_NO_INTERNAL_LOOKUP и SESSION_CACHE_NO_INTERNAL_STORE.

SESSION_CACHE_NO_INTERNAL_LOOKUP

Всегда выполнять поиск сеансов во внешнем хранилище, даже если они находятся во внутреннем кэше.

Этот флаг не влияет на клиентов

SESSION_CACHE_NO_INTERNAL_STORE

Никогда не сохранять сеансы автоматически во внутреннем хранилище.

SESSION_CACHE_OFF

Кэширование сеансов клиента или сервера отключено

SESSION_CACHE_SERVER

Сеансы сервера добавляются в кэш сеансов

Атрибуты

alpn_protocols [RW]

Enumerable строк. Каждая String представляет протокол, который будет объявлен в списке протоколов, поддерживаемых для согласования протокола прикладного уровня (ALPN). Поддерживается в OpenSSL версии 1.0.2 и выше. Не влияет на серверную сторону. Если не задан явно, расширение ALPN не будет включено в рукопожатие.

Пример

ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"]
alpn_select_cb [RW]

Обратный вызов, вызываемый на серверной стороне, когда серверу необходимо выбрать протокол из списка, отправленного клиентом. Поддерживается в OpenSSL версии 1.0.2 и выше. Обратный вызов должен возвращать один из протоколов, объявленных клиентом. Если ни один из них не подходит, ошибка, вызванная в обратном вызове, приведёт к сбою рукопожатия. Если этот обратный вызов явно не задан, расширение ALPN на сервере не поддерживается — все протоколы, объявленные клиентом, будут проигнорированы.

Пример

ctx.alpn_select_cb = lambda do |protocols|
  # inspect the protocols and select one
  protocols.first
end
ca_file [RW]

Путь к файлу, содержащему сертификат УЦ в формате PEM

ca_path [RW]

Путь к каталогу, содержащему сертификаты УЦ в формате PEM.

Файлы ищутся по хэш-значению имени субъекта X509.

cert [RW]

Сертификат контекста

Атрибуты cert, key и extra_chain_cert устарели. Вместо них рекомендуется использовать add_certificate.

cert_store [RW]

OpenSSL::X509::Store, используемое для проверки сертификатов.

client_ca [RW]

Сертификат или Array сертификатов, которые будут отправлены клиенту.

client_cert_cb [RW]

Обратный вызов, вызываемый, когда сервер запрашивает сертификат клиента, но сертификат не задан.

Обратный вызов вызывается с объектом Session и должен возвращать Array, содержащий OpenSSL::X509::Certificate и OpenSSL::PKey. Если возвращается любое другое значение, рукопожатие приостанавливается.

extra_chain_cert [RW]

Array дополнительных сертификатов X509, добавляемых в цепочку сертификатов.

Атрибуты cert, key и extra_chain_cert устарели. Вместо них рекомендуется использовать add_certificate.

key [RW]

Закрытый ключ контекста

Атрибуты cert, key и extra_chain_cert устарели. Вместо них рекомендуется использовать add_certificate.

keylog_cb [RW]

Обратный вызов, вызываемый при создании или получении ключевого материала TLS, чтобы приложения могли сохранять этот материал для отладки.

Обратный вызов вызывается с объектом SSLSocket и строкой, содержащей ключевой материал в формате, используемом NSS для отладочного вывода SSLKEYLOGFILE.

Совместимо только с OpenSSL версии >= 1.1.1. Хотя LibreSSL реализует SSL_CTX_set_keylog_callback() начиная с версии 3.4.2, эта функция ничего не делает (см. github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).

Пример

context.keylog_cb = proc do |_sock, line|
  File.open('ssl_keylog_file', "a") do |f|
    f.write("#{line}\n")
  end
end
npn_protocols [RW]

Enumerable строк. Каждая String представляет протокол, который будет объявлен в списке протоколов, поддерживаемых для согласования следующего протокола (NPN). Поддерживается в OpenSSL версии 1.0.1 и выше. Не влияет на клиентскую сторону. Если не задан явно, сервер не отправит расширение NPN в рукопожатии.

Пример

ctx.npn_protocols = ["http/1.1", "spdy/2"]
npn_select_cb [RW]

Обратный вызов, вызываемый на клиентской стороне, когда клиенту необходимо выбрать протокол из списка, отправленного сервером. Поддерживается в OpenSSL версии 1.0.1 и выше. Клиент ДОЛЖЕН выбрать один из протоколов, объявленных сервером. Если ни один из них не подходит, ошибка, вызванная в обратном вызове, приведёт к сбою рукопожатия. Если этот обратный вызов явно не задан, расширение NPN на клиенте не поддерживается — все протоколы, объявленные сервером, будут проигнорированы.

Пример

ctx.npn_select_cb = lambda do |protocols|
  # inspect the protocols and select one
  protocols.first
end
renegotiation_cb [RW]

Обратный вызов, вызываемый при каждом начале нового рукопожатия в уже установленном соединении. Может использоваться для полного отключения повторного согласования.

Обратный вызов вызывается с активным объектом SSLSocket. Возвращаемое значение обратного вызова игнорируется. Нормальный возврат означает «одобрение» повторного согласования, и процесс будет продолжен. Чтобы запретить повторное согласование и отменить процесс, вызовите исключение внутри обратного вызова.

Отключение повторного согласования клиентом

При работе сервера часто требуется полностью отключить повторное согласование со стороны клиента. Для реализации этой возможности можно использовать следующий обратный вызов:

ctx.renegotiation_cb = lambda do |ssl|
  raise RuntimeError, "Client renegotiation disabled"
end
servername_cb [RW]

Обратный вызов, вызываемый при подключении для различения нескольких имён серверов.

Обратный вызов вызывается с объектом SSLSocket и именем сервера. Он должен возвращать SSLContext для этого имени сервера или nil.

session_get_cb [RW]

Обратный вызов, вызываемый на сервере, когда клиент предлагает сеанс, но серверу не удаётся найти его во внутреннем кэше.

Обратный вызов вызывается с объектом SSLSocket и идентификатором сеанса. Обратный вызов может вернуть Session из внешнего кэша.

session_id_context [RW]

Задаёт контекст, в котором можно повторно использовать сеанс. Это позволяет различать сеансы нескольких приложений, например, по имени.

session_new_cb [RW]

Обратный вызов, вызываемый при согласовании нового сеанса.

Обратный вызов вызывается с объектом SSLSocket. Если возвращается false, сеанс будет удалён из внутреннего кэша.

session_remove_cb [RW]

Обратный вызов, вызываемый при удалении сеанса из внутреннего кэша.

Обратный вызов вызывается с объектом SSLContext и объектом Session.

ВАЖНОЕ ЗАМЕЧАНИЕ: В настоящее время безопасно использовать этот механизм в многопоточном приложении невозможно. Обратный вызов вызывается внутри глобальной блокировки и может случайным образом привести к взаимной блокировке при переключении потоков Ruby.

ssl_timeout [RW]

Максимальный срок действия сеанса в секундах.

timeout [RW]

Максимальный срок действия сеанса в секундах.

tmp_dh_callback [RW]

Обратный вызов, вызываемый, когда для эфемерного обмена ключами DH требуются параметры DH.

Обратный вызов вызывается с объектом SSLSocket, флагом, указывающим на использование экспортного шифра, и требуемой длиной ключа.

Обратный вызов должен возвращать экземпляр OpenSSL::PKey::DH с соответствующей длиной ключа.

Устарел в версии 3.0. Вместо него используйте tmp_dh=.

verify_callback [RW]

Обратный вызов для дополнительной проверки сертификатов. Обратный вызов вызывается для каждого сертификата в цепочке.

Обратный вызов вызывается с двумя значениями. preverify_ok указывает, прошла ли проверка (true) или нет (false). store_context — это OpenSSL::X509::StoreContext, содержащий контекст, использованный для проверки сертификата.

Если обратный вызов возвращает false, проверка цепочки немедленно прекращается, после чего отправляется оповещение bad_certificate.

verify_depth [RW]

Количество сертификатов УЦ, которые следует пройти при проверке цепочки сертификатов.

verify_hostname [RW]

Проверять ли, действителен ли сертификат сервера для имени хоста.

Для работы этой функции verify_mode должен быть установлен в VERIFY_PEER, а имя хоста сервера должно быть задано с помощью OpenSSL::SSL::SSLSocket#hostname=.

verify_mode [RW]

Режим проверки Session.

Допустимые режимы: VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE, VERIFY_FAIL_IF_NO_PEER_CERT; они определены в OpenSSL::SSL

По умолчанию используется режим VERIFY_NONE, который вообще не выполняет проверку.

Подробности см. в SSL_CTX_set_verify(3).

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

new → ctx Показать исходный код
new(:TLSv1) → ctx
new("SSLv23") → ctx
# File ext/openssl/lib/openssl/ssl.rb, line 127
def initialize(version = nil)
  self.ssl_version = version if version
  self.verify_mode = OpenSSL::SSL::VERIFY_NONE
  self.verify_hostname = false
end

Создаёт новый контекст SSL.

Если передан аргумент, вызывается ssl_version= с этим значением. Обратите внимание, что эта форма устарела. В новых приложениях при необходимости следует использовать min_version= и max_version=.

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

add_certificate(certificate, pkey [, extra_certs]) → self Показать исходный код
static VALUE
ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
{
    VALUE cert, key, extra_chain_ary;
    SSL_CTX *ctx;
    X509 *x509;
    STACK_OF(X509) *extra_chain = NULL;
    EVP_PKEY *pkey, *pub_pkey;

    GetSSLCTX(self, ctx);
    rb_scan_args(argc, argv, "21", &cert, &key, &extra_chain_ary);
    rb_check_frozen(self);
    x509 = GetX509CertPtr(cert);
    pkey = GetPrivPKeyPtr(key);

    /*
     * The reference counter is bumped, and decremented immediately.
     * X509_get0_pubkey() is only available in OpenSSL >= 1.1.0.
     */
    pub_pkey = X509_get_pubkey(x509);
    EVP_PKEY_free(pub_pkey);
    if (!pub_pkey)
        rb_raise(rb_eArgError, "certificate does not contain public key");
    if (EVP_PKEY_eq(pub_pkey, pkey) != 1)
        rb_raise(rb_eArgError, "public key mismatch");

    if (argc >= 3)
        extra_chain = ossl_x509_ary2sk(extra_chain_ary);

    if (!SSL_CTX_use_certificate(ctx, x509)) {
        sk_X509_pop_free(extra_chain, X509_free);
        ossl_raise(eSSLError, "SSL_CTX_use_certificate");
    }
    if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
        sk_X509_pop_free(extra_chain, X509_free);
        ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
    }
    if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) {
        sk_X509_pop_free(extra_chain, X509_free);
        ossl_raise(eSSLError, "SSL_CTX_set0_chain");
    }
    return self;
}

Добавляет сертификат в контекст. pkey должен быть соответствующим закрытым ключом для certificate.

Повторными вызовами этого метода можно добавить несколько сертификатов с разными типами открытых ключей, а OpenSSL выберет наиболее подходящий сертификат во время рукопожатия.

cert=, key= и extra_chain_cert= — устаревшие методы доступа для установки сертификата, которые внутри вызывают этот метод.

Параметры

certificate

Сертификат. Экземпляр OpenSSL::X509::Certificate.

pkey

Закрытый ключ для certificate. Экземпляр OpenSSL::PKey::PKey.

extra_certs

Необязательный параметр. Массив OpenSSL::X509::Certificate. При отправке цепочки сертификатов указанные здесь сертификаты отправляются после certificate в порядке, заданном в массиве.

Пример

rsa_cert = OpenSSL::X509::Certificate.new(...)
rsa_pkey = OpenSSL::PKey.read(...)
ca_intermediate_cert = OpenSSL::X509::Certificate.new(...)
ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert])

ecdsa_cert = ...
ecdsa_pkey = ...
another_ca_cert = ...
ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert])
ciphers → [[name, version, bits, alg_bits], ...] Показать исходный код
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciphers;
    const SSL_CIPHER *cipher;
    VALUE ary;
    int i, num;

    GetSSLCTX(self, ctx);
    ciphers = SSL_CTX_get_ciphers(ctx);
    if (!ciphers)
        return rb_ary_new();

    num = sk_SSL_CIPHER_num(ciphers);
    ary = rb_ary_new2(num);
    for(i = 0; i < num; i++){
        cipher = sk_SSL_CIPHER_value(ciphers, i);
        rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
    }
    return ary;
}

Список наборов шифров, настроенных для этого контекста.

ciphers = "cipher1:cipher2:..." Показать исходный код
ciphers = [name, ...]
ciphers = [[name, version, bits, alg_bits], ...]
static VALUE
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    VALUE str;

    rb_check_frozen(self);
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

    GetSSLCTX(self, ctx);
    if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str)))
        ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");

    return v;
}

Задает список доступных наборов шифров для этого контекста. Обратите внимание, что в контексте сервера для некоторых шифров требуются соответствующие сертификаты. Например, набор шифров RSA можно выбрать только при наличии сертификата RSA.

ciphersuites = "cipher1:cipher2:..." Показать исходный код
ciphersuites = [name, ...]
ciphersuites = [[name, version, bits, alg_bits], ...]
static VALUE
ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    VALUE str;

    rb_check_frozen(self);
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

    GetSSLCTX(self, ctx);
    if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str)))
        ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites");

    return v;
}

Задает список доступных наборов шифров TLSv1.3 для этого контекста.

ecdh_curves = curve_list → curve_list Показать исходный код
static VALUE
ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);
    StringValueCStr(arg);

    if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
        ossl_raise(eSSLError, NULL);
    return arg;
}

Задает список «поддерживаемых эллиптических кривых» для этого контекста.

Для клиента TLS этот список напрямую используется в расширении Supported Elliptic Curves. Для сервера OpenSSL использует список, чтобы определить набор общих кривых. OpenSSL выберет из него наиболее подходящую кривую.

Пример

ctx1 = OpenSSL::SSL::SSLContext.new
ctx1.ecdh_curves = "X25519:P-256:P-224"
svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
Thread.new { svr.accept }

ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.ecdh_curves = "P-256"
cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
cli.connect

p cli.tmp_key.group.curve_name
# => "prime256v1" (is an alias for NIST P-256)
enable_fallback_scsv() → nil Показать исходный код
static VALUE
ossl_sslctx_enable_fallback_scsv(VALUE self)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);
    SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV);

    return Qnil;
}

Включает TLS_FALLBACK_SCSV для этого контекста. См. RFC 7507.

flush_sessions(time) → self Показать исходный код
static VALUE
ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
{
    VALUE arg1;
    SSL_CTX *ctx;
    time_t tm = 0;

    rb_scan_args(argc, argv, "01", &arg1);

    GetSSLCTX(self, ctx);

    if (NIL_P(arg1)) {
        tm = time(0);
    } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
        tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
    } else {
        ossl_raise(rb_eArgError, "arg must be Time or nil");
    }

    SSL_CTX_flush_sessions(ctx, (long)tm);

    return self;
}

Удаляет из внутреннего кэша сеансы, срок действия которых истек к моменту time.

freeze
Псевдоним для: setup
max_version = OpenSSL::SSL::TLS1_2_VERSION Показать исходный код
max_version = :TLS1_2
max_version = nil
# File ext/openssl/lib/openssl/ssl.rb, line 189
def max_version=(version)
  set_minmax_proto_version(@min_proto_version ||= nil, version)
  @max_proto_version = version
end

Задает верхнюю границу поддерживаемой версии протокола SSL/TLS. Возможные значения см. в разделе min_version=.

min_version = OpenSSL::SSL::TLS1_2_VERSION Показать исходный код
min_version = :TLS1_2
min_version = nil
# File ext/openssl/lib/openssl/ssl.rb, line 177
def min_version=(version)
  set_minmax_proto_version(version, @max_proto_version ||= nil)
  @min_proto_version = version
end

Задает нижнюю границу поддерживаемой версии протокола SSL/TLS. Версию можно указать целочисленной константой с именем OpenSSL::SSL::*_VERSION, объектом Symbol или nil, что означает «любая версия».

Будьте осторожны: после вызова min_version= или max_version= не перезаписывайте параметры OpenSSL::SSL::OP_NO_{SSL,TLS}v* с помощью options=.

Пример

ctx = OpenSSL::SSL::SSLContext.new
ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION

sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2
options → integer Показать исходный код
static VALUE
ossl_sslctx_get_options(VALUE self)
{
    SSL_CTX *ctx;
    GetSSLCTX(self, ctx);
    /*
     * Do explicit cast because SSL_CTX_get_options() returned (signed) long in
     * OpenSSL before 1.1.0.
     */
    return ULONG2NUM((unsigned long)SSL_CTX_get_options(ctx));
}

Возвращает различные параметры OpenSSL.

options = integer Показать исходный код
static VALUE
ossl_sslctx_set_options(VALUE self, VALUE options)
{
    SSL_CTX *ctx;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);

    SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));

    if (NIL_P(options)) {
        SSL_CTX_set_options(ctx, SSL_OP_ALL);
    } else {
        SSL_CTX_set_options(ctx, NUM2ULONG(options));
    }

    return self;
}

Задает различные параметры OpenSSL. Параметры представляют собой битовое поле, значения которого можно объединять побитовым оператором ИЛИ (|). Доступные параметры определены как константы в OpenSSL::SSL и начинаются с OP_.

Для обратной совместимости передача nil имеет тот же эффект, что и передача OpenSSL::SSL::OP_ALL.

См. также страницу руководства SSL_CTX_set_options(3).

security_level → Integer Показать исходный код
static VALUE
ossl_sslctx_get_security_level(VALUE self)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
    return INT2NUM(SSL_CTX_get_security_level(ctx));
#else
    (void)ctx;
    return INT2FIX(0);
#endif
}

Возвращает уровень безопасности контекста.

См. также OpenSSL::SSL::SSLContext#security_level=.

security_level = integer Показать исходный код
static VALUE
ossl_sslctx_set_security_level(VALUE self, VALUE value)
{
    SSL_CTX *ctx;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);

#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
    SSL_CTX_set_security_level(ctx, NUM2INT(value));
#else
    (void)ctx;
    if (NUM2INT(value) != 0)
        ossl_raise(rb_eNotImpError, "setting security level to other than 0 is "
                   "not supported in this version of OpenSSL");
#endif

    return value;
}

Задает уровень безопасности контекста. OpenSSL ограничивает параметры в соответствии с этим уровнем. К «параметрам» относятся наборы шифров, кривые, размеры ключей, алгоритмы подписи сертификатов, версия протокола и т. д. Например, уровень 1 запрещает параметры с уровнем безопасности ниже 80 бит, такие как наборы шифров с MD5 для MAC или ключи RSA короче 1024 бит.

Обратите внимание, что попытки установить параметры с недостаточным уровнем безопасности также блокируются. Сначала необходимо понизить уровень.

Эта функция не поддерживается в OpenSSL < 1.1.0, и установка уровня, отличного от 0, вызовет исключение NotImplementedError. Уровень 0 означает, что разрешено всё; поведение такое же, как в предыдущих версиях OpenSSL.

Подробности см. на странице руководства SSL_CTX_set_security_level(3).

session_add(session) → true | false Показать исходный код
static VALUE
ossl_sslctx_session_add(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    SSL_SESSION *sess;

    GetSSLCTX(self, ctx);
    GetSSLSession(arg, sess);

    return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}

Добавляет session в кэш сеансов.

session_cache_mode → Integer Показать исходный код
static VALUE
ossl_sslctx_get_session_cache_mode(VALUE self)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

    return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
}

Текущий режим кэширования сеансов.

session_cache_mode=(integer) → Integer Показать исходный код
static VALUE
ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

    SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));

    return arg;
}

Задает режим кэширования сеансов SSL. Чтобы задать режим, объедините побитовым ИЛИ нужные константы SESSION_CACHE_*. Подробности см. в SSL_CTX_set_session_cache_mode(3).

session_cache_size → Integer Показать исходный код
static VALUE
ossl_sslctx_get_session_cache_size(VALUE self)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

    return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
}

Возвращает текущий размер кэша сеансов. Нулевое значение означает неограниченный размер кэша.

session_cache_size=(integer) → Integer Показать исходный код
static VALUE
ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

    SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));

    return arg;
}

Задает размер кэша сеансов. Возвращает предыдущее допустимое значение размера кэша сеансов. Нулевое значение означает неограниченный размер кэша сеансов.

session_cache_stats → Hash Показать исходный код
static VALUE
ossl_sslctx_get_session_cache_stats(VALUE self)
{
    SSL_CTX *ctx;
    VALUE hash;

    GetSSLCTX(self, ctx);

    hash = rb_hash_new();
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));

    return hash;
}

Возвращает Hash со следующими ключами:

:accept

Количество начатых рукопожатий SSL/TLS в режиме сервера

:accept_good

Количество установленных сеансов SSL/TLS в режиме сервера

:accept_renegotiate

Количество начатых повторных согласований в режиме сервера

:cache_full

Количество сеансов, удаленных из-за переполнения кэша

:cache_hits

Количество успешно повторно использованных соединений

:cache_misses

Количество сеансов, предложенных клиентами, но не найденных в кэше

:cache_num

Количество сеансов во внутреннем кэше сеансов

:cb_hits

Количество сеансов, извлеченных из внешнего кэша в режиме сервера

:connect

Количество начатых рукопожатий SSL/TLS в режиме клиента

:connect_good

Количество установленных сеансов SSL/TLS в режиме клиента

:connect_renegotiate

Количество начатых повторных согласований в режиме клиента

:timeouts

Количество сеансов, предложенных клиентами и найденных в кэше, но срок действия которых истек по тайм-ауту

session_remove(session) → true | false Показать исходный код
static VALUE
ossl_sslctx_session_remove(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    SSL_SESSION *sess;

    GetSSLCTX(self, ctx);
    GetSSLSession(arg, sess);

    return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}

Удаляет session из кэша сеансов.

set_params(params = {}) → params Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 145
def set_params(params={})
  params = DEFAULT_PARAMS.merge(params)
  self.options |= params.delete(:options) # set before min_version/max_version
  params.each{|name, value| self.__send__("#{name}=", value) }
  if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
    unless self.ca_file or self.ca_path or self.cert_store
      self.cert_store = DEFAULT_CERT_STORE
    end
  end
  return params
end

Задает более разумные значения по умолчанию, оптимизированные для использования с протоколами, подобными HTTP.

Если указан Hash params, параметры переопределяются его значениями. Ключи в params должны соответствовать методам присваивания в SSLContext.

Если verify_mode имеет значение, отличное от VERIFY_NONE, а ca_file, ca_path и cert_store не заданы, используется системное хранилище сертификатов по умолчанию.

setup → Qtrue # first time Показать исходный код
setup → nil # thereafter
static VALUE
ossl_sslctx_setup(VALUE self)
{
    SSL_CTX *ctx;
    X509 *cert = NULL, *client_ca = NULL;
    EVP_PKEY *key = NULL;
    char *ca_path = NULL, *ca_file = NULL;
    int verify_mode;
    long i;
    VALUE val;

    if(OBJ_FROZEN(self)) return Qnil;
    GetSSLCTX(self, ctx);

#if !defined(OPENSSL_NO_DH)
    SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
#endif

#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
    SSL_CTX_set_post_handshake_auth(ctx, 1);
#endif

    val = rb_attr_get(self, id_i_cert_store);
    if (!NIL_P(val)) {
        X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
        SSL_CTX_set_cert_store(ctx, store);
        X509_STORE_up_ref(store);
    }

    val = rb_attr_get(self, id_i_extra_chain_cert);
    if(!NIL_P(val)){
        rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
    }

    /* private key may be bundled in certificate file. */
    val = rb_attr_get(self, id_i_cert);
    cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
    val = rb_attr_get(self, id_i_key);
    key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
    if (cert && key) {
        if (!SSL_CTX_use_certificate(ctx, cert)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_certificate");
        }
        if (!SSL_CTX_use_PrivateKey(ctx, key)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
        }
        if (!SSL_CTX_check_private_key(ctx)) {
            ossl_raise(eSSLError, "SSL_CTX_check_private_key");
        }
    }

    val = rb_attr_get(self, id_i_client_ca);
    if(!NIL_P(val)){
        if (RB_TYPE_P(val, T_ARRAY)) {
            for(i = 0; i < RARRAY_LEN(val); i++){
                client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
                if (!SSL_CTX_add_client_CA(ctx, client_ca)){
                    /* Copies X509_NAME => FREE it. */
                    ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
                }
            }
        }
        else{
            client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
            if (!SSL_CTX_add_client_CA(ctx, client_ca)){
                /* Copies X509_NAME => FREE it. */
                ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
            }
        }
    }

    val = rb_attr_get(self, id_i_ca_file);
    ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
    val = rb_attr_get(self, id_i_ca_path);
    ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE
    if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file))
        ossl_raise(eSSLError, "SSL_CTX_load_verify_file");
    if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path))
        ossl_raise(eSSLError, "SSL_CTX_load_verify_dir");
#else
    if (ca_file || ca_path) {
        if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
            ossl_raise(eSSLError, "SSL_CTX_load_verify_locations");
    }
#endif

    val = rb_attr_get(self, id_i_verify_mode);
    verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
    SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
    if (RTEST(rb_attr_get(self, id_i_client_cert_cb)))
        SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);

    val = rb_attr_get(self, id_i_timeout);
    if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));

    val = rb_attr_get(self, id_i_verify_depth);
    if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));

#ifdef OSSL_USE_NEXTPROTONEG
    val = rb_attr_get(self, id_i_npn_protocols);
    if (!NIL_P(val)) {
        VALUE encoded = ssl_encode_npn_protocols(val);
        rb_ivar_set(self, id_npn_protocols_encoded, encoded);
        SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
        OSSL_Debug("SSL NPN advertise callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
        SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
        OSSL_Debug("SSL NPN select callback added");
    }
#endif

    val = rb_attr_get(self, id_i_alpn_protocols);
    if (!NIL_P(val)) {
        VALUE rprotos = ssl_encode_npn_protocols(val);

        /* returns 0 on success */
        if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
                                    RSTRING_LENINT(rprotos)))
            ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
        OSSL_Debug("SSL ALPN values added");
    }
    if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
        SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
        OSSL_Debug("SSL ALPN select callback added");
    }

    rb_obj_freeze(self);

    val = rb_attr_get(self, id_i_session_id_context);
    if (!NIL_P(val)){
        StringValue(val);
        if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
                                            RSTRING_LENINT(val))){
            ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
        }
    }

    if (RTEST(rb_attr_get(self, id_i_session_get_cb))) {
        SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
        OSSL_Debug("SSL SESSION get callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_session_new_cb))) {
        SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
        OSSL_Debug("SSL SESSION new callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) {
        SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
        OSSL_Debug("SSL SESSION remove callback added");
    }

    val = rb_attr_get(self, id_i_servername_cb);
    if (!NIL_P(val)) {
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
        OSSL_Debug("SSL TLSEXT servername callback added");
    }

#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
    /*
     * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
     * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
     * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
     */
    if (RTEST(rb_attr_get(self, id_i_keylog_cb))) {
        SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb);
        OSSL_Debug("SSL keylog callback added");
    }
#endif

    return Qtrue;
}

Этот метод вызывается автоматически при создании нового SSLSocket. Однако он не является потокобезопасным, поэтому в многопоточной программе его необходимо вызвать до создания объектов SSLSocket.

Также имеет псевдоним: freeze
ssl_version = :TLSv1 Показать исходный код
ssl_version = "SSLv23"
# File ext/openssl/lib/openssl/ssl.rb, line 208
def ssl_version=(meth)
  meth = meth.to_s if meth.is_a?(Symbol)
  if /(?<type>_client|_server)\z/ =~ meth
    meth = $`
    if $VERBOSE
      warn "#{caller(1, 1)[0]}: method type #{type.inspect} is ignored"
    end
  end
  version = METHODS_MAP[meth.intern] or
    raise ArgumentError, "unknown SSL method `%s'" % meth
  set_minmax_proto_version(version, version)
  @min_proto_version = @max_proto_version = version
end

Задает версию протокола SSL/TLS для контекста. Это заставляет соединения использовать только указанную версию протокола. Метод устарел и сохранен только для обратной совместимости. Вместо него используйте min_version= и max_version=.

История

Как следует из названия, раньше этот метод вызывал функцию SSL_CTX_set_ssl_version(), которая задает метод SSL, используемый соединениями, созданными на основе контекста. Начиная с Ruby/OpenSSL 2.1 этот метод доступа реализован так, чтобы вместо этого вызывать min_version= и max_version=.

tmp_dh = pkey Показать исходный код
static VALUE
ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    EVP_PKEY *pkey;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);
    pkey = GetPKeyPtr(arg);

    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
        rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
                 OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
#ifdef HAVE_SSL_SET0_TMP_DH_PKEY
    if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
        ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
    EVP_PKEY_up_ref(pkey);
#else
    if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
        ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
#endif

    return arg;
}

Задает параметры DH, используемые для эфемерного обмена ключами DH. Это имеет значение только для серверов.

pkey — экземпляр OpenSSL::PKey::DH. Обратите внимание, что компоненты ключа, содержащиеся в объекте ключа (если они есть), игнорируются. Сервер всегда генерирует новую пару ключей для каждого рукопожатия.

Добавлено в версии 3.0. См. также страницу руководства SSL_set0_tmp_dh_pkey(3).

Пример:

ctx = OpenSSL::SSL::SSLContext.new
ctx.tmp_dh = OpenSSL::DH.generate(2048)
svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
Thread.new { svr.accept }

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

set_minmax_proto_version(min, max) → nil Показать исходный код
static VALUE
ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v)
{
    SSL_CTX *ctx;
    int min, max;

    GetSSLCTX(self, ctx);
    min = parse_proto_version(min_v);
    max = parse_proto_version(max_v);

#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
    if (!SSL_CTX_set_min_proto_version(ctx, min))
        ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
    if (!SSL_CTX_set_max_proto_version(ctx, max))
        ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
#else
    {
        unsigned long sum = 0, opts = 0;
        int i;
        static const struct {
            int ver;
            unsigned long opts;
        } options_map[] = {
            { SSL2_VERSION, SSL_OP_NO_SSLv2 },
            { SSL3_VERSION, SSL_OP_NO_SSLv3 },
            { TLS1_VERSION, SSL_OP_NO_TLSv1 },
            { TLS1_1_VERSION, SSL_OP_NO_TLSv1_1 },
            { TLS1_2_VERSION, SSL_OP_NO_TLSv1_2 },
# if defined(TLS1_3_VERSION)
            { TLS1_3_VERSION, SSL_OP_NO_TLSv1_3 },
# endif
        };

        for (i = 0; i < numberof(options_map); i++) {
            sum |= options_map[i].opts;
            if ((min && min > options_map[i].ver) ||
                (max && max < options_map[i].ver)) {
                opts |= options_map[i].opts;
            }
        }
        SSL_CTX_clear_options(ctx, sum);
        SSL_CTX_set_options(ctx, opts);
    }
#endif

    return Qnil;
}

Задает минимальную и максимальную поддерживаемые версии протокола. См. min_version= и max_version=.

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