Class: OpenSSL::SSL::SSLContext

Inherits:
Object
  • Object
show all
Defined in:
ext/openssl/ossl_ssl.c,
lib/openssl/ssl.rb,
ext/openssl/ossl_ssl.c

Overview

An SSLContext is used to set various options regarding certificates, algorithms, verification, session caching, etc. The SSLContext is used to create an SSLSocket.

All attributes must be set before creating an SSLSocket as the SSLContext will be frozen afterward.

Constant Summary collapse

DEFAULT_PARAMS =

:nodoc:

{ # :nodoc:
  :verify_mode => OpenSSL::SSL::VERIFY_PEER,
  :verify_hostname => true,
  :options => -> {
    opts = OpenSSL::SSL::OP_ALL
    opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
    opts |= OpenSSL::SSL::OP_NO_COMPRESSION
    opts
  }.call
}
DEFAULT_CERT_STORE =

:nodoc:

OpenSSL::X509::Store.new
METHODS =

The list of available SSL/TLS methods. This constant is only provided for backwards compatibility.

METHODS_MAP.flat_map { |name,|
  [name, :"#{name}_client", :"#{name}_server"]
}.freeze
SESSION_CACHE_OFF =

No session caching for client or server

LONG2NUM(SSL_SESS_CACHE_OFF)
SESSION_CACHE_CLIENT =

doesn’t actually do anything in 0.9.8e

LONG2NUM(SSL_SESS_CACHE_CLIENT)
SESSION_CACHE_SERVER =

Server sessions are added to the session cache

LONG2NUM(SSL_SESS_CACHE_SERVER)
SESSION_CACHE_BOTH =

no different than CACHE_SERVER in 0.9.8e

LONG2NUM(SSL_SESS_CACHE_BOTH)
SESSION_CACHE_NO_AUTO_CLEAR =

Normally the session cache is checked for expired sessions every 255 connections. Since this may lead to a delay that cannot be controlled, the automatic flushing may be disabled and #flush_sessions can be called explicitly.

LONG2NUM(SSL_SESS_CACHE_NO_AUTO_CLEAR)
SESSION_CACHE_NO_INTERNAL_LOOKUP =

Always perform external lookups of sessions even if they are in the internal cache.

This flag has no effect on clients

LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)
SESSION_CACHE_NO_INTERNAL_STORE =

Never automatically store sessions in the internal store.

LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_STORE)
SESSION_CACHE_NO_INTERNAL =

Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and SESSION_CACHE_NO_INTERNAL_STORE.

LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version = nil) ⇒ SSLContext

call-seq:

SSLContext.new           -> ctx
SSLContext.new(:TLSv1)   -> ctx
SSLContext.new("SSLv23") -> ctx

Creates a new SSL context.

If an argument is given, #ssl_version= is called with the value. Note that this form is deprecated. New applications should use #min_version= and #max_version= as necessary.



94
95
96
97
98
# File 'lib/openssl/ssl.rb', line 94

def initialize(version = nil)
  self.ssl_version = version if version
  self.verify_mode = OpenSSL::SSL::VERIFY_NONE
  self.verify_hostname = false
end

Instance Attribute Details

#servername_cbObject

A callback invoked at connect time to distinguish between multiple server names.

The callback is invoked with an SSLSocket and a server name. The callback must return an SSLContext for the server name or nil.



82
83
84
# File 'lib/openssl/ssl.rb', line 82

def servername_cb
  @servername_cb
end

Instance Method Details

#add_certificate(certificate, pkey[, extra_certs]) ⇒ self

Adds a certificate to the context. pkey must be a corresponding private key with certificate.

Multiple certificates with different public key type can be added by repeated calls of this method, and OpenSSL will choose the most appropriate certificate during the handshake.

#cert=, #key=, and #extra_chain_cert= are old accessor methods for setting certificate and internally call this method.

Parameters

certificate

A certificate. An instance of OpenSSL::X509::Certificate.

pkey

The private key for certificate. An instance of OpenSSL::PKey::PKey.

extra_certs

Optional. An array of OpenSSL::X509::Certificate. When sending a certificate chain, the certificates specified by this are sent following certificate, in the order in the array.

