@@ -236,6 +236,9 @@ def socket_pair():
236
236
237
237
238
238
def handshake (client , server ):
239
+ """
240
+ Wait until the TLS handshake is done on both client and server side.
241
+ """
239
242
conns = [client , server ]
240
243
while conns :
241
244
for conn in conns :
@@ -2755,43 +2758,141 @@ def test_set_session_wrong_args(self):
2755
2758
with pytest .raises (TypeError ):
2756
2759
connection .set_session (object ())
2757
2760
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 ):
2759
2771
"""
2760
2772
`Connection.set_session`, when used prior to a connection being
2761
2773
established, accepts a `Session` instance and causes an attempt to
2762
2774
re-use the session it represents when the SSL handshake is performed.
2775
+
2776
+ `Connection.session_reused` is used to query the reuse status.
2763
2777
"""
2764
2778
key = load_privatekey (FILETYPE_PEM , server_key_pem )
2765
2779
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
2770
2795
2771
2796
def makeServer (socket ):
2772
- server = Connection (ctx , socket )
2797
+ server = Connection (server_ctx , socket )
2773
2798
server .set_accept_state ()
2774
2799
return server
2775
2800
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 )
2777
2810
originalSession = originalClient .get_session ()
2778
2811
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
+
2779
2862
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 )
2782
2867
return client
2783
2868
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
+
2784
2876
resumedServer , resumedClient = loopback (
2785
2877
server_factory = makeServer , client_factory = makeClient
2786
2878
)
2787
2879
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
+
2788
2888
# This is a proxy: in general, we have no access to any unique
2789
2889
# identifier for the session (new enough versions of OpenSSL expose
2790
2890
# a hash which could be usable, but "new enough" is very, very new).
2791
2891
# Instead, exploit the fact that the master key is re-used if the
2792
2892
# session is re-used. As long as the master key for the two
2793
2893
# connections is the same, the session was re-used!
2794
2894
assert originalServer .master_key () == resumedServer .master_key ()
2895
+ assert originalClient .master_key () == resumedClient .master_key ()
2795
2896
2796
2897
def test_set_session_wrong_method (self ):
2797
2898
"""
0 commit comments