Class: OpenSSL::SSL::SSLContext
- Inherits:
-
Object
- Object
- OpenSSL::SSL::SSLContext
- Defined in:
- ossl_ssl.c,
lib/openssl/ssl-internal.rb
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
- 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 sesison 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
- DEFAULT_PARAMS =
{ :ssl_version => "SSLv23", :verify_mode => OpenSSL::SSL::VERIFY_PEER, :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", :options => OpenSSL::SSL::OP_ALL, }
- DEFAULT_CERT_STORE =
OpenSSL::X509::Store.new
Instance Method Summary collapse
-
#ciphers ⇒ Array
The list of ciphers configured for this context.
-
#ciphers= ⇒ Object
ctx.ciphers = [name, ...] ctx.ciphers = [[name, version, bits, alg_bits], ...].
-
#flush_sessions(time|nil) ⇒ self
Removes sessions in the internal cache that have expired at
time
. -
#initialize ⇒ Object
constructor
You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS.
-
#session_add(session) ⇒ Object
Adds
session
to the session cache. -
#session_cache_mode ⇒ Integer
The current session cache mode.
-
#session_cache_mode=(integer) ⇒ Integer
Sets the SSL session cache mode.
-
#session_cache_size ⇒ Integer
Returns the current session cache size.
-
#session_cache_size=(integer) ⇒ Integer
Sets the session cache size.
-
#session_cache_stats ⇒ Hash
Returns a Hash containing the following keys:.
-
#session_remove(session) ⇒ Object
Removes
session
from the session cache. - #set_params(params = {}) ⇒ Object
-
#setup ⇒ Object
This method is called automatically when a new SSLSocket is created.
-
#ssl_version= ⇒ Object
ctx.ssl_version = "SSLv23_client".
Constructor Details
#new ⇒ Object #new(:TLSv1) ⇒ Object #new("SSLv23_client") ⇒ Object
You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'ossl_ssl.c', line 201
static VALUE
ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE ssl_method;
int i;
for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
char buf[32];
snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
rb_iv_set(self, buf, Qnil);
}
if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
return self;
}
ossl_sslctx_set_ssl_version(self, ssl_method);
return self;
}
|
Instance Method Details
#ciphers ⇒ Array
The list of ciphers configured for this context.
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 |
# File 'ossl_ssl.c', line 708
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
SSL_CTX *ctx;
STACK_OF(SSL_CIPHER) *ciphers;
SSL_CIPHER *cipher;
VALUE ary;
int i, num;
Data_Get_Struct(self, SSL_CTX, 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= ⇒ 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
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 |
# File 'ossl_ssl.c', line 748
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 (TYPE(v) == T_ARRAY) {
str = rb_str_new(0, 0);
for (i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
if (TYPE(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);
}
Data_Get_Struct(self, SSL_CTX, 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
.
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
# File 'ossl_ssl.c', line 947
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);
Data_Get_Struct(self, SSL_CTX, 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;
}
|
#session_add(session) ⇒ Object
Adds session
to the session cache
791 792 793 794 795 796 797 798 799 800 801 |
# File 'ossl_ssl.c', line 791
static VALUE
ossl_sslctx_session_add(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
SSL_SESSION *sess;
Data_Get_Struct(self, SSL_CTX, ctx);
SafeGetSSLSession(arg, sess);
return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}
|
#session_cache_mode ⇒ Integer
The current session cache mode.
827 828 829 830 831 832 833 834 835 |
# File 'ossl_ssl.c', line 827
static VALUE
ossl_sslctx_get_session_cache_mode(VALUE self)
{
SSL_CTX *ctx;
Data_Get_Struct(self, SSL_CTX, 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.
845 846 847 848 849 850 851 852 853 854 855 |
# File 'ossl_ssl.c', line 845
static VALUE
ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
Data_Get_Struct(self, SSL_CTX, ctx);
SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
return arg;
}
|
#session_cache_size ⇒ Integer
Returns the current session cache size. Zero is used to represent an unlimited cache size.
864 865 866 867 868 869 870 871 872 |
# File 'ossl_ssl.c', line 864
static VALUE
ossl_sslctx_get_session_cache_size(VALUE self)
{
SSL_CTX *ctx;
Data_Get_Struct(self, SSL_CTX, 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.
881 882 883 884 885 886 887 888 889 890 891 |
# File 'ossl_ssl.c', line 881
static VALUE
ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
Data_Get_Struct(self, SSL_CTX, ctx);
SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
return arg;
}
|
#session_cache_stats ⇒ Hash
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
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
# File 'ossl_ssl.c', line 915
static VALUE
ossl_sslctx_get_session_cache_stats(VALUE self)
{
SSL_CTX *ctx;
VALUE hash;
Data_Get_Struct(self, SSL_CTX, 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
809 810 811 812 813 814 815 816 817 818 819 |
# File 'ossl_ssl.c', line 809
static VALUE
ossl_sslctx_session_remove(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
SSL_SESSION *sess;
Data_Get_Struct(self, SSL_CTX, ctx);
SafeGetSSLSession(arg, sess);
return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
}
|
#set_params(params = {}) ⇒ Object
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/openssl/ssl-internal.rb', line 36 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 |
#setup ⇒ Qtrue # first time #setup ⇒ Object
This method is called automatically when a new SSLSocket is created. Normally you do not need to call this method (unless you are writing an extension in C).
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 |
# File 'ossl_ssl.c', line 542
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 i, verify_mode;
VALUE val;
if(OBJ_FROZEN(self)) return Qnil;
Data_Get_Struct(self, SSL_CTX, ctx);
#if !defined(OPENSSL_NO_DH)
if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
}
else{
SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
}
#endif
SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
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(TYPE(val) == T_ARRAY){
for(i = 0; i < RARRAY_LEN(val); i++){
client_ca = GetX509CertPtr(RARRAY_PTR(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));
val = ossl_sslctx_get_options(self);
if(!NIL_P(val)) {
SSL_CTX_set_options(ctx, NUM2LONG(val));
}
else {
SSL_CTX_set_options(ctx, SSL_OP_ALL);
}
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= ⇒ Object
ctx.ssl_version = "SSLv23_client"
You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'ossl_ssl.c', line 164
static VALUE
ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
SSL_METHOD *method = NULL;
const char *s;
int i;
SSL_CTX *ctx;
if(TYPE(ssl_method) == T_SYMBOL)
s = rb_id2name(SYM2ID(ssl_method));
else
s = StringValuePtr(ssl_method);
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 `%s'.", s);
}
Data_Get_Struct(self, SSL_CTX, ctx);
if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
}
return ssl_method;
}
|