Example

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

Returns:



1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
# File 'ext/openssl/ossl_ssl.c', line 1325

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

#ciphersArray

The list of cipher suites configured for this context.

Returns:



964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
# File 'ext/openssl/ossl_ssl.c', line 964

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=(v) ⇒ Object

ctx.ciphers = [name, …]

ctx.ciphers = [[name, version, bits, alg_bits], ...]

Sets the list of available cipher suites for TLS 1.2 and below for this context.

Note in a server context some ciphers require the appropriate certificates. For example, an RSA cipher suite can only be chosen when an RSA certificate is available.

This method does not affect TLS 1.3 connections. See also #ciphersuites=.



1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
# File 'ext/openssl/ossl_ssl.c', line 1024

static VALUE
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    VALUE str;

    rb_check_frozen(self);
    // Assigning nil is a no-op for compatibility
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

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

    return v;
}

#ciphersuites=(v) ⇒ Object

ctx.ciphersuites = [name, …]

Sets the list of available TLS 1.3 cipher suites for this context.



1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
# File 'ext/openssl/ossl_ssl.c', line 1051

static VALUE
ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    VALUE str;

    rb_check_frozen(self);
    // Assigning nil is a no-op for compatibility
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

    GetSSLCTX(self, ctx);
    if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str)))
        ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites");

    return v;
}

#client_sigalgs=(v) ⇒ Object

Sets the list of “supported signature algorithms” for client authentication for this context.

For a TLS server, the list is sent to the client as part of the CertificateRequest message.

See also #sigalgs= for the server authentication equivalent.



1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
# File 'ext/openssl/ossl_ssl.c', line 1113

static VALUE
ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
{
    SSL_CTX *ctx;

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

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

    return v;
}

#enable_fallback_scsvnil

Activate TLS_FALLBACK_SCSV for this context. See RFC 7507.

Returns:



1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
# File 'ext/openssl/ossl_ssl.c', line 1278

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

#flush_sessions(time) ⇒ self

Removes sessions in the internal cache that have expired at time.

Returns:



1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
# File 'ext/openssl/ossl_ssl.c', line 1531

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

#groups=(groups_list) ⇒ Object #ecdh_curves=(groups_list) ⇒ Object Also known as: ecdh_curves=

Sets the list of supported groups for key agreement for this context.

For a TLS client, the list is directly used in the “supported_groups” extension. For a server, the list is used by OpenSSL to determine the set of shared supported groups. OpenSSL will pick the most appropriate one from it.

#ecdh_curves= is a deprecated alias for #groups=.

See also the man page SSL_CTX_set1_groups_list(3).

Example

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

ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.groups = "P-256"
cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
cli.connect

p cli.tmp_key.group.curve_name
# => "prime256v1" (is an alias for NIST P-256)


1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
# File 'ext/openssl/ossl_ssl.c', line 1206

