Spec-Zone.ru › Ruby 3.4

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

Родитель:
Объект

Объект 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 представляет протокол, который будет объявлен в качестве списка поддерживаемых протоколов для Application-Layer Protocol Negotiation. Поддерживается в 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() начиная с v3.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 представляет протокол, который будет объявлен в качестве списка поддерживаемых протоколов для Next Protocol Negotiation. Поддерживается в 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 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, что означает «любая версия».

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

Пример

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 # первый раз
setup → nil # впоследствии
Исходный код
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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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