From 060184c347822b11dff3db6bef915c04a564c4e4 Mon Sep 17 00:00:00 2001 From: emboss <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> Date: Sun, 6 May 2012 22:26:08 +0000 Subject: [PATCH] * ext/openssl/ossl_ssl.c: support TLSv1.1 & TLSv1.1. Add SSLContext#version to inspect the version that was negotiated for a given connection. * ext/openssl/extconf.rb: detect TLS 1.1 & 1.2 support. * test/openssl/test_ssl.rb: add tests for TLS 1.1 & 1.2 given they are supported by the native OpenSSL being used. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35549 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 +++++++++ ext/openssl/extconf.rb | 6 ++++++ ext/openssl/ossl_ssl.c | 43 +++++++++++++++++++++++++++++++++++----- test/openssl/test_ssl.rb | 29 +++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1351c8b768..d765423347 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Mon May 07 09:14:11 2012 Martin Bosslet <Martin.Bosslet@googlemail.com> + + * ext/openssl/ossl_ssl.c: support TLSv1.1 & TLSv1.1. Add + SSLContext#version to inspect the version that was negotiated for + a given connection. + * ext/openssl/extconf.rb: detect TLS 1.1 & 1.2 support. + * test/openssl/test_ssl.rb: add tests for TLS 1.1 & 1.2 given they + are supported by the native OpenSSL being used. + Sun May 6 21:34:29 2012 NARUSE, Yui <naruse@ruby-lang.org> * io.c (io_encoding_set): suppress warnings. [ruby-dev:45627] diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 640348f64a..ff27fad327 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -103,6 +103,12 @@ have_func("OPENSSL_cleanse") have_func("SSLv2_method") have_func("SSLv2_server_method") have_func("SSLv2_client_method") +have_func("TLSv1_1_method") +have_func("TLSv1_1_server_method") +have_func("TLSv1_1_client_method") +have_func("TLSv1_2_method") +have_func("TLSv1_2_server_method") +have_func("TLSv1_2_client_method") unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") end diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 79941db1ee..3746f97fa7 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -107,6 +107,18 @@ struct { OSSL_SSL_METHOD_ENTRY(TLSv1), OSSL_SSL_METHOD_ENTRY(TLSv1_server), OSSL_SSL_METHOD_ENTRY(TLSv1_client), +#if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \ + defined(HAVE_TLSV1_2_CLIENT_METHOD) + OSSL_SSL_METHOD_ENTRY(TLSv1_2), + OSSL_SSL_METHOD_ENTRY(TLSv1_2_server), + OSSL_SSL_METHOD_ENTRY(TLSv1_2_client), +#endif +#if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \ + defined(HAVE_TLSV1_1_CLIENT_METHOD) + OSSL_SSL_METHOD_ENTRY(TLSv1_1), + OSSL_SSL_METHOD_ENTRY(TLSv1_1_server), + OSSL_SSL_METHOD_ENTRY(TLSv1_1_client), +#endif #if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \ defined(HAVE_SSLV2_CLIENT_METHOD) OSSL_SSL_METHOD_ENTRY(SSLv2), @@ -1505,11 +1517,31 @@ ossl_ssl_get_peer_cert_chain(VALUE self) } /* - * call-seq: - * ssl.cipher => [name, version, bits, alg_bits] - * - * The cipher being used for the current connection - */ +* call-seq: +* ssl.version => String +* +* Returns a String representing the SSL/TLS version that was negotiated +* for the connection, for example "TLSv1.2". +*/ +static VALUE +ossl_ssl_get_version(VALUE self) +{ + SSL *ssl; + + Data_Get_Struct(self, SSL, ssl); + if (!ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + return rb_str_new2(SSL_get_version(ssl)); +} + +/* +* call-seq: +* ssl.cipher => [name, version, bits, alg_bits] +* +* The cipher being used for the current connection +*/ static VALUE ossl_ssl_get_cipher(VALUE self) { @@ -1957,6 +1989,7 @@ Init_ossl_ssl() rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0); rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0); rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0); + rb_define_method(cSSLSocket, "ssl_version", ossl_ssl_get_version, 0); rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0); rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0); rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0); diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 033d1e8be5..3ccb3cda87 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -437,6 +437,35 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ssl.close } end + + def test_tls_v_1_1 + ctx_proc = Proc.new { |ctx| + ctx.ssl_version = :TLSv1_1 + } + start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) { |server, port| + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock) + ssl.sync_close = true + ssl.connect + assert_equal("TLSv1.1", ssl.ssl_version) + ssl.close + } + end if OpenSSL::SSL::SSLContext::METHODS.include? :TLSv1_1 + + def test_tls_v_1_2 + ctx_proc = Proc.new { |ctx| + ctx.ssl_version = :TLSv1_2 + } + start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) { |server, port| + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock) + ssl.sync_close = true + ssl.connect + assert_equal("TLSv1.2", ssl.ssl_version) + ssl.close + } + end if OpenSSL::SSL::SSLContext::METHODS.include? :TLSv1_2 + end end