/* * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8270344 * @library /test/lib /javax/net/ssl/templates * @summary Session resumption errors * @run main/othervm InvalidateSession */ import javax.net.*; import javax.net.ssl.*; import java.io.*; import java.net.*; import java.util.*; import jdk.test.lib.security.SecurityUtils; public class InvalidateSession extends SSLContextTemplate { static ServerSocketFactory serverSsf = null; static SSLSocketFactory clientSsf = null; static Server server; static SSLSession cacheSession; static final String[] CLIENT_VERSIONS = {"TLSv1", "TLSv1.1", "TLSv1.2"}; public static void main(String args[]) throws Exception { // drop the supported_versions extension to force test to use the legacy // TLS protocol version field during handshakes System.setProperty("jdk.tls.client.disableExtensions", "supported_versions"); SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1"); InvalidateSession test = new InvalidateSession(); test.sessionTest(); server.go = false; } /** * 3 test iterations * 1) Server configured with TLSv1, client with TLSv1, v1.1, v1.2 * - Handshake should succeed * - Session "A" established * 2) 2nd iteration, server configured with TLSv1.2 only * - Connection should succeed but with a new session due to TLS protocol version change * - Session "A" should be invalidated * - Session "B" is created * 3) 3rd iteration, same server/client config * - Session "B" should continue to be in use */ private void sessionTest() throws Exception { serverSsf = createServerSSLContext().getServerSocketFactory(); clientSsf = createClientSSLContext().getSocketFactory(); server = startServer(); while (!server.started) { Thread.yield(); } for (int i = 1; i <= 3; i++) { clientConnect(i); Thread.sleep(1000); } } public void clientConnect(int testIterationCount) throws Exception { System.out.printf("Connecting to: localhost: %s, iteration count %d%n", "localhost:" + server.port, testIterationCount); SSLSocket sslSocket = (SSLSocket) clientSsf.createSocket("localhost", server.port); sslSocket.setEnabledProtocols(CLIENT_VERSIONS); sslSocket.startHandshake(); System.out.println("Got session: " + sslSocket.getSession()); if (testIterationCount == 2 && Objects.equals(cacheSession, sslSocket.getSession())) { throw new RuntimeException("Same session should not have resumed"); } if (testIterationCount == 3 && !Objects.equals(cacheSession, sslSocket.getSession())) { throw new RuntimeException("Same session should have resumed"); } cacheSession = sslSocket.getSession(); try ( ObjectOutputStream oos = new ObjectOutputStream(sslSocket.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(sslSocket.getInputStream())) { oos.writeObject("Hello"); String serverMsg = (String) ois.readObject(); System.out.println("Server message : " + serverMsg); } catch (Exception ex) { throw new RuntimeException(ex); } finally { sslSocket.close(); } } private static Server startServer() { Server server = new Server(); new Thread(server).start(); return server; } private static class Server implements Runnable { public volatile boolean go = true; public volatile int port = 0; public volatile boolean started = false; @Override public void run() { try { SSLServerSocket ssock = (SSLServerSocket) serverSsf.createServerSocket(0); this.port = ssock.getLocalPort(); ssock.setEnabledProtocols(new String[]{"TLSv1"}); started = true; while (go) { try { System.out.println("Waiting for connection"); Socket sock = ssock.accept(); // now flip server to TLSv1.2 mode for successive connections ssock.setEnabledProtocols(new String[]{"TLSv1.2"}); try ( ObjectInputStream ois = new ObjectInputStream(sock.getInputStream()); ObjectOutputStream oos = new ObjectOutputStream(sock.getOutputStream())) { String recv = (String) ois.readObject(); oos.writeObject("Received: " + recv); } catch (SSLHandshakeException she) { System.out.println("Server caught :" + she); } finally { sock.close(); } } catch (Exception ex) { throw new RuntimeException(ex); } } } catch (Exception ex) { throw new RuntimeException(ex); } } } }