static VALUE
ossl_sslctx_set_groups(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;

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

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

#max_version=(OpenSSL) ⇒ Object

ctx.max_version = nil

Sets the upper bound of the supported SSL/TLS protocol version. See #min_version= for the possible values.



927
928
929
930
931
932
933
934
935
936
937
938
939
940
# File 'ext/openssl/ossl_ssl.c', line 927

static VALUE
ossl_sslctx_set_max_version(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    int version;

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

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

#min_version=(OpenSSL) ⇒ Object

ctx.min_version = nil

Sets the lower bound on the supported SSL/TLS protocol version. The version may be specified by an integer constant named OpenSSL::SSL::*_VERSION, a Symbol, or nil which means “any version”.

Example

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


903
904
905
906
907
908
909
910
911
912
913
914
915
916
# File 'ext/openssl/ossl_ssl.c', line 903

static VALUE
ossl_sslctx_set_min_version(VALUE self, VALUE v)
{
    SSL_CTX *ctx;
    int version;

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

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

#optionsInteger

Gets various OpenSSL options.

Returns:



624
625
626
627
628
629
630
631
632
633
634
# File 'ext/openssl/ossl_ssl.c', line 624

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

#options=(integer) ⇒ Object

Sets various OpenSSL options. The options are a bit field and can be combined with the bitwise OR operator (|). Available options are defined as constants in OpenSSL::SSL that begin with OP_.

For backwards compatibility, passing nil has the same effect as passing OpenSSL::SSL::OP_ALL.

See also man page SSL_CTX_set_options(3).



649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
# File 'ext/openssl/ossl_ssl.c', line 649

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

#security_levelInteger

Returns the security level for the context.

See also OpenSSL::SSL::SSLContext#security_level=.

Returns:



1228
1229
1230
1231
1232
1233
1234
1235
1236
# File 'ext/openssl/ossl_ssl.c', line 1228

static VALUE
ossl_sslctx_get_security_level(VALUE self)
{
    SSL_CTX *ctx;

    GetSSLCTX(self, ctx);

    return INT2NUM(SSL_CTX_get_security_level(ctx));
}

#security_level=(integer) ⇒ Object

Sets the security level for the context. OpenSSL limits parameters according to the level. The “parameters” include: ciphersuites, curves, key sizes, certificate signature algorithms, protocol version and so on. For example, level 1 rejects parameters offering below 80 bits of security, such as ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits.

Note that attempts to set such parameters with insufficient security are also blocked. You need to lower the level first.

This feature is not supported in OpenSSL < 1.1.0, and setting the level to other than 0 will raise NotImplementedError. Level 0 means everything is permitted, the same behavior as previous versions of OpenSSL.

See the manpage of SSL_CTX_set_security_level(3) for details.



1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
# File 'ext/openssl/ossl_ssl.c', line 1257

static VALUE
ossl_sslctx_set_security_level(VALUE self, VALUE value)
{
    SSL_CTX *ctx;

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

    SSL_CTX_set_security_level(ctx, NUM2INT(value));

    return value;
}

#session_add(session) ⇒ Object

Adds session to the session cache.



1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
# File 'ext/openssl/ossl_ssl.c', line 1375

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_cache_modeInteger

The current session cache mode.

Returns:



1411
1412
1413
1414
1415
1416
1417
1418
1419
# File 'ext/openssl/ossl_ssl.c', line 1411

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

Sets the SSL session cache mode. Bitwise-or together the desired SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for details.

Returns:



1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
# File 'ext/openssl/ossl_ssl.c', line 1429

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

#session_cache_sizeInteger

Returns the current session cache size. Zero is used to represent an unlimited cache size.

Returns:



1448
1449
1450
1451
1452
1453
1454
1455
1456
# File 'ext/openssl/ossl_ssl.c', line 1448

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

Sets the session cache size. Returns the previously valid session cache size. Zero is used to represent an unlimited session cache size.

Returns:



1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
# File 'ext/openssl/ossl_ssl.c', line 1465

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_statsHash

Returns a Hash containing the following keys:

:accept

Number of started SSL/TLS handshakes in server mode

:accept_good

Number of established SSL/TLS sessions in server mode

:accept_renegotiate

Number of start renegotiations in server mode

:cache_full

Number of sessions that were removed due to cache overflow

:cache_hits

Number of successfully reused connections

:cache_misses

Number of sessions proposed by clients that were not found

in the cache
:cache_num

Number of sessions in the internal session cache

:cb_hits

Number of sessions retrieved from the external cache in server

mode
:connect

Number of started SSL/TLS handshakes in client mode

:connect_good

Number of established SSL/TLS sessions in client mode

:connect_renegotiate

Number of start renegotiations in client mode

:timeouts

Number of sessions proposed by clients that were found in the

cache but had expired due to timeouts

Returns:



1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
# File 'ext/openssl/ossl_ssl.c', line 1499

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

#session_remove(session) ⇒ Object

Removes session from the session cache.



1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
# File 'ext/openssl/ossl_ssl.c', line 1393

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 = {}) ⇒ Object

call-seq:

ctx.set_params(params = {}) -> params

Sets saner defaults optimized for the use with HTTP-like protocols.

If a Hash params is given, the parameters are overridden with it. The keys in params must be assignment methods on SSLContext.

If the verify_mode is not VERIFY_NONE and ca_file, ca_path and cert_store are not set then the system default certificate store is used.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/openssl/ssl.rb', line 112

def set_params(params={})
  params = DEFAULT_PARAMS.merge(params)
  self.options |= params.delete(:options) # set before min_version/max_version
  params.each{|name, value| self.__send__("#{name}=", value) }
  if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
    unless self.ca_file or self.ca_path or self.cert_store
      if not defined?(Ractor) or Ractor.current == Ractor.main
        self.cert_store = DEFAULT_CERT_STORE
      else
        self.cert_store = Ractor.current[:__openssl_default_store__] ||=
          OpenSSL::X509::Store.new.tap { |store|
            store.set_default_paths
          }
      end
    end
  end
  return params
end

#setupQtrue #firstt time #setupObject Also known as: freeze

This method is called automatically when a new SSLSocket is created. However, it is not thread-safe and must be called before creating SSLSocket objects in a multi-threaded program.

Overloads:

  • #setupQtrue #firstt time

    Returns:



677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
# File 'ext/openssl/ossl_ssl.c', line 677

static VALUE
ossl_sslctx_setup(VALUE self)
{
    SSL_CTX *ctx;
    X509 *cert = NULL, *client_ca = NULL;
    EVP_PKEY *key = NULL;
    char *ca_path = NULL, *ca_file = NULL;
    int verify_mode;
    long i;
    VALUE val;

    if(OBJ_FROZEN(self)) return Qnil;
    GetSSLCTX(self, ctx);

#if !defined(OPENSSL_NO_DH)
    if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) {
        SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
        SSL_CTX_set_dh_auto(ctx, 0);
    }
#endif

#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */
    SSL_CTX_set_post_handshake_auth(ctx, 1);
#endif

    val = rb_attr_get(self, id_i_cert_store);
    if (!NIL_P(val)) {
        X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
        SSL_CTX_set_cert_store(ctx, store);
        X509_STORE_up_ref(store);
    }

    val = rb_attr_get(self, id_i_extra_chain_cert);
    if(!NIL_P(val)){
        rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
    }

    /* private key may be bundled in certificate file. */
    val = rb_attr_get(self, id_i_cert);
    cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
    val = rb_attr_get(self, id_i_key);
    key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
    if (cert && key) {
        if (!SSL_CTX_use_certificate(ctx, cert)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_certificate");
        }
        if (!SSL_CTX_use_PrivateKey(ctx, key)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
        }
        if (!SSL_CTX_check_private_key(ctx)) {
            ossl_raise(eSSLError, "SSL_CTX_check_private_key");
        }
    }

    val = rb_attr_get(self, id_i_client_ca);
    if(!NIL_P(val)){
        if (RB_TYPE_P(val, T_ARRAY)) {
            for(i = 0; i < RARRAY_LEN(val); i++){
                client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
                if (!SSL_CTX_add_client_CA(ctx, client_ca)){
                    /* Copies X509_NAME => FREE it. */
                    ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
                }
            }
        }
        else{
            client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
            if (!SSL_CTX_add_client_CA(ctx, client_ca)){
                /* Copies X509_NAME => FREE it. */
                ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
            }
        }
    }

    val = rb_attr_get(self, id_i_ca_file);
    ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
    val = rb_attr_get(self, id_i_ca_path);
    ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE
    if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file))
        ossl_raise(eSSLError, "SSL_CTX_load_verify_file");
    if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path))
        ossl_raise(eSSLError, "SSL_CTX_load_verify_dir");
