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

ruby-changes:20156

From: nahi <ko1@a...>
Date: Wed, 22 Jun 2011 22:40:09 +0900 (JST)
Subject: [ruby-changes:20156] nahi:r32204 (trunk): * ext/openssl/ossl_ssl.c (ossl_sslctx_session_new_cb): Return 0 to

nahi	2011-06-22 22:39:56 +0900 (Wed, 22 Jun 2011)

  New Revision: 32204

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32204

  Log:
    * ext/openssl/ossl_ssl.c (ossl_sslctx_session_new_cb): Return 0 to
      OpenSSL from the callback for SSL_CTX_sess_set_get_cb().
      Returning 0 means to OpenSSL that the the session is still valid
      (since we created Ruby Session object) and was not freed by us with
      SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
      session_get_cb block if you don't want OpenSSL to cache the session
      internally.
      This potential issue was pointed by Ippei Obayashi. See #4416.
    
    * test/openssl/test_ssl_session.rb (test_ctx_server_session_cb): Test
      it.

  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/ossl_ssl.c
    trunk/test/openssl/test_ssl_session.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 32203)
+++ ChangeLog	(revision 32204)
@@ -1,3 +1,17 @@
+Wed Jun 22 22:34:05 2011  Hiroshi Nakamura  <nahi@r...>
+
+	* ext/openssl/ossl_ssl.c (ossl_sslctx_session_new_cb): Return 0 to
+	  OpenSSL from the callback for SSL_CTX_sess_set_get_cb().
+	  Returning 0 means to OpenSSL that the the session is still valid
+	  (since we created Ruby Session object) and was not freed by us with
+	  SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
+	  session_get_cb block if you don't want OpenSSL to cache the session
+	  internally.
+	  This potential issue was pointed by Ippei Obayashi. See #4416.
+
+	* test/openssl/test_ssl_session.rb (test_ctx_server_session_cb): Test
+	  it.
+
 Wed Jun 22 22:21:17 2011  Martin Bosslet  <Martin.Bosslet@g...>
 
 	* ext/openssl/ossl_ssl_session.c: Respect T_BIGNUM time values. Patch by
Index: ext/openssl/ossl_ssl.c
===================================================================
--- ext/openssl/ossl_ssl.c	(revision 32203)
+++ ext/openssl/ossl_ssl.c	(revision 32204)
@@ -400,10 +400,16 @@
     ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
     if (state) {
         rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
-        return 0; /* what should be returned here??? */
     }
 
-    return RTEST(ret_obj) ? 1 : 0;
+    /*
+     * return 0 which means to OpenSSL that the the session is still
+     * valid (since we created Ruby Session object) and was not freed by us
+     * with SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
+     * session_get_cb block if you don't want OpenSSL to cache the session
+     * internally.
+     */
+    return 0;
 }
 
 static VALUE
Index: test/openssl/test_ssl_session.rb
===================================================================
--- test/openssl/test_ssl_session.rb	(revision 32203)
+++ test/openssl/test_ssl_session.rb	(revision 32204)
@@ -159,16 +159,18 @@
     called = {}
     ctx = OpenSSL::SSL::SSLContext.new("SSLv3")
     ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
+
     ctx.session_new_cb = lambda { |ary|
       sock, sess = ary
       called[:new] = [sock, sess]
-      true
     }
+
     ctx.session_remove_cb = lambda { |ary|
       ctx, sess = ary
       called[:remove] = [ctx, sess]
       # any resulting value is OK (ignored)
     }
+
     start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
       sock = TCPSocket.new("127.0.0.1", port)
       ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
@@ -183,6 +185,63 @@
       ssl.close
     end
   end
+
+  def test_ctx_server_session_cb
+    called = {}
+
+    ctx_proc = Proc.new { |ctx, ssl|
+      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
+      last_server_session = nil
+
+      # get_cb is called whenever a client proposed to resume a session but
+      # the session could not be found in the internal session cache.
+      ctx.session_get_cb = lambda { |ary|
+        sess, data = ary
+        if last_server_session
+          called[:get2] = [sess, data]
+          last_server_session
+        else
+          called[:get1] = [sess, data]
+          last_server_session = sess
+          nil
+        end
+      }
+
+      ctx.session_new_cb = lambda { |ary|
+        sock, sess = ary
+        called[:new] = [sock, sess]
+        # SSL server doesn't cache sessions so get_cb is called next time.
+        ctx.session_remove(sess)
+      }
+
+      ctx.session_remove_cb = lambda { |ary|
+        ctx, sess = ary
+        called[:remove] = [ctx, sess]
+      }
+    }
+
+    server_proc = Proc.new { |c, ssl|
+      session = ssl.session
+      stats = c.session_cache_stats
+      readwrite_loop(c, ssl)
+    }
+    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
+      last_client_session = nil
+      3.times do
+        sock = TCPSocket.new("127.0.0.1", port)
+        ssl = OpenSSL::SSL::SSLSocket.new(sock, OpenSSL::SSL::SSLContext.new("SSLv3"))
+        ssl.sync_close = true
+        ssl.session = last_client_session if last_client_session
+        ssl.connect
+        last_client_session = ssl.session
+        ssl.close
+        assert(called.delete(:new))
+        assert(called.delete(:remove))
+      end
+    end
+    assert(called[:get1])
+    assert(called[:get2])
+  end
 end
 
 end

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

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