Class: OpenSSL::SSL::SSLContext

Inherits:
Object
  • Object
show all
Defined in:
ossl_ssl.c,
lib/openssl/ssl.rb,
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.

The following attributes are available but don’t show up in rdoc:

  • ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,

  • verify_mode, verify_depth client_cert_cb, tmp_dh_callback,

  • session_id_context, session_add_cb, session_new_cb, session_remove_cb

Constant Summary collapse

DEFAULT_PARAMS =
{
  :ssl_version => "SSLv23",
  :verify_mode => OpenSSL::SSL::VERIFY_PEER,
  :ciphers => %w{
    ECDHE-ECDSA-AES128-GCM-SHA256
    ECDHE-RSA-AES128-GCM-SHA256
    ECDHE-ECDSA-AES256-GCM-SHA384
    ECDHE-RSA-AES256-GCM-SHA384
    DHE-RSA-AES128-GCM-SHA256
    DHE-DSS-AES128-GCM-SHA256
    DHE-RSA-AES256-GCM-SHA384
    DHE-DSS-AES256-GCM-SHA384
    ECDHE-ECDSA-AES128-SHA256
    ECDHE-RSA-AES128-SHA256
    ECDHE-ECDSA-AES128-SHA
    ECDHE-RSA-AES128-SHA
    ECDHE-ECDSA-AES256-SHA384
    ECDHE-RSA-AES256-SHA384
    ECDHE-ECDSA-AES256-SHA
    ECDHE-RSA-AES256-SHA
    DHE-RSA-AES128-SHA256
    DHE-RSA-AES256-SHA256
    DHE-RSA-AES128-SHA
    DHE-RSA-AES256-SHA
    DHE-DSS-AES128-SHA256
    DHE-DSS-AES256-SHA256
    DHE-DSS-AES128-SHA
    DHE-DSS-AES256-SHA
    AES128-GCM-SHA256
    AES256-GCM-SHA384
    AES128-SHA256
    AES256-SHA256
    AES128-SHA
    AES256-SHA
    ECDHE-ECDSA-RC4-SHA
    ECDHE-RSA-RC4-SHA
    RC4-SHA
  }.join(":"),
  :options => -> {
    opts = OpenSSL::SSL::OP_ALL
    opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
    opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
    opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
    opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
    opts
  }.call
}
DEFAULT_CERT_STORE =
OpenSSL::X509::Store.new
INIT_VARS =
["cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
"verify_callback", "cert_store", "extra_chain_cert",
"client_cert_cb", "session_id_context", "tmp_dh_callback",
"session_get_cb", "session_new_cb", "session_remove_cb",
"tmp_ecdh_callback", "servername_cb", "npn_protocols",
"alpn_protocols", "alpn_select_cb",
"npn_select_cb"].map { |x| "@#{x}" }
SESSION_CACHE_OFF =

No session caching for client or server

LONG2FIX(SSL_SESS_CACHE_OFF)
SESSION_CACHE_CLIENT =

doesn’t actually do anything in 0.9.8e

LONG2FIX(SSL_SESS_CACHE_CLIENT)
SESSION_CACHE_SERVER =

Server sessions are added to the session cache

LONG2FIX(SSL_SESS_CACHE_SERVER)
SESSION_CACHE_BOTH =

no different than CACHE_SERVER in 0.9.8e

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

LONG2FIX(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

LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)
SESSION_CACHE_NO_INTERNAL_STORE =

Never automatically store sessions in the internal store.

LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE)
SESSION_CACHE_NO_INTERNAL =

Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and SESSION_CACHE_NO_INTERNAL_STORE.

LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL)
METHODS =

The list of available SSL/TLS methods

ary

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_client") => ctx

You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS



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

def initialize(version = nil)
  INIT_VARS.each { |v| instance_variable_set v, nil }
  self.options = self.options | OpenSSL::SSL::OP_ALL
  return unless version
  self.ssl_version = version
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.



99
100
101
# File 'lib/openssl/ssl.rb', line 99

def servername_cb
  @servername_cb
end

#tmp_dh_callbackObject

A callback invoked when DH parameters are required.

The callback is invoked with the Session for the key exchange, an 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.



91
92
93
# File 'lib/openssl/ssl.rb', line 91

def tmp_dh_callback
  @tmp_dh_callback
end

Instance Method Details

#ciphersArray

The list of ciphers configured for this context.

Returns:

  • (Array)


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
# File 'ossl_ssl.c', line 880

static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciphers;
    SSL_CIPHER *cipher;
    VALUE ary;
    int i, num;

    GetSSLCTX(self, ctx);
    if(!ctx){
        rb_warning("SSL_CTX is not initialized.");
        return Qnil;
    }
    ciphers = ctx->cipher_list;

    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 ciphers for this context. Note in a server context some ciphers require the appropriate certificates. For example, an RSA cipher can only be chosen when an RSA certificate is available.

See also OpenSSL::Cipher and OpenSSL::Cipher::ciphers



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
# File 'ossl_ssl.c', line 920

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(!ctx){
        ossl_raise(eSSLError, "SSL_CTX is not initialized.");
        return Qnil;
    }
    if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
        ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
    }

    return v;
}

