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

класс OpenSSL::SSL::SSLContext

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

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

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

Константы

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]

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

ca_path [RW]

Путь к каталогу, содержащему сертификаты CA в формате 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]

Количество сертификатов CA, проверяемых при проверке цепочки сертификатов.

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 94
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);
    // Assigning nil is a no-op for compatibility
    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;
}

Задаёт список доступных наборов шифров для TLS 1.2 и более ранних версий в этом контексте.

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

Этот метод не влияет на соединения TLS 1.3. См. также ciphersuites=.

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

    rb_check_frozen(self);
    // Assigning nil is a no-op for compatibility
    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;
}

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

client_sigalgs = "sigalg1:sigalg2:..." Показать исходный код
static VALUE
ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
{
    SSL_CTX *ctx;

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

    if (!SSL_CTX_set1_client_sigalgs_list(ctx, StringValueCStr(v)))
        ossl_raise(eSSLError, "SSL_CTX_set1_client_sigalgs_list");

    return v;
}

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

Для TLS-сервера этот список отправляется клиенту в составе сообщения CertificateRequest.

Эквивалентный метод для аутентификации сервера см. в sigalgs=.

groups = groups_list
ecdh_curves = groups_list

Задаёт список поддерживаемых групп для согласования ключей в этом контексте.

Для TLS-клиента этот список непосредственно используется в расширении “supported_groups”. Для сервера список используется OpenSSL для определения набора общих поддерживаемых групп. OpenSSL выберет из него наиболее подходящую группу.

ecdh_curves= — устаревший псевдоним для groups=.

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

Пример

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

ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.groups = "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)
Псевдоним для: groups=
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
groups = groups_list Показать исходный код
ecdh_curves = groups_list
static VALUE
ossl_sslctx_set_groups(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;

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

    if (!SSL_CTX_set1_groups_list(ctx, RSTRING_PTR(arg)))
        ossl_raise(eSSLError, "SSL_CTX_set1_groups_list");
    return arg;
}

Задаёт список поддерживаемых групп для согласования ключей в этом контексте.

Для TLS-клиента этот список непосредственно используется в расширении “supported_groups”. Для сервера список используется OpenSSL для определения набора общих поддерживаемых групп. OpenSSL выберет из него наиболее подходящую группу.

ecdh_curves= — устаревший псевдоним для groups=.

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

Пример

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

ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.groups = "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)
Также имеет псевдоним: ecdh_curves=
max_version = OpenSSL::SSL::TLS1_2_VERSION Показать исходный код
max_version = :TLS1_2
max_version = nil
static VALUE
ossl_sslctx_set_max_version(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    int version;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);
    version = parse_proto_version(v);

    if (!SSL_CTX_set_max_proto_version(ctx, version))
        ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
    return v;
}

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

min_version = OpenSSL::SSL::TLS1_2_VERSION Показать исходный код
min_version = :TLS1_2
min_version = nil
static VALUE
ossl_sslctx_set_min_version(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    int version;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);
    version = parse_proto_version(v);

    if (!SSL_CTX_set_min_proto_version(ctx, version))
        ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
    return v;
}

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

Пример

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

    return INT2NUM(SSL_CTX_get_security_level(ctx));
}

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

См. также 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);

    SSL_CTX_set_security_level(ctx, NUM2INT(value));

    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 112
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
      if not defined?(Ractor) or Ractor.current == Ractor.main
        self.cert_store = DEFAULT_CERT_STORE
      else
        self.cert_store = Ractor.current[:__openssl_default_store__] ||=
          OpenSSL::X509::Store.new.tap { |store|
            store.set_default_paths
          }
      end
    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)
    if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) {
        SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
        SSL_CTX_set_dh_auto(ctx, 0);
    }
#endif

#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */
    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 !OSSL_IS_LIBRESSL
    /*
     * 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
sigalgs = "sigalg1:sigalg2:..." Показать исходный код
static VALUE
ossl_sslctx_set_sigalgs(VALUE self, VALUE v)
{
    SSL_CTX *ctx;

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

    if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v)))
        ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list");

    return v;
}

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

Для TLS-клиента этот список используется в расширении “signature_algorithms” сообщения ClientHello. Для сервера список используется OpenSSL для определения набора общих алгоритмов подписи. OpenSSL выберет из него наиболее подходящий алгоритм.

Эквивалентный метод для аутентификации клиента см. в client_sigalgs=.

ssl_version = :TLSv1 Показать исходный код
ssl_version = "SSLv23"
# File ext/openssl/lib/openssl/ssl.rb, line 145
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
  self.min_version = self.max_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_CTX_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

    // Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc()
    SSL_CTX_set_dh_auto(ctx, 0);

    return arg;
}

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

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

Добавлено в версии 3.0. См. также страницу руководства SSL_CTX_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 }

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