#else
    if (ca_file || ca_path) {
        if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
            ossl_raise(eSSLError, "SSL_CTX_load_verify_locations");
    }
#endif

    val = rb_attr_get(self, id_i_verify_mode);
    verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
    SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
    if (RTEST(rb_attr_get(self, id_i_client_cert_cb)))
        SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);

    val = rb_attr_get(self, id_i_timeout);
    if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));

    val = rb_attr_get(self, id_i_verify_depth);
    if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));

#ifdef OSSL_USE_NEXTPROTONEG
    val = rb_attr_get(self, id_i_npn_protocols);
    if (!NIL_P(val)) {
        VALUE encoded = ssl_encode_npn_protocols(val);
        rb_ivar_set(self, id_npn_protocols_encoded, encoded);
        SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
        OSSL_Debug("SSL NPN advertise callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
        SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
        OSSL_Debug("SSL NPN select callback added");
    }
#endif

    val = rb_attr_get(self, id_i_alpn_protocols);
    if (!NIL_P(val)) {
        VALUE rprotos = ssl_encode_npn_protocols(val);

        /* returns 0 on success */
        if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
                                    RSTRING_LENINT(rprotos)))
            ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
        OSSL_Debug("SSL ALPN values added");
    }
    if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
        SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
        OSSL_Debug("SSL ALPN select callback added");
    }

    rb_obj_freeze(self);

    val = rb_attr_get(self, id_i_session_id_context);
    if (!NIL_P(val)){
        StringValue(val);
        if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
                                            RSTRING_LENINT(val))){
            ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
        }
    }

    if (RTEST(rb_attr_get(self, id_i_session_get_cb))) {
        SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
        OSSL_Debug("SSL SESSION get callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_session_new_cb))) {
        SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
        OSSL_Debug("SSL SESSION new callback added");
    }
    if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) {
        SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
        OSSL_Debug("SSL SESSION remove callback added");
    }

    val = rb_attr_get(self, id_i_servername_cb);
    if (!NIL_P(val)) {
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
        OSSL_Debug("SSL TLSEXT servername callback added");
    }

