Spec-Zone.ru › Ruby 2.7

class OpenSSL::SSL::SSLContext

Parent:
Object

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

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

Постоянные

DEFAULT_2048
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]

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

ca_path[RW]

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

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

cert[RW]

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

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

cert_store[RW]

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

client_ca[RW]

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

client_cert_cb[RW]

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

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

extra_chain_cert[RW]

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

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

key[RW]

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

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

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. Возвращаемое значение обратного вызова не имеет значения, обычный возврат указывает на «утверждение» повторного согласования и продолжит процесс. Чтобы запретить повторное согласование и отменить процесс, внутри обратного вызова может быть вызвана ошибка Error.

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

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

num_handshakes = 0
ctx.renegotiation_cb = lambda do |ssl|
  num_handshakes += 1
  raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1
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.

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

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

tmp_ecdh_callback[RW]

Обратный вызов, вызываемый при необходимости параметров ECDH.

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

Обратный вызов устарел. Он не работает с последними версиями OpenSSL. Используйте OpenSSL::SSL::SSLContext#ecdh_curves= вместо этого.

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 121
def initialize(version = nil)
  self.options |= OpenSSL::SSL::OP_ALL
  self.ssl_version = version if version
end

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

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

Общедоступные методы экземпляра

add_certificate(certiticate, 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_cmp(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) {
#if OPENSSL_VERSION_NUMBER >= 0x10002000 && !defined(LIBRESSL_VERSION_NUMBER)
        if (!SSL_CTX_set0_chain(ctx, extra_chain)) {
            sk_X509_pop_free(extra_chain, X509_free);
            ossl_raise(eSSLError, "SSL_CTX_set0_chain");
        }
#else
        STACK_OF(X509) *orig_extra_chain;
        X509 *x509_tmp;

        /* First, clear the existing chain */
        SSL_CTX_get_extra_chain_certs(ctx, &orig_extra_chain);
        if (orig_extra_chain && sk_X509_num(orig_extra_chain)) {
            rb_warning("SSL_CTX_set0_chain() is not available; " \
                       "clearing previously set certificate chain");
            SSL_CTX_clear_extra_chain_certs(ctx);
        }
        while ((x509_tmp = sk_X509_shift(extra_chain))) {
            /* Transfers ownership */
            if (!SSL_CTX_add_extra_chain_cert(ctx, x509_tmp)) {
                X509_free(x509_tmp);
                sk_X509_pop_free(extra_chain, X509_free);
                ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
            }
        }
        sk_X509_free(extra_chain);
#endif
    }
    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])

Примечание

OpenSSL до версии 1.0.2 мог обрабатывать только одну дополнительную цепочку для всех типов ключей. Вызов этого метода отбрасывает ранее установленную цепочку.

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, elem;
    int i;

    rb_check_frozen(self);
    if (NIL_P(v))
        return v;
    else if (RB_TYPE_P(v, T_ARRAY)) {
        str = rb_str_new(0, 0);
        for (i = 0; i < RARRAY_LEN(v); i++) {
            elem = rb_ary_entry(v, i);
            if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0);
            elem = rb_String(elem);
            rb_str_append(str, elem);
            if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
        }
    } else {
        str = v;
        StringValue(str);
    }

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

    return v;
}

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

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 defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
    if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
        ossl_raise(eSSLError, NULL);
#else
    /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
     * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
    {
        VALUE curve, splitted;
        EC_KEY *ec;
        int nid;

        splitted = rb_str_split(arg, ":");
        if (!RARRAY_LEN(splitted))
            ossl_raise(eSSLError, "invalid input format");
        curve = RARRAY_AREF(splitted, 0);
        StringValueCStr(curve);

        /* SSL_CTX_set1_curves_list() accepts NIST names */
        nid = EC_curve_nist2nid(RSTRING_PTR(curve));
        if (nid == NID_undef)
            nid = OBJ_txt2nid(RSTRING_PTR(curve));
        if (nid == NID_undef)
            ossl_raise(eSSLError, "unknown curve name");

        ec = EC_KEY_new_by_curve_name(nid);
        if (!ec)
            ossl_raise(eSSLError, NULL);
        EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
        if (!SSL_CTX_set_tmp_ecdh(ctx, ec)) {
            EC_KEY_free(ec);
            ossl_raise(eSSLError, "SSL_CTX_set_tmp_ecdh");
        }
        EC_KEY_free(ec);
# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
        /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
         * is enabled. So disable ecdh_auto. */
        if (!SSL_CTX_set_ecdh_auto(ctx, 0))
            ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
# endif
    }
#endif

    return arg;
}

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

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

Обратите внимание, что это работает по-другому со старыми версиями OpenSSL (≤ 1.0.1). Можно установить только одну кривую, и это не оказывает никакого влияния на клиентов TLS.

Пример

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

END_OF_DOCUMENT_MARKER
session_cache_size → Целое число Показать исходный код
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=(целое число) → Целое число Показать исходный код
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 → Хэш Показать исходный код
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(сессия) → 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;
}

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

set_params(params = {}) → params Показать исходный код
# File ext/openssl/lib/openssl/ssl.rb, line 138
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

#if !defined(OPENSSL_NO_EC)
    /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
     * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
    if (RTEST(rb_attr_get(self, id_i_tmp_ecdh_callback))) {
# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
        rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
        SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
#  if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
        /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
         * tmp_ecdh_callback. So disable ecdh_auto. */
        if (!SSL_CTX_set_ecdh_auto(ctx, 0))
            ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
#  endif
# else
        ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
                   "use #ecdh_curves= instead");
# endif
    }
#endif /* OPENSSL_NO_EC */

    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);
#if !defined(HAVE_X509_STORE_UP_REF)
        /*
         * WORKAROUND:
         *   X509_STORE can count references, but
         *   X509_STORE_free() doesn't care it.
         *   So we won't increment it but mark it by ex_data.
         */
        SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_store_p, ctx);
#else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */
        X509_STORE_up_ref(store);
#endif
    }

    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);
    if(ca_file || ca_path){
        if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
            rb_warning("can't set verify locations");
    }

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

#ifndef OPENSSL_NO_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 *)encoded);
        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

#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
    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");
    }
#endif

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

    return Qtrue;
}

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

Также алиас: заморозить
ssl_version = :TLSv1 Показать исходный код
ssl_version = "SSLv23"
# File ext/openssl/lib/openssl/ssl.rb, line 201
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= вместо этого.

Приватные методы экземпляра

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–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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