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:
  :min_version => OpenSSL::SSL::TLS1_VERSION,
  :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_TMP_DH_CALLBACK =

:nodoc:

lambda { |ctx, is_export, keylen| # :nodoc:
  warn "using default DH parameters." if $VERBOSE
  DH_ffdhe2048
}
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.



127
128
129
130
131
132
# File 'lib/openssl/ssl.rb', line 127

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

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.



115
116
117
# File 'lib/openssl/ssl.rb', line 115

def servername_cb
  @servername_cb
end

#tmp_dh_callbackObject

A callback invoked when DH parameters are required for ephemeral DH key exchange.

The callback is invoked with the SSLSocket, a flag indicating the use of an export cipher and the keylength required.

The callback must return an OpenSSL::PKey::DH instance of the correct key length.

Deprecated in version 3.0. Use #tmp_dh= instead.



108
109
110
# File 'lib/openssl/ssl.rb', line 108

def tmp_dh_callback
  @tmp_dh_callback
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:

  • (self)


1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
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
# File 'ext/openssl/ossl_ssl.c', line 1311

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:

  • (Array)


1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
# File 'ext/openssl/ossl_ssl.c', line 1002

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 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.



1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
# File 'ext/openssl/ossl_ssl.c', line 1058

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

    rb_check_frozen(self);
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

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

    return v;
}

#ciphersuites=(v) ⇒ Object

ctx.ciphersuites = [name, …]

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

Sets the list of available TLSv1.3 cipher suites for this context.



1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
# File 'ext/openssl/ossl_ssl.c', line 1086

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

    rb_check_frozen(self);
    if (NIL_P(v))
        return v;

    str = build_cipher_string(v);

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

    return v;
}

#ecdh_curves=(curve_list) ⇒ Object

Sets the list of “supported elliptic curves” for this context.

For a TLS client, the list is directly used in the Supported Elliptic Curves Extension. For a server, the list is used by OpenSSL to determine the set of shared curves. OpenSSL will pick the most appropriate one from it.

Example

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)


1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
# File 'ext/openssl/ossl_ssl.c', line 1177

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

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

    if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
	ossl_raise(eSSLError, NULL);
    return arg;
}

#enable_fallback_scsvnil

Activate TLS_FALLBACK_SCSV for this context. See RFC 7507.

Returns:

  • (nil)


1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
# File 'ext/openssl/ossl_ssl.c', line 1264

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:

  • (self)


1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
# File 'ext/openssl/ossl_ssl.c', line 1517

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

#max_version=(version) ⇒ Object

call-seq:

ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
ctx.max_version = :TLS1_2
ctx.max_version = nil

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



190
191
192
193
# File 'lib/openssl/ssl.rb', line 190

def max_version=(version)
  set_minmax_proto_version(@min_proto_version ||= nil, version)
  @max_proto_version = version
end

#min_version=(version) ⇒ Object

call-seq:

ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
ctx.min_version = :TLS1_2
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”.

Be careful that you don’t overwrite OpenSSL::SSL::OP_NO_SSL,TLSv* options by #options= once you have called #min_version= or #max_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


178
179
180
181
# File 'lib/openssl/ssl.rb', line 178

def min_version=(version)
  set_minmax_proto_version(version, @max_proto_version ||= nil)
  @min_proto_version = version
end

#optionsObject

Gets various OpenSSL options.



762
763
764
765
766
767
768
769
770
771
772
# File 'ext/openssl/ossl_ssl.c', line 762

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

Sets various OpenSSL options.



777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
# File 'ext/openssl/ossl_ssl.c', line 777

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:



1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
# File 'ext/openssl/ossl_ssl.c', line 1202

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=(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.



1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
# File 'ext/openssl/ossl_ssl.c', line 1236

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

#session_add(session) ⇒ Object

Adds session to the session cache.



1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
# File 'ext/openssl/ossl_ssl.c', line 1361

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:



1397
1398
1399
1400
1401
1402
1403
1404
1405
# File 'ext/openssl/ossl_ssl.c', line 1397

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:



1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
# File 'ext/openssl/ossl_ssl.c', line 1415

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:



1434
1435
1436
1437
1438
1439
1440
1441
1442
# File 'ext/openssl/ossl_ssl.c', line 1434

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:



1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
# File 'ext/openssl/ossl_ssl.c', line 1451

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:

  • (Hash)


1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
# File 'ext/openssl/ossl_ssl.c', line 1485

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.



1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
# File 'ext/openssl/ossl_ssl.c', line 1379

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.



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

def set_params(params={})
  params = DEFAULT_PARAMS.merge(params)
  self.options = params.delete(:options) # set before min_version/max_version
  params.each{|name, value| self.__send__("#{name}=", value) }
  if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
    unless self.ca_file or self.ca_path or self.cert_store
      self.cert_store = DEFAULT_CERT_STORE
    end
  end
  return params
end

#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:

    • (Qtrue #firstt time)


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
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
# File 'ext/openssl/ossl_ssl.c', line 805

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

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

#if !defined(OPENSSL_NO_DH)
    SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
#endif

#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
    SSL_CTX_set_post_handshake_auth(ctx, 1);
#endif

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

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

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

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

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

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

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

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

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

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

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

    rb_obj_freeze(self);

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

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

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

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

    return Qtrue;
}

#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.



209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/openssl/ssl.rb', line 209

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

#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_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 }


1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
# File 'ext/openssl/ossl_ssl.c', line 1126

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

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

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

    return arg;
}