mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-12 03:18:37 +00:00
8333857: Test sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java failed: Existing session was used
Reviewed-by: hchao
This commit is contained in:
parent
38cd860daa
commit
e6ebefaa40
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8206929 8212885
|
||||
* @bug 8206929 8212885 8333857
|
||||
* @summary ensure that client only resumes a session if certain properties
|
||||
* of the session are compatible with the new connection
|
||||
* @library /javax/net/ssl/templates
|
||||
@ -47,6 +47,9 @@ import java.io.*;
|
||||
import java.security.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class ResumeChecksClient extends SSLContextTemplate {
|
||||
enum TestMode {
|
||||
@ -56,49 +59,60 @@ public class ResumeChecksClient extends SSLContextTemplate {
|
||||
CIPHER_SUITE,
|
||||
SIGNATURE_SCHEME
|
||||
}
|
||||
static TestMode testMode;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new ResumeChecksClient(TestMode.valueOf(args[0])).run();
|
||||
testMode = TestMode.valueOf(args[0]);
|
||||
new ResumeChecksClient().test();
|
||||
}
|
||||
|
||||
private final TestMode testMode;
|
||||
public ResumeChecksClient(TestMode mode) {
|
||||
this.testMode = mode;
|
||||
}
|
||||
|
||||
private void run() throws Exception {
|
||||
Server server = startServer();
|
||||
server.signal();
|
||||
private void test() throws Exception {
|
||||
Server server = new Server();
|
||||
SSLContext sslContext = createClientSSLContext();
|
||||
while (!server.started) {
|
||||
Thread.yield();
|
||||
}
|
||||
SSLSession firstSession = connect(sslContext, server.port, testMode, false);
|
||||
HexFormat hex = HexFormat.of();
|
||||
long firstStartTime = System.currentTimeMillis();
|
||||
SSLSession firstSession = connect(sslContext, server.port, true);
|
||||
System.err.println("firstStartTime = " + firstStartTime);
|
||||
System.err.println("firstId = " + hex.formatHex(firstSession.getId()));
|
||||
System.err.println("firstSession.getCreationTime() = " +
|
||||
firstSession.getCreationTime());
|
||||
|
||||
server.signal();
|
||||
long secondStartTime = System.currentTimeMillis();
|
||||
Thread.sleep(10);
|
||||
SSLSession secondSession = connect(sslContext, server.port, testMode, true);
|
||||
|
||||
server.go = false;
|
||||
server.signal();
|
||||
SSLSession secondSession = connect(sslContext, server.port, false);
|
||||
System.err.println("secondStartTime = " + secondStartTime);
|
||||
// Note: Ids will never match with TLS 1.3 due to spec
|
||||
System.err.println("secondId = " + hex.formatHex(secondSession.getId()));
|
||||
System.err.println("secondSession.getCreationTime() = " +
|
||||
secondSession.getCreationTime());
|
||||
|
||||
switch (testMode) {
|
||||
case BASIC:
|
||||
// fail if session is not resumed
|
||||
checkResumedSession(firstSession, secondSession);
|
||||
try {
|
||||
checkResumedSession(firstSession, secondSession);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("secondSession did not resume: FAIL",
|
||||
e);
|
||||
}
|
||||
System.out.println("secondSession used resumption: PASS");
|
||||
break;
|
||||
case VERSION_2_TO_3:
|
||||
case VERSION_3_TO_2:
|
||||
case CIPHER_SUITE:
|
||||
case SIGNATURE_SCHEME:
|
||||
// fail if a new session is not created
|
||||
if (secondSession.getCreationTime() <= secondStartTime) {
|
||||
throw new RuntimeException("Existing session was used");
|
||||
try {
|
||||
checkResumedSession(firstSession, secondSession);
|
||||
System.err.println("firstSession = " + firstSession);
|
||||
System.err.println("secondSession = " + secondSession);
|
||||
throw new AssertionError("Second connection should not " +
|
||||
"have resumed first session: FAIL");
|
||||
} catch (Exception e) {
|
||||
System.out.println("secondSession didn't use resumption: PASS");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode: " + testMode);
|
||||
throw new AssertionError("unknown mode: " + testMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,51 +148,29 @@ public class ResumeChecksClient extends SSLContextTemplate {
|
||||
}
|
||||
|
||||
private static SSLSession connect(SSLContext sslContext, int port,
|
||||
TestMode mode, boolean second) {
|
||||
boolean first) {
|
||||
|
||||
try {
|
||||
SSLSocket sock = (SSLSocket)
|
||||
sslContext.getSocketFactory().createSocket();
|
||||
SSLParameters params = sock.getSSLParameters();
|
||||
|
||||
switch (mode) {
|
||||
case BASIC:
|
||||
// do nothing to ensure resumption works
|
||||
break;
|
||||
case VERSION_2_TO_3:
|
||||
if (second) {
|
||||
params.setProtocols(new String[] {"TLSv1.3"});
|
||||
} else {
|
||||
params.setProtocols(new String[] {"TLSv1.2"});
|
||||
}
|
||||
break;
|
||||
case VERSION_3_TO_2:
|
||||
if (second) {
|
||||
params.setProtocols(new String[] {"TLSv1.2"});
|
||||
} else {
|
||||
params.setProtocols(new String[] {"TLSv1.3"});
|
||||
}
|
||||
break;
|
||||
case CIPHER_SUITE:
|
||||
if (second) {
|
||||
params.setCipherSuites(
|
||||
new String[] {"TLS_AES_256_GCM_SHA384"});
|
||||
} else {
|
||||
params.setCipherSuites(
|
||||
new String[] {"TLS_AES_128_GCM_SHA256"});
|
||||
}
|
||||
break;
|
||||
case SIGNATURE_SCHEME:
|
||||
AlgorithmConstraints constraints =
|
||||
params.getAlgorithmConstraints();
|
||||
if (second) {
|
||||
params.setAlgorithmConstraints(new NoSig("ecdsa"));
|
||||
} else {
|
||||
params.setAlgorithmConstraints(new NoSig("rsa"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode: " + mode);
|
||||
switch (testMode) {
|
||||
case BASIC -> {} // do nothing
|
||||
case VERSION_2_TO_3 -> params.setProtocols(new String[]{
|
||||
first ? "TLSv1.2" : "TLSv1.3"});
|
||||
case VERSION_3_TO_2 -> params.setProtocols(new String[]{
|
||||
first ? "TLSv1.3" : "TLSv1.2"});
|
||||
case CIPHER_SUITE -> params.setCipherSuites(
|
||||
new String[]{
|
||||
first ? "TLS_AES_128_GCM_SHA256" :
|
||||
"TLS_AES_256_GCM_SHA384"});
|
||||
case SIGNATURE_SCHEME ->
|
||||
params.setAlgorithmConstraints(new NoSig(
|
||||
first ? "rsa" : "ecdsa"));
|
||||
default ->
|
||||
throw new AssertionError("unknown mode: " +
|
||||
testMode);
|
||||
}
|
||||
sock.setSSLParameters(params);
|
||||
sock.connect(new InetSocketAddress("localhost", port));
|
||||
@ -195,7 +187,7 @@ public class ResumeChecksClient extends SSLContextTemplate {
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
// unexpected exception
|
||||
throw new RuntimeException(ex);
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,65 +266,63 @@ public class ResumeChecksClient extends SSLContextTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
private static Server startServer() {
|
||||
Server server = new Server();
|
||||
new Thread(server).start();
|
||||
return server;
|
||||
}
|
||||
private static class Server extends SSLContextTemplate {
|
||||
public int port;
|
||||
private final SSLServerSocket ssock;
|
||||
ExecutorService threadPool = Executors.newFixedThreadPool(1);
|
||||
CountDownLatch serverLatch = new CountDownLatch(1);
|
||||
|
||||
private static class Server extends SSLContextTemplate implements Runnable {
|
||||
|
||||
public volatile boolean go = true;
|
||||
private boolean signal = false;
|
||||
public volatile int port = 0;
|
||||
public volatile boolean started = false;
|
||||
|
||||
private synchronized void waitForSignal() {
|
||||
while (!signal) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ex) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
signal = false;
|
||||
}
|
||||
public synchronized void signal() {
|
||||
signal = true;
|
||||
notify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Server() {
|
||||
try {
|
||||
|
||||
SSLContext sc = createServerSSLContext();
|
||||
ServerSocketFactory fac = sc.getServerSocketFactory();
|
||||
SSLServerSocket ssock = (SSLServerSocket)
|
||||
fac.createServerSocket(0);
|
||||
this.port = ssock.getLocalPort();
|
||||
ssock = (SSLServerSocket) fac.createServerSocket(0);
|
||||
port = ssock.getLocalPort();
|
||||
|
||||
waitForSignal();
|
||||
started = true;
|
||||
while (go) {
|
||||
// Thread to allow multiple clients to connect
|
||||
new Thread(() -> {
|
||||
try {
|
||||
System.out.println("Waiting for connection");
|
||||
Socket sock = ssock.accept();
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
System.out.println("server read: " + line);
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println(line);
|
||||
out.flush();
|
||||
waitForSignal();
|
||||
System.err.println("Server starting to accept");
|
||||
serverLatch.countDown();
|
||||
do {
|
||||
threadPool.submit(
|
||||
new ServerThread((SSLSocket) ssock.accept()));
|
||||
} while (true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new AssertionError("Server Down", ex);
|
||||
} finally {
|
||||
threadPool.close();
|
||||
}
|
||||
}).start();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class ServerThread extends Thread {
|
||||
SSLSocket sock;
|
||||
|
||||
ServerThread(SSLSocket s) {
|
||||
this.sock = s;
|
||||
System.err.println("(Server) client connection on port " +
|
||||
sock.getPort());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
System.out.println("server read: " + line);
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println(line);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Server thread error", e);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8206929
|
||||
* @bug 8206929 8333857
|
||||
* @summary ensure that server only resumes a session if certain properties
|
||||
* of the session are compatible with the new connection
|
||||
* @modules java.base/sun.security.x509
|
||||
@ -49,6 +49,10 @@ import java.io.*;
|
||||
import java.security.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
public class ResumeChecksServer extends SSLContextTemplate {
|
||||
@ -63,60 +67,56 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
||||
LOCAL_CERTS
|
||||
}
|
||||
|
||||
static CountDownLatch latch = new CountDownLatch(1);
|
||||
static TestMode testMode;
|
||||
static int serverPort;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
new ResumeChecksServer(TestMode.valueOf(args[0])).run();
|
||||
}
|
||||
private final TestMode testMode;
|
||||
|
||||
public ResumeChecksServer(TestMode testMode) {
|
||||
this.testMode = testMode;
|
||||
testMode = TestMode.valueOf(args[0]);
|
||||
new ResumeChecksServer().test();
|
||||
}
|
||||
|
||||
private void run() throws Exception {
|
||||
SSLSession firstSession;
|
||||
SSLSession secondSession = null;
|
||||
private void test() throws Exception {
|
||||
SSLSession firstSession, secondSession;
|
||||
HexFormat hex = HexFormat.of();
|
||||
|
||||
SSLContext sslContext = createServerSSLContext();
|
||||
ServerSocketFactory fac = sslContext.getServerSocketFactory();
|
||||
SSLServerSocket ssock = (SSLServerSocket)
|
||||
fac.createServerSocket(0);
|
||||
serverPort = new Server().port;
|
||||
latch.await();
|
||||
Client c = new Client(serverPort);
|
||||
|
||||
Client client = startClient(ssock.getLocalPort());
|
||||
System.out.println("Waiting for connection");
|
||||
long firstStartTime = System.currentTimeMillis();
|
||||
firstSession = c.test();
|
||||
|
||||
try {
|
||||
firstSession = connect(client, ssock, testMode, null);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
System.err.println("firstStartTime = " + firstStartTime);
|
||||
System.err.println("firstId = " + hex.formatHex(firstSession.getId()));
|
||||
System.err.println("firstSession.getCreationTime() = " +
|
||||
firstSession.getCreationTime());
|
||||
|
||||
long secondStartTime = System.currentTimeMillis();
|
||||
Thread.sleep(10);
|
||||
try {
|
||||
secondSession = connect(client, ssock, testMode, firstSession);
|
||||
} catch (SSLHandshakeException ex) {
|
||||
// this is expected
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
secondSession = c.test();
|
||||
|
||||
client.go = false;
|
||||
client.signal();
|
||||
System.err.println("secondStartTime = " + secondStartTime);
|
||||
// Note: Ids will never match with TLS 1.3 due to spec
|
||||
System.err.println("secondId = " + hex.formatHex(secondSession.getId()));
|
||||
System.err.println("secondSession.getCreationTime() = " +
|
||||
secondSession.getCreationTime());
|
||||
|
||||
switch (testMode) {
|
||||
case BASIC:
|
||||
// fail if session is not resumed
|
||||
if (secondSession.getCreationTime() > secondStartTime) {
|
||||
throw new RuntimeException("Session was not reused");
|
||||
if (firstSession.getCreationTime() !=
|
||||
secondSession.getCreationTime()) {
|
||||
throw new AssertionError("Session was not reused: FAIL");
|
||||
}
|
||||
|
||||
// Fail if session's certificates are not restored correctly.
|
||||
if (!java.util.Arrays.equals(
|
||||
if (!Arrays.equals(
|
||||
firstSession.getLocalCertificates(),
|
||||
secondSession.getLocalCertificates())) {
|
||||
throw new RuntimeException("Certificates do not match");
|
||||
throw new AssertionError("Certificates do not match: FAIL");
|
||||
}
|
||||
|
||||
System.out.println("secondSession used resumption: PASS");
|
||||
break;
|
||||
case CLIENT_AUTH:
|
||||
// throws an exception if the client is not authenticated
|
||||
@ -128,24 +128,23 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
||||
case SIGNATURE_SCHEME:
|
||||
case LOCAL_CERTS:
|
||||
// fail if a new session is not created
|
||||
if (secondSession.getCreationTime() <= secondStartTime) {
|
||||
throw new RuntimeException("Existing session was used");
|
||||
if (secondSession.getCreationTime() < secondStartTime) {
|
||||
throw new AssertionError("Existing session was used: FAIL");
|
||||
}
|
||||
System.out.println("secondSession not resumed: PASS");
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode: " + testMode);
|
||||
throw new AssertionError("unknown mode: " + testMode);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoSig implements AlgorithmConstraints {
|
||||
|
||||
private final String alg;
|
||||
|
||||
NoSig(String alg) {
|
||||
this.alg = alg;
|
||||
}
|
||||
|
||||
|
||||
private boolean test(String a) {
|
||||
return !a.toLowerCase().contains(alg.toLowerCase());
|
||||
}
|
||||
@ -153,176 +152,151 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
||||
public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean permits(Set<CryptoPrimitive> primitives,
|
||||
String algorithm, AlgorithmParameters parameters) {
|
||||
|
||||
return test(algorithm);
|
||||
}
|
||||
|
||||
public boolean permits(Set<CryptoPrimitive> primitives,
|
||||
String algorithm, Key key, AlgorithmParameters parameters) {
|
||||
|
||||
return test(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
private static SSLSession connect(Client client, SSLServerSocket ssock,
|
||||
TestMode mode, SSLSession firstSession) throws Exception {
|
||||
|
||||
boolean second = firstSession != null;
|
||||
|
||||
try {
|
||||
client.signal();
|
||||
System.out.println("Waiting for connection");
|
||||
SSLSocket sock = (SSLSocket) ssock.accept();
|
||||
SSLParameters params = sock.getSSLParameters();
|
||||
|
||||
switch (mode) {
|
||||
case BASIC:
|
||||
// do nothing to ensure resumption works
|
||||
break;
|
||||
case CLIENT_AUTH:
|
||||
if (second) {
|
||||
params.setNeedClientAuth(true);
|
||||
} else {
|
||||
params.setNeedClientAuth(false);
|
||||
}
|
||||
break;
|
||||
case VERSION_2_TO_3:
|
||||
if (second) {
|
||||
params.setProtocols(new String[] {"TLSv1.3"});
|
||||
} else {
|
||||
params.setProtocols(new String[] {"TLSv1.2"});
|
||||
}
|
||||
break;
|
||||
case VERSION_3_TO_2:
|
||||
if (second) {
|
||||
params.setProtocols(new String[] {"TLSv1.2"});
|
||||
} else {
|
||||
params.setProtocols(new String[] {"TLSv1.3"});
|
||||
}
|
||||
break;
|
||||
case CIPHER_SUITE:
|
||||
if (second) {
|
||||
params.setCipherSuites(
|
||||
new String[] {"TLS_AES_128_GCM_SHA256"});
|
||||
} else {
|
||||
params.setCipherSuites(
|
||||
new String[] {"TLS_AES_256_GCM_SHA384"});
|
||||
}
|
||||
break;
|
||||
case SIGNATURE_SCHEME:
|
||||
params.setNeedClientAuth(true);
|
||||
AlgorithmConstraints constraints =
|
||||
params.getAlgorithmConstraints();
|
||||
if (second) {
|
||||
params.setAlgorithmConstraints(
|
||||
new NoSig("ecdsa_secp384r1_sha384"));
|
||||
} else {
|
||||
params.setAlgorithmConstraints(
|
||||
new NoSig("ecdsa_secp521r1_sha512"));
|
||||
}
|
||||
break;
|
||||
case LOCAL_CERTS:
|
||||
if (second) {
|
||||
// Add first session's certificate signature
|
||||
// algorithm to constraints so local certificates
|
||||
// can't be restored from the session ticket.
|
||||
params.setAlgorithmConstraints(
|
||||
new NoSig(X509CertImpl.toImpl((X509CertImpl)
|
||||
firstSession.getLocalCertificates()[0])
|
||||
.getSigAlgName()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode: " + mode);
|
||||
}
|
||||
sock.setSSLParameters(params);
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
System.out.println("server read: " + line);
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println(line);
|
||||
out.flush();
|
||||
out.close();
|
||||
SSLSession result = sock.getSession();
|
||||
sock.close();
|
||||
return result;
|
||||
} catch (SSLHandshakeException ex) {
|
||||
if (!second) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Client startClient(int port) {
|
||||
Client client = new Client(port);
|
||||
new Thread(client).start();
|
||||
return client;
|
||||
}
|
||||
|
||||
private static class Client extends SSLContextTemplate implements Runnable {
|
||||
|
||||
public volatile boolean go = true;
|
||||
private boolean signal = false;
|
||||
private static class Client extends SSLContextTemplate {
|
||||
private final int port;
|
||||
private final SSLContext sc;
|
||||
public SSLSession session;
|
||||
|
||||
Client(int port) {
|
||||
Client(int port) throws Exception {
|
||||
sc = createClientSSLContext();
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
private synchronized void waitForSignal() {
|
||||
while (!signal) {
|
||||
public SSLSession test() throws Exception {
|
||||
SSLSocket sock = null;
|
||||
latch.await();
|
||||
do {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ex) {
|
||||
// do nothing
|
||||
sock = (SSLSocket) sc.getSocketFactory().createSocket();
|
||||
} catch (IOException e) {
|
||||
// If the server never starts, test will time out.
|
||||
System.err.println("client trying again to connect");
|
||||
Thread.sleep(500);
|
||||
}
|
||||
}
|
||||
signal = false;
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ex) {
|
||||
// do nothing
|
||||
}
|
||||
} while (sock == null);
|
||||
sock.connect(new InetSocketAddress("localhost", port));
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println("message");
|
||||
out.flush();
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String inMsg = reader.readLine();
|
||||
System.out.println("Client received: " + inMsg);
|
||||
out.close();
|
||||
session = sock.getSession();
|
||||
sock.close();
|
||||
return session;
|
||||
}
|
||||
public synchronized void signal() {
|
||||
signal = true;
|
||||
notify();
|
||||
}
|
||||
|
||||
// The server will only have two connections each tests
|
||||
private static class Server extends SSLContextTemplate {
|
||||
public int port;
|
||||
ExecutorService threadPool = Executors.newFixedThreadPool(1);
|
||||
// Stores the certs from the first connection in mode LOCAL_CERTS
|
||||
static X509CertImpl localCerts;
|
||||
// first connection to the server
|
||||
static boolean first = true;
|
||||
|
||||
Server() throws Exception {
|
||||
SSLContext sc = createServerSSLContext();
|
||||
ServerSocketFactory fac = sc.getServerSocketFactory();
|
||||
SSLServerSocket ssock = (SSLServerSocket) fac.createServerSocket(0);
|
||||
port = ssock.getLocalPort();
|
||||
|
||||
// Thread to allow multiple clients to connect
|
||||
new Thread(() -> {
|
||||
try {
|
||||
System.err.println("Server starting to accept");
|
||||
latch.countDown();
|
||||
do {
|
||||
threadPool.submit(new ServerThread(ssock.accept()));
|
||||
} while (true);
|
||||
} catch (Exception ex) {
|
||||
throw new AssertionError("Server Down", ex);
|
||||
} finally {
|
||||
threadPool.close();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
static class ServerThread implements Runnable {
|
||||
final SSLSocket sock;
|
||||
|
||||
SSLContext sc = createClientSSLContext();
|
||||
ServerThread(Socket s) {
|
||||
this.sock = (SSLSocket) s;
|
||||
System.err.println("(Server) client connection on port " +
|
||||
sock.getPort());
|
||||
}
|
||||
|
||||
waitForSignal();
|
||||
while (go) {
|
||||
try {
|
||||
SSLSocket sock = (SSLSocket)
|
||||
sc.getSocketFactory().createSocket();
|
||||
sock.connect(new InetSocketAddress("localhost", port));
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println("message");
|
||||
out.flush();
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String inMsg = reader.readLine();
|
||||
System.out.println("Client received: " + inMsg);
|
||||
out.close();
|
||||
sock.close();
|
||||
waitForSignal();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
public void run() {
|
||||
try {
|
||||
SSLParameters params = sock.getSSLParameters();
|
||||
switch (testMode) {
|
||||
case BASIC -> {} // do nothing
|
||||
case CLIENT_AUTH -> params.setNeedClientAuth(!first);
|
||||
case VERSION_2_TO_3 -> params.setProtocols(new String[]{
|
||||
first ? "TLSv1.2" : "TLSv1.3"});
|
||||
case VERSION_3_TO_2 -> params.setProtocols(new String[]{
|
||||
first ? "TLSv1.3" : "TLSv1.2"});
|
||||
case CIPHER_SUITE -> params.setCipherSuites(
|
||||
new String[]{
|
||||
first ? "TLS_AES_256_GCM_SHA384" :
|
||||
"TLS_AES_128_GCM_SHA256"});
|
||||
case SIGNATURE_SCHEME -> {
|
||||
params.setNeedClientAuth(true);
|
||||
params.setAlgorithmConstraints(new NoSig(
|
||||
first ? "ecdsa_secp521r1_sha512" :
|
||||
"ecdsa_secp384r1_sha384"));
|
||||
}
|
||||
case LOCAL_CERTS -> {
|
||||
if (!first) {
|
||||
// Add first session's certificate signature
|
||||
// algorithm to constraints so local certificates
|
||||
// can't be restored from the session ticket.
|
||||
params.setAlgorithmConstraints(
|
||||
new NoSig(X509CertImpl.toImpl(localCerts)
|
||||
.getSigAlgName()));
|
||||
}
|
||||
}
|
||||
default ->
|
||||
throw new AssertionError("Server: " +
|
||||
"unknown mode: " + testMode);
|
||||
}
|
||||
sock.setSSLParameters(params);
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
System.err.println("server read: " + line);
|
||||
PrintWriter out = new PrintWriter(
|
||||
new OutputStreamWriter(sock.getOutputStream()));
|
||||
out.println(line);
|
||||
out.flush();
|
||||
out.close();
|
||||
SSLSession session = sock.getSession();
|
||||
if (testMode == TestMode.LOCAL_CERTS && first) {
|
||||
localCerts = (X509CertImpl) session.
|
||||
getLocalCertificates()[0];
|
||||
}
|
||||
first = false;
|
||||
System.err.println("server socket closed: " + session);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Server error", e);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user