#flush_sessions(time|nil) ⇒ self

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

Returns:

  • (self)


1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
# File 'ossl_ssl.c', line 1118

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

#optionsObject

Gets various OpenSSL options.



655
656
657
658
659
660
661
# File 'ossl_ssl.c', line 655

static VALUE
ossl_sslctx_get_options(VALUE self)
{
    SSL_CTX *ctx;
    GetSSLCTX(self, ctx);
    return LONG2NUM(SSL_CTX_get_options(ctx));
}

#options=(options) ⇒ Object

Sets various OpenSSL options.



666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
# File 'ossl_ssl.c', line 666

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, NUM2LONG(options));
    }

    return self;
}

#session_add(session) ⇒ Object

Adds session to the session cache



962
963
964
965
966
967
968
969
970
971
972
# File 'ossl_ssl.c', line 962

static VALUE
ossl_sslctx_session_add(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    SSL_SESSION *sess;

    GetSSLCTX(self, ctx);
    SafeGetSSLSession(arg, sess);

    return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}

#session_cache_modeInteger

The current session cache mode.

Returns:



998
999
1000
1001
1002
1003
1004
1005
1006
# File 'ossl_ssl.c', line 998

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:



1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
# File 'ossl_ssl.c', line 1016

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:



1035
1036
1037
1038
1039
1040
1041
1042
1043
# File 'ossl_ssl.c', line 1035

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:



1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
# File 'ossl_ssl.c', line 1052

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)


1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
# File 'ossl_ssl.c', line 1086

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



980
981
982
983
984
985
986
987
988
989
990
# File 'ossl_ssl.c', line 980

static VALUE
ossl_sslctx_session_remove(VALUE self, VALUE arg)
{
    SSL_CTX *ctx;
    SSL_SESSION *sess;

    GetSSLCTX(self, ctx);
    SafeGetSSLSession(arg, sess);

    return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}

#set_params(params = {}) ⇒ Object

Sets the parameters for this SSL context to the values in params. 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.



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

def set_params(params={})
  params = DEFAULT_PARAMS.merge(params)
  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

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)


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
854
855
856
# File 'ossl_ssl.c', line 694

static VALUE
ossl_sslctx_setup(VALUE self)
{
    SSL_CTX *ctx;
    X509 *cert = NULL, *client_ca = NULL;
    X509_STORE *store;
    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)
    if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){
	SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
    }
#endif

    val = ossl_sslctx_get_cert_store(self);
    if(!NIL_P(val)){
	/*
         * 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.
	 */
        store = GetX509StorePtr(val); /* NO NEED TO DUP */
        SSL_CTX_set_cert_store(ctx, store);
        SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
    }

    val = ossl_sslctx_get_extra_cert(self);
    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 = ossl_sslctx_get_cert(self);
    cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
    val = ossl_sslctx_get_key(self);
    key = NIL_P(val) ? NULL : GetPKeyPtr(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 = ossl_sslctx_get_client_ca(self);
    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 = ossl_sslctx_get_ca_file(self);
    ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
    val = ossl_sslctx_get_ca_path(self);
    ca_path = NIL_P(val) ? NULL : StringValuePtr(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 = ossl_sslctx_get_verify_mode(self);
    verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
    SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
    if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
	SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);

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

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

#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
    val = rb_iv_get(self, "@npn_protocols");
    if (!NIL_P(val)) {
	rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
	SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
	OSSL_Debug("SSL NPN advertise callback added");
    }
    if (RTEST(rb_iv_get(self, "@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_iv_get(self, "@alpn_protocols");
    if (!NIL_P(val)) {
	VALUE rprotos = ssl_encode_npn_protocols(val);
	SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos));
	OSSL_Debug("SSL ALPN values added");
    }
    if (RTEST(rb_iv_get(self, "@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 = ossl_sslctx_get_sess_id_ctx(self);
    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_iv_get(self, "@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_iv_get(self, "@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_iv_get(self, "@session_remove_cb"))) {
	SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
	OSSL_Debug("SSL SESSION remove callback added");
    }

#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
    val = rb_iv_get(self, "@servername_cb");
    if (!NIL_P(val)) {
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
	OSSL_Debug("SSL TLSEXT servername callback added");
    }
#endif

    return Qtrue;
}

#ssl_version=(ssl_method) ⇒ Object

ctx.ssl_version = “SSLv23_client”

You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'ossl_ssl.c', line 174

static VALUE
ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
    SSL_METHOD *method = NULL;
    const char *s;
    VALUE m = ssl_method;
    int i;

    SSL_CTX *ctx;
    if (RB_TYPE_P(ssl_method, T_SYMBOL))
	m = rb_sym2str(ssl_method);
    s = StringValueCStr(m);
    for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
        if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
            method = ossl_ssl_method_tab[i].func();
            break;
        }
    }
    if (!method) {
        ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m);
    }
    GetSSLCTX(self, ctx);
    if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
        ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
    }

    return ssl_method;
}