Spec-Zone.ru › Ruby 3.3

класс 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]

An Enumerable of Strings. Each String represents a protocol to be advertised as the list of supported protocols for Application-Layer Protocol Negotiation. Supported in OpenSSL 1.0.2 and higher. Has no effect on the server side. If not set explicitly, the ALPN extension will not be included in the handshake.

Пример

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

A callback invoked on the server side when the server needs to select a protocol from the list sent by the client. Supported in OpenSSL 1.0.2 and higher. The callback must return a protocol of those advertised by the client. If none is acceptable, raising an error in the callback will cause the handshake to fail. Not setting this callback explicitly means not supporting the ALPN extension on the server - any protocols advertised by the client will be ignored.

Пример

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]

An OpenSSL::X509::Store used for certificate verification.

client_ca[RW]

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

client_cert_cb[RW]

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

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

extra_chain_cert[RW]

An Array of extra X509 certificates to be added to the certificate chain.

Атрибуты 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]

An Enumerable of Strings. Each String represents a protocol to be advertised as the list of supported protocols for Next Protocol Negotiation. Supported in OpenSSL 1.0.1 and higher. Has no effect on the client side. If not set explicitly, the NPN extension will not be sent by the server in the handshake.

Пример

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

A callback invoked on the client side when the client needs to select a protocol from the list sent by the server. Supported in OpenSSL 1.0.1 and higher. The client MUST select a protocol of those advertised by the server. If none is acceptable, raising an error in the callback will cause the handshake to fail. Not setting this callback explicitly means not supporting the NPN extension on the client - any protocols advertised by the server will be ignored.

Пример

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.options |= OpenSSL::SSL::OP_ALL
  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 Show source
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], ...] Show source
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:..." Show source
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:..." Show source
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 Show source
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 Show source
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 Show source
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
Alias for: setup
max_version = OpenSSL::SSL::TLS1_2_VERSION Show source
max_version = :TLS1_2
max_version = nil
# File ext/openssl/lib/openssl/ssl.rb, line 190
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 Show source
min_version = :TLS1_2
min_version = nil
# File ext/openssl/lib/openssl/ssl.rb, line 178
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() Show source
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=(p1) Show source
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.

security_level → Integer Show source
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 Show source
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 Show source
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 Show source
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 146
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 в многопоточной программе.

Также алиасируется как: замораживать
ssl_version = :TLSv1 Показать исходный код
ssl_version = "SSLv23"
# File ext/openssl/lib/openssl/ssl.rb, line 209
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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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