11/*
2- * Copyright (c) 2018, 2023 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2018, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323
2424/*
2525 * @test
26- * @bug 8206929 8212885
26+ * @bug 8206929 8212885 8333857
2727 * @summary ensure that client only resumes a session if certain properties
2828 * of the session are compatible with the new connection
2929 * @library /javax/net/ssl/templates
4747import java .security .*;
4848import java .net .*;
4949import java .util .*;
50+ import java .util .concurrent .CountDownLatch ;
51+ import java .util .concurrent .ExecutorService ;
52+ import java .util .concurrent .Executors ;
5053
5154public class ResumeChecksClient extends SSLContextTemplate {
5255 enum TestMode {
@@ -56,49 +59,60 @@ enum TestMode {
5659 CIPHER_SUITE ,
5760 SIGNATURE_SCHEME
5861 }
62+ static TestMode testMode ;
5963
6064 public static void main (String [] args ) throws Exception {
61- new ResumeChecksClient (TestMode .valueOf (args [0 ])).run ();
65+ testMode = TestMode .valueOf (args [0 ]);
66+ new ResumeChecksClient ().test ();
6267 }
6368
64- private final TestMode testMode ;
65- public ResumeChecksClient (TestMode mode ) {
66- this .testMode = mode ;
67- }
68-
69- private void run () throws Exception {
70- Server server = startServer ();
71- server .signal ();
69+ private void test () throws Exception {
70+ Server server = new Server ();
7271 SSLContext sslContext = createClientSSLContext ();
73- while (!server .started ) {
74- Thread .yield ();
75- }
76- SSLSession firstSession = connect (sslContext , server .port , testMode , false );
72+ HexFormat hex = HexFormat .of ();
73+ long firstStartTime = System .currentTimeMillis ();
74+ SSLSession firstSession = connect (sslContext , server .port , true );
75+ System .err .println ("firstStartTime = " + firstStartTime );
76+ System .err .println ("firstId = " + hex .formatHex (firstSession .getId ()));
77+ System .err .println ("firstSession.getCreationTime() = " +
78+ firstSession .getCreationTime ());
7779
78- server .signal ();
7980 long secondStartTime = System .currentTimeMillis ();
80- Thread .sleep (10 );
81- SSLSession secondSession = connect (sslContext , server .port , testMode , true );
82-
83- server .go = false ;
84- server .signal ();
81+ SSLSession secondSession = connect (sslContext , server .port , false );
82+ System .err .println ("secondStartTime = " + secondStartTime );
83+ // Note: Ids will never match with TLS 1.3 due to spec
84+ System .err .println ("secondId = " + hex .formatHex (secondSession .getId ()));
85+ System .err .println ("secondSession.getCreationTime() = " +
86+ secondSession .getCreationTime ());
8587
8688 switch (testMode ) {
8789 case BASIC :
8890 // fail if session is not resumed
89- checkResumedSession (firstSession , secondSession );
91+ try {
92+ checkResumedSession (firstSession , secondSession );
93+ } catch (Exception e ) {
94+ throw new AssertionError ("secondSession did not resume: FAIL" ,
95+ e );
96+ }
97+ System .out .println ("secondSession used resumption: PASS" );
9098 break ;
9199 case VERSION_2_TO_3 :
92100 case VERSION_3_TO_2 :
93101 case CIPHER_SUITE :
94102 case SIGNATURE_SCHEME :
95103 // fail if a new session is not created
96- if (secondSession .getCreationTime () <= secondStartTime ) {
97- throw new RuntimeException ("Existing session was used" );
104+ try {
105+ checkResumedSession (firstSession , secondSession );
106+ System .err .println ("firstSession = " + firstSession );
107+ System .err .println ("secondSession = " + secondSession );
108+ throw new AssertionError ("Second connection should not " +
109+ "have resumed first session: FAIL" );
110+ } catch (Exception e ) {
111+ System .out .println ("secondSession didn't use resumption: PASS" );
98112 }
99113 break ;
100114 default :
101- throw new RuntimeException ("unknown mode: " + testMode );
115+ throw new AssertionError ("unknown mode: " + testMode );
102116 }
103117 }
104118
@@ -134,51 +148,29 @@ public boolean permits(Set<CryptoPrimitive> primitives,
134148 }
135149
136150 private static SSLSession connect (SSLContext sslContext , int port ,
137- TestMode mode , boolean second ) {
151+ boolean first ) {
138152
139153 try {
140154 SSLSocket sock = (SSLSocket )
141155 sslContext .getSocketFactory ().createSocket ();
142156 SSLParameters params = sock .getSSLParameters ();
143157
144- switch (mode ) {
145- case BASIC :
146- // do nothing to ensure resumption works
147- break ;
148- case VERSION_2_TO_3 :
149- if (second ) {
150- params .setProtocols (new String [] {"TLSv1.3" });
151- } else {
152- params .setProtocols (new String [] {"TLSv1.2" });
153- }
154- break ;
155- case VERSION_3_TO_2 :
156- if (second ) {
157- params .setProtocols (new String [] {"TLSv1.2" });
158- } else {
159- params .setProtocols (new String [] {"TLSv1.3" });
160- }
161- break ;
162- case CIPHER_SUITE :
163- if (second ) {
164- params .setCipherSuites (
165- new String [] {"TLS_AES_256_GCM_SHA384" });
166- } else {
167- params .setCipherSuites (
168- new String [] {"TLS_AES_128_GCM_SHA256" });
169- }
170- break ;
171- case SIGNATURE_SCHEME :
172- AlgorithmConstraints constraints =
173- params .getAlgorithmConstraints ();
174- if (second ) {
175- params .setAlgorithmConstraints (new NoSig ("ecdsa" ));
176- } else {
177- params .setAlgorithmConstraints (new NoSig ("rsa" ));
178- }
179- break ;
180- default :
181- throw new RuntimeException ("unknown mode: " + mode );
158+ switch (testMode ) {
159+ case BASIC -> {} // do nothing
160+ case VERSION_2_TO_3 -> params .setProtocols (new String []{
161+ first ? "TLSv1.2" : "TLSv1.3" });
162+ case VERSION_3_TO_2 -> params .setProtocols (new String []{
163+ first ? "TLSv1.3" : "TLSv1.2" });
164+ case CIPHER_SUITE -> params .setCipherSuites (
165+ new String []{
166+ first ? "TLS_AES_128_GCM_SHA256" :
167+ "TLS_AES_256_GCM_SHA384" });
168+ case SIGNATURE_SCHEME ->
169+ params .setAlgorithmConstraints (new NoSig (
170+ first ? "rsa" : "ecdsa" ));
171+ default ->
172+ throw new AssertionError ("unknown mode: " +
173+ testMode );
182174 }
183175 sock .setSSLParameters (params );
184176 sock .connect (new InetSocketAddress ("localhost" , port ));
@@ -195,7 +187,7 @@ private static SSLSession connect(SSLContext sslContext, int port,
195187 return result ;
196188 } catch (Exception ex ) {
197189 // unexpected exception
198- throw new RuntimeException (ex );
190+ throw new AssertionError (ex );
199191 }
200192 }
201193
@@ -274,65 +266,63 @@ private static void checkResumedSession(SSLSession initSession,
274266 }
275267 }
276268
277- private static Server startServer () {
278- Server server = new Server ();
279- new Thread (server ).start ();
280- return server ;
281- }
282-
283- private static class Server extends SSLContextTemplate implements Runnable {
284-
285- public volatile boolean go = true ;
286- private boolean signal = false ;
287- public volatile int port = 0 ;
288- public volatile boolean started = false ;
269+ private static class Server extends SSLContextTemplate {
270+ public int port ;
271+ private final SSLServerSocket ssock ;
272+ ExecutorService threadPool = Executors .newFixedThreadPool (1 );
273+ CountDownLatch serverLatch = new CountDownLatch (1 );
289274
290- private synchronized void waitForSignal () {
291- while (!signal ) {
292- try {
293- wait ();
294- } catch (InterruptedException ex ) {
295- // do nothing
296- }
297- }
298- signal = false ;
299- }
300- public synchronized void signal () {
301- signal = true ;
302- notify ();
303- }
304-
305- @ Override
306- public void run () {
275+ Server () {
307276 try {
308-
309277 SSLContext sc = createServerSSLContext ();
310278 ServerSocketFactory fac = sc .getServerSocketFactory ();
311- SSLServerSocket ssock = (SSLServerSocket )
312- fac .createServerSocket (0 );
313- this .port = ssock .getLocalPort ();
279+ ssock = (SSLServerSocket ) fac .createServerSocket (0 );
280+ port = ssock .getLocalPort ();
314281
315- waitForSignal ();
316- started = true ;
317- while (go ) {
282+ // Thread to allow multiple clients to connect
283+ new Thread (() -> {
318284 try {
319- System .out .println ("Waiting for connection" );
320- Socket sock = ssock .accept ();
321- BufferedReader reader = new BufferedReader (
322- new InputStreamReader (sock .getInputStream ()));
323- String line = reader .readLine ();
324- System .out .println ("server read: " + line );
325- PrintWriter out = new PrintWriter (
326- new OutputStreamWriter (sock .getOutputStream ()));
327- out .println (line );
328- out .flush ();
329- waitForSignal ();
285+ System .err .println ("Server starting to accept" );
286+ serverLatch .countDown ();
287+ do {
288+ threadPool .submit (
289+ new ServerThread ((SSLSocket ) ssock .accept ()));
290+ } while (true );
330291 } catch (Exception ex ) {
331- ex .printStackTrace ();
292+ throw new AssertionError ("Server Down" , ex );
293+ } finally {
294+ threadPool .close ();
332295 }
296+ }).start ();
297+
298+ } catch (Exception e ) {
299+ throw new AssertionError (e );
300+ }
301+ }
302+
303+ static class ServerThread extends Thread {
304+ SSLSocket sock ;
305+
306+ ServerThread (SSLSocket s ) {
307+ this .sock = s ;
308+ System .err .println ("(Server) client connection on port " +
309+ sock .getPort ());
310+ }
311+
312+ public void run () {
313+ try {
314+ BufferedReader reader = new BufferedReader (
315+ new InputStreamReader (sock .getInputStream ()));
316+ String line = reader .readLine ();
317+ System .out .println ("server read: " + line );
318+ PrintWriter out = new PrintWriter (
319+ new OutputStreamWriter (sock .getOutputStream ()));
320+ out .println (line );
321+ out .flush ();
322+ out .close ();
323+ } catch (Exception e ) {
324+ throw new AssertionError ("Server thread error" , e );
333325 }
334- } catch (Exception ex ) {
335- throw new RuntimeException (ex );
336326 }
337327 }
338328 }
0 commit comments