@@ -236,6 +236,9 @@ def socket_pair():
236236
237237
238238def handshake (client , server ):
239+ """
240+ Wait until the TLS handshake is done on both client and server side.
241+ """
239242 conns = [client , server ]
240243 while conns :
241244 for conn in conns :
@@ -2755,43 +2758,141 @@ def test_set_session_wrong_args(self):
27552758 with pytest .raises (TypeError ):
27562759 connection .set_session (object ())
27572760
2758- def test_client_set_session (self ):
2761+ def test_session_reused (self ):
2762+ """
2763+ `Connection.session_reused`, returns 0 for new connections..
2764+ """
2765+ ctx = Context (TLSv1_2_METHOD )
2766+ connection = Connection (ctx , None )
2767+
2768+ assert connection .session_reused () == 0
2769+
2770+ def test_client_set_session_tls1_2 (self ):
27592771 """
27602772 `Connection.set_session`, when used prior to a connection being
27612773 established, accepts a `Session` instance and causes an attempt to
27622774 re-use the session it represents when the SSL handshake is performed.
2775+
2776+ `Connection.session_reused` is used to query the reuse status.
27632777 """
27642778 key = load_privatekey (FILETYPE_PEM , server_key_pem )
27652779 cert = load_certificate (FILETYPE_PEM , server_cert_pem )
2766- ctx = Context (TLSv1_2_METHOD )
2767- ctx .use_privatekey (key )
2768- ctx .use_certificate (cert )
2769- ctx .set_session_id (b"unity-test" )
2780+ server_ctx = Context (TLSv1_2_METHOD )
2781+ server_ctx .use_privatekey (key )
2782+ server_ctx .use_certificate (cert )
2783+ # !!!!
2784+ # I have no idea why it works when server-side cache is disabled.
2785+ # I guess that this might be because server and client are in the
2786+ # same process.
2787+ server_ctx .set_session_cache_mode (SSL .SESS_CACHE_OFF )
2788+ server_ctx .set_session_id (b"unity-test" )
2789+ server_ctx .set_min_proto_version (TLS1_2_VERSION )
2790+ # Session is reused even when client cache is disabled.
2791+ client_ctx = Context (TLSv1_2_METHOD )
2792+ client_ctx .set_session_cache_mode (SSL .SESS_CACHE_OFF )
2793+ client_ctx .set_min_proto_version (TLS1_2_VERSION )
2794+ originalSession = None
27702795
27712796 def makeServer (socket ):
2772- server = Connection (ctx , socket )
2797+ server = Connection (server_ctx , socket )
27732798 server .set_accept_state ()
27742799 return server
27752800
2776- originalServer , originalClient = loopback (server_factory = makeServer )
2801+ def makeClient (socket ):
2802+ client = Connection (client_ctx , socket )
2803+ client .set_connect_state ()
2804+ if originalSession is not None :
2805+ client .set_session (originalSession )
2806+ return client
2807+
2808+ originalServer , originalClient = loopback (
2809+ server_factory = makeServer , client_factory = makeClient )
27772810 originalSession = originalClient .get_session ()
27782811
2812+ assert originalServer .session_reused () == 0
2813+ assert originalClient .session_reused () == 0
2814+
2815+ resumedServer , resumedClient = loopback (
2816+ server_factory = makeServer , client_factory = makeClient
2817+ )
2818+
2819+ # The session on the original connections are not reused.
2820+ assert originalServer .session_reused () == 0
2821+ assert originalClient .session_reused () == 0
2822+
2823+ # The sessions on the new connections are reused.
2824+ assert resumedServer .session_reused () == 1
2825+ assert resumedClient .session_reused () == 1
2826+
2827+ # This is a proxy: in general, we have no access to any unique
2828+ # identifier for the session (new enough versions of OpenSSL expose
2829+ # a hash which could be usable, but "new enough" is very, very new).
2830+ # Instead, exploit the fact that the master key is re-used if the
2831+ # session is re-used. As long as the master key for the two
2832+ # connections is the same, the session was re-used!
2833+ assert originalServer .master_key () == resumedServer .master_key ()
2834+ assert originalClient .master_key () == resumedClient .master_key ()
2835+
2836+ def test_client_set_session_tls1_3 (self ):
2837+ """
2838+ Test run for `Connection.set_session` and `Connection.session_reused`
2839+ when TLS 1.3 is used.
2840+ """
2841+ key = load_privatekey (FILETYPE_PEM , server_key_pem )
2842+ cert = load_certificate (FILETYPE_PEM , server_cert_pem )
2843+ server_ctx = Context (TLS_METHOD )
2844+ server_ctx .use_privatekey (key )
2845+ server_ctx .use_certificate (cert )
2846+
2847+ # Session is reused even when server cache is disabled.
2848+ server_ctx .set_session_cache_mode (SESS_CACHE_SERVER )
2849+ server_ctx .set_session_id (b"unity-test" )
2850+ server_ctx .set_min_proto_version (TLS1_3_VERSION )
2851+ server_ctx .set_options (OP_NO_TICKET )
2852+
2853+ client_ctx = Context (TLS_METHOD )
2854+ client_ctx .set_options (OP_NO_TICKET )
2855+ originalSession = None
2856+
2857+ def makeServer (socket ):
2858+ server = Connection (server_ctx , socket )
2859+ server .set_accept_state ()
2860+ return server
2861+
27792862 def makeClient (socket ):
2780- client = loopback_client_factory (socket )
2781- client .set_session (originalSession )
2863+ client = Connection (client_ctx , socket )
2864+ client .set_connect_state ()
2865+ if originalSession is not None :
2866+ client .set_session (originalSession )
27822867 return client
27832868
2869+ originalServer , originalClient = loopback (
2870+ server_factory = makeServer , client_factory = makeClient )
2871+ originalSession = originalClient .get_session ()
2872+
2873+ assert originalServer .session_reused () == 0
2874+ assert originalClient .session_reused () == 0
2875+
27842876 resumedServer , resumedClient = loopback (
27852877 server_factory = makeServer , client_factory = makeClient
27862878 )
27872879
2880+ # The session on the original connections are not reused.
2881+ assert originalServer .session_reused () == 0
2882+ assert originalClient .session_reused () == 0
2883+
2884+ # The sessions on the new connections are reused.
2885+ assert resumedServer .session_reused () == 1
2886+ assert resumedClient .session_reused () == 1
2887+
27882888 # This is a proxy: in general, we have no access to any unique
27892889 # identifier for the session (new enough versions of OpenSSL expose
27902890 # a hash which could be usable, but "new enough" is very, very new).
27912891 # Instead, exploit the fact that the master key is re-used if the
27922892 # session is re-used. As long as the master key for the two
27932893 # connections is the same, the session was re-used!
27942894 assert originalServer .master_key () == resumedServer .master_key ()
2895+ assert originalClient .master_key () == resumedClient .master_key ()
27952896
27962897 def test_set_session_wrong_method (self ):
27972898 """
0 commit comments