Spec-Zone.ru › Ruby 2.5

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 строк. Каждая строка представляет протокол, который будет объявлен как список поддерживаемых протоколов для согласования протоколов прикладного уровня (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]

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

client_cert_cb[RW]

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

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

extra_chain_cert[RW]

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

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

key[RW]

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

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

npn_protocols[RW]

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

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

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

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.

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

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

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]

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

Допустимые режимы — 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 119
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 список используется непосредственно в расширении Supported Elliptic Curves. Для сервера список используется 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.

заморозить()
Псевдоним для: setup
max_version = OpenSSL::SSL::TLS1_2_VERSION Показать исходный код
max_version = :TLS1_2
max_version = nil
# File ext/openssl/lib/openssl/ssl.rb, line 180
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 168
def min_version=(version)
  set_minmax_proto_version(version, @max_proto_version ||= nil)
  @min_proto_version = version
end

Устанавливает нижнюю границу поддерживаемой версии протокола SSL/TLS. Версия может быть указана целочисленной константой с именем OpenSSL::SSL::*_VERSION, символом или 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 → Целое Показать исходный код
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
}

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

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

См. руководство manpage для 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 → Целое Показать исходный код
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) → Целое Показать исходный код
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 → Целое Показать исходный код
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));
}

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

END_OF_DOCUMENT_MARKER
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 136
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 в многопоточной программе.

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