#if !OSSL_IS_LIBRESSL
    /*
     * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
     * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
     * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
     */
    if (RTEST(rb_attr_get(self, id_i_keylog_cb))) {
        SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb);
        OSSL_Debug("SSL keylog callback added");
    }
#endif

    return Qtrue;
}

#sigalgs=(v) ⇒ Object

Sets the list of “supported signature algorithms” for this context.

For a TLS client, the list is used in the “signature_algorithms” extension in the ClientHello message. For a server, the list is used by OpenSSL to determine the set of shared signature algorithms. OpenSSL will pick the most appropriate one from it.

See also #client_sigalgs= for the client authentication equivalent.



1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
# File 'ext/openssl/ossl_ssl.c', line 1085

static VALUE
ossl_sslctx_set_sigalgs(VALUE self, VALUE v)
{
    SSL_CTX *ctx;

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

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

    return v;
}

#ssl_version=(meth) ⇒ Object

call-seq:

ctx.ssl_version = :TLSv1
ctx.ssl_version = "SSLv23"

Sets the SSL/TLS protocol version for the context. This forces connections to use only the specified protocol version. This is deprecated and only provided for backwards compatibility. Use #min_version= and #max_version= instead.

History

As the name hints, this used to call the SSL_CTX_set_ssl_version() function which sets the SSL method used for connections created from the context. As of Ruby/OpenSSL 2.1, this accessor method is implemented to call #min_version= and #max_version= instead.



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/openssl/ssl.rb', line 145

def ssl_version=(meth)
  meth = meth.to_s if meth.is_a?(Symbol)
  if /(?<type>_client|_server)\z/ =~ meth
    meth = $`
    if $VERBOSE
      warn "#{caller(1, 1)[0]}: method type #{type.inspect} is ignored"
    end
  end
  version = METHODS_MAP[meth.intern] or
    raise ArgumentError, "unknown SSL method `%s'" % meth
  self.min_version = self.max_version = version
end

#tmp_dh=(pkey) ⇒ Object

Sets DH parameters used for ephemeral DH key exchange. This is relevant for servers only.

pkey is an instance of OpenSSL::PKey::DH. Note that key components contained in the key object, if any, are ignored. The server will always generate a new key pair for each handshake.

Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey(3).

Example:

ctx = OpenSSL::SSL::SSLContext.new
ctx.tmp_dh = OpenSSL::DH.generate(2048)
svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
Thread.new { svr.accept }


1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
# File 'ext/openssl/ossl_ssl.c', line 1148

static VALUE
ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    EVP_PKEY *pkey;

    rb_check_frozen(self);
    GetSSLCTX(self, ctx);
    pkey = GetPKeyPtr(arg);

    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
        rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
                 OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
    if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
        ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
    EVP_PKEY_up_ref(pkey);
#else
    if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
        ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
#endif

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

    return arg;
}