[前][次][番号順一覧][スレッド一覧]

ruby-changes:4617

From: ko1@a...
Date: Mon, 21 Apr 2008 07:32:20 +0900 (JST)
Subject: [ruby-changes:4617] technorama - Ruby:r16111 (trunk): * ext/openssl/ossl_ssl.c: Switch stats hash key from string to symbol.

technorama	2008-04-21 07:32:06 +0900 (Mon, 21 Apr 2008)

  New Revision: 16111

  Modified files:
    trunk/ext/openssl/ossl_ssl.c
    trunk/ext/openssl/ossl_version.h
    trunk/ext/openssl/ossl_x509ext.c
    trunk/test/openssl/test_ssl.rb
    trunk/test/openssl/utils.rb

  Log:
    * ext/openssl/ossl_ssl.c: Switch stats hash key from string to symbol.
      New method SSLContext#setup to aid C extension writers.
    * test/openssl/test_ssl.rb: Add tests for new method and sessions.
      Use threads for ssl server instead of forking.
    * ext/openssl/ossl_version.h: Bump version.
    * ext/openssl/ossl_x509ext.c: Fix warnings.
    * test/openssl/utils.rb: Fix warnings.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/openssl/ossl_ssl.c?r1=16111&r2=16110&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/openssl/ossl_x509ext.c?r1=16111&r2=16110&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/openssl/utils.rb?r1=16111&r2=16110&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/openssl/test_ssl.rb?r1=16111&r2=16110&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/openssl/ossl_version.h?r1=16111&r2=16110&diff_format=u

Index: ext/openssl/ossl_ssl.c
===================================================================
--- ext/openssl/ossl_ssl.c	(revision 16110)
+++ ext/openssl/ossl_ssl.c	(revision 16111)
@@ -446,6 +446,14 @@
     return i;
 }
 
+/*
+ * call-seq:
+ *    ctx.setup => Qtrue # first time
+ *    ctx.setup => nil # thereafter
+ *
+ * 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).
+ */
 static VALUE
 ossl_sslctx_setup(VALUE self)
 {
@@ -779,18 +787,18 @@
     Data_Get_Struct(self, SSL_CTX, ctx);
 
     hash = rb_hash_new();
-    rb_hash_aset(hash, rb_str_new2("cache_num"), LONG2NUM(SSL_CTX_sess_number(ctx)));
-    rb_hash_aset(hash, rb_str_new2("connect"), LONG2NUM(SSL_CTX_sess_connect(ctx)));
-    rb_hash_aset(hash, rb_str_new2("connect_good"), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
-    rb_hash_aset(hash, rb_str_new2("connect_renegotiate"), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
-    rb_hash_aset(hash, rb_str_new2("accept"), LONG2NUM(SSL_CTX_sess_accept(ctx)));
-    rb_hash_aset(hash, rb_str_new2("accept_good"), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
-    rb_hash_aset(hash, rb_str_new2("accept_renegotiate"), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
-    rb_hash_aset(hash, rb_str_new2("cache_hits"), LONG2NUM(SSL_CTX_sess_hits(ctx)));
-    rb_hash_aset(hash, rb_str_new2("cb_hits"), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
-    rb_hash_aset(hash, rb_str_new2("cache_misses"), LONG2NUM(SSL_CTX_sess_misses(ctx)));
-    rb_hash_aset(hash, rb_str_new2("cache_full"), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
-    rb_hash_aset(hash, rb_str_new2("timeouts"), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
+    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;
 }
@@ -1347,6 +1355,8 @@
     mSSL = rb_define_module_under(mOSSL, "SSL");
     eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
 
+    Init_ossl_ssl_session();
+
     /* class SSLContext
      *
      * The following attributes are available but don't show up in rdoc.
@@ -1365,6 +1375,8 @@
     rb_define_method(cSSLContext, "ciphers",     ossl_sslctx_get_ciphers, 0);
     rb_define_method(cSSLContext, "ciphers=",    ossl_sslctx_set_ciphers, 1);
 
+    rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+
     
     rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
     rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
Index: ext/openssl/ossl_x509ext.c
===================================================================
--- ext/openssl/ossl_x509ext.c	(revision 16110)
+++ ext/openssl/ossl_x509ext.c	(revision 16111)
@@ -110,6 +110,7 @@
     VALUE obj;
 
     MakeX509ExtFactory(klass, obj, ctx);
+    rb_iv_set(obj, "@config", Qnil);
 
     return obj;
 }
Index: ext/openssl/ossl_version.h
===================================================================
--- ext/openssl/ossl_version.h	(revision 16110)
+++ ext/openssl/ossl_version.h	(revision 16111)
@@ -11,6 +11,6 @@
 #if !defined(_OSSL_VERSION_H_)
 #define _OSSL_VERSION_H_
 
-#define OSSL_VERSION "1.0.0"
+#define OSSL_VERSION "1.1.0"
 
 #endif /* _OSSL_VERSION_H_ */
Index: test/openssl/test_ssl.rb
===================================================================
--- test/openssl/test_ssl.rb	(revision 16110)
+++ test/openssl/test_ssl.rb	(revision 16111)
@@ -58,29 +58,78 @@
     OpenSSL::TestUtils.issue_crl(*arg)
   end
 
-  def start_server(port0, verify_mode, start_immediately, &block)
-    server = nil
+  def readwrite_loop(ctx, ssl)
+    while line = ssl.gets
+      if line =~ /^STARTTLS$/
+        ssl.accept
+        next
+      end
+      ssl.write(line)
+    end
+  rescue OpenSSL::SSL::SSLError
+  rescue IOError
+  ensure
+    ssl.close rescue nil
+  end
+
+  def server_loop(ctx, ssls, server_proc)
+    loop do
+      ssl = nil
+      begin
+        ssl = ssls.accept
+      rescue OpenSSL::SSL::SSLError
+      	retry
+      end
+
+      Thread.start do
+        Thread.current.abort_on_exception = true  
+        server_proc.call(ctx, ssl)
+      end
+    end
+  rescue Errno::EBADF, IOError
+  end
+
+  def start_server(port0, verify_mode, start_immediately, args = {}, &block)
+    ctx_proc = args[:ctx_proc]
+    server_proc = args[:server_proc]
+    server_proc ||= method(:readwrite_loop)
+  
+    store = OpenSSL::X509::Store.new
+    store.add_cert(@ca_cert)
+    store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+    ctx = OpenSSL::SSL::SSLContext.new
+    ctx.cert_store = store
+    #ctx.extra_chain_cert = [ ca_cert ]
+    ctx.cert = @svr_cert
+    ctx.key = @svr_key
+    ctx.verify_mode = verify_mode
+    ctx_proc.call(ctx) if ctx_proc
+
+    Socket.do_not_reverse_lookup = true
+    tcps = nil
+    port = port0
     begin
-      cmd = [RUBY]
-      cmd << "-d" if $DEBUG
-      cmd << SSL_SERVER << port0.to_s << verify_mode.to_s
-      cmd << (start_immediately ? "yes" : "no")
-      server = IO.popen(cmd, "w+")
-      server.write(@ca_cert.to_pem)
-      server.write(@svr_cert.to_pem)
-      server.write(@svr_key.to_pem)
-      pid = Integer(server.gets)
-      if port = server.gets
-        if $DEBUG
-          $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port)
-        end
-        block.call(server, port.to_i)
+      tcps = TCPServer.new("127.0.0.1", port)
+    rescue Errno::EADDRINUSE
+      port += 1
+      retry
+    end
+
+    ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+    ssls.start_immediately = start_immediately
+
+    begin
+      server = Thread.new do
+        Thread.current.abort_on_exception = true  
+        server_loop(ctx, ssls, server_proc)
       end
+
+      $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG
+
+      block.call(server, port.to_i)
     ensure
-      if server
-        Process.kill(:KILL, pid)
-        server.close
-      end
+      tcps.close if (tcps)
+      server.join if (server)
     end
   end
 
@@ -93,6 +142,12 @@
     ssl.connect
   end
 
+  def test_ctx_setup
+    ctx = OpenSSL::SSL::SSLContext.new
+    assert_equal(ctx.setup, true)
+    assert_equal(ctx.setup, nil)
+  end
+
   def test_connect_and_close
     start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
       sock = TCPSocket.new("127.0.0.1", port)
@@ -182,7 +237,7 @@
 
       called = nil
       ctx = OpenSSL::SSL::SSLContext.new
-      ctx.client_cert_cb = Proc.new{|ssl|
+      ctx.client_cert_cb = Proc.new{ |sslconn|
         called = true
         [@cli_cert, @cli_key]
       }
@@ -360,6 +415,120 @@
       assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
     }
   end
+
+  def test_client_session
+    last_session = nil
+    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
+      2.times do
+        sock = TCPSocket.new("127.0.0.1", port)
+        ssl = OpenSSL::SSL::SSLSocket.new(sock)
+        ssl.sync_close = true
+        ssl.session = last_session if last_session
+        ssl.connect
+
+        session = ssl.session
+        if last_session
+          assert(ssl.session_reused?)
+
+          if session.respond_to?(:id)
+            assert_equal(session.id, last_session.id)
+          end
+          assert_equal(session.to_pem, last_session.to_pem)
+          assert_equal(session.to_der, last_session.to_der)
+          # Older version of OpenSSL may not be consistent.  Look up which versions later.
+          assert_equal(session.to_text, last_session.to_text)
+        else
+          assert(!ssl.session_reused?)
+        end
+        last_session = session
+
+        str = "x" * 100 + "\n"
+        ssl.puts(str)
+        assert_equal(str, ssl.gets)
+
+        ssl.close
+      end
+    end
+  end
+
+  def test_server_session
+    connections = 0
+    saved_session = nil
+
+    ctx_proc = Proc.new do |ctx, ssl|
+# add test for session callbacks here
+    end
+
+    server_proc = Proc.new do |ctx, ssl|
+      session = ssl.session
+      stats = ctx.session_cache_stats
+
+      case connections
+      when 0
+        assert_equal(stats[:cache_num], 1)
+        assert_equal(stats[:cache_hits], 0)
+        assert_equal(stats[:cache_misses], 0)
+        assert(!ssl.session_reused?)
+      when 1
+        assert_equal(stats[:cache_num], 1)
+        assert_equal(stats[:cache_hits], 1)
+        assert_equal(stats[:cache_misses], 0)
+        assert(ssl.session_reused?)
+        ctx.session_remove(session)
+        saved_session = session
+      when 2
+        assert_equal(stats[:cache_num], 1)
+        assert_equal(stats[:cache_hits], 1)
+        assert_equal(stats[:cache_misses], 1)
+        assert(!ssl.session_reused?)
+        ctx.session_add(saved_session)
+      when 3
+        assert_equal(stats[:cache_num], 2)
+        assert_equal(stats[:cache_hits], 2)
+        assert_equal(stats[:cache_misses], 1)
+        assert(ssl.session_reused?)
+        ctx.flush_sessions(Time.now + 5000)
+      when 4
+        assert_equal(stats[:cache_num], 1)
+        assert_equal(stats[:cache_hits], 2)
+        assert_equal(stats[:cache_misses], 2)
+        assert(!ssl.session_reused?)
+        ctx.session_add(saved_session)
+      end
+      connections += 1
+      
+      readwrite_loop(ctx, ssl)
+    end
+
+    first_session = nil
+    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
+      10.times do |i|
+        sock = TCPSocket.new("127.0.0.1", port)
+        ssl = OpenSSL::SSL::SSLSocket.new(sock)
+        ssl.sync_close = true
+        ssl.session = first_session if first_session
+        ssl.connect
+
+        session = ssl.session
+        if first_session
+          case i
+          when 1; assert(ssl.session_reused?)
+          when 2; assert(!ssl.session_reused?)
+          when 3; assert(ssl.session_reused?)
+          when 4; assert(!ssl.session_reused?)
+          when 5..10; assert(ssl.session_reused?)
+          end
+        end
+        first_session ||= session
+
+        str = "x" * 100 + "\n"
+        ssl.puts(str)
+        assert_equal(str, ssl.gets)
+
+        ssl.close
+      end
+    end
+  end
 end
 
 end
Index: test/openssl/utils.rb
===================================================================
--- test/openssl/utils.rb	(revision 16110)
+++ test/openssl/utils.rb	(revision 16111)
@@ -103,9 +103,9 @@
     crl.version = 1
     crl.last_update = lastup
     crl.next_update = nextup
-    revoke_info.each{|serial, time, reason_code|
+    revoke_info.each{|rserial, time, reason_code|
       revoked = OpenSSL::X509::Revoked.new
-      revoked.serial = serial
+      revoked.serial = rserial
       revoked.time = time
       enum = OpenSSL::ASN1::Enumerated(reason_code)
       ext = OpenSSL::X509::Extension.new("CRLReason", enum)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]