JSSE: add SSLSocket.getSession() tests throughout different times of connection establishment

pull/233/head
Chris Conlon 2024-11-25 15:02:59 -07:00
parent ed3db7a92c
commit f164e6465d
5 changed files with 215 additions and 17 deletions

View File

@ -326,7 +326,7 @@ public class WolfSSLAuthStore {
/* Return new session if in server mode, or if host is null */
if (!clientMode || host == null) {
return this.getSession(ssl, clientMode);
return this.getSession(ssl, clientMode, host, port);
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
@ -527,18 +527,22 @@ public class WolfSSLAuthStore {
}
/** Returns a new session, does not check/save for resumption
*
* @param ssl WOLFSSL class to reference with new session
* @param clientMode true if on client side, false if server
* @param host hostname of peer, or null if not available
* @param port port of peer
*
* @return a new SSLSession on success
*/
protected synchronized WolfSSLImplementSSLSession getSession(
WolfSSLSession ssl, boolean clientMode) {
WolfSSLSession ssl, boolean clientMode, String host, int port) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"creating new session");
WolfSSLImplementSSLSession ses =
new WolfSSLImplementSSLSession(ssl, this);
new WolfSSLImplementSSLSession(ssl, this, host, port);
ses.setValid(true);
ses.isFromTable = false;

View File

@ -1262,6 +1262,7 @@ public class WolfSSLEngineHelper {
int ret, err;
byte[] serverId = null;
String hostAddress = null;
String sessCacheHostname = this.hostname;
if (!modeSet) {
throw new SSLException("setUseClientMode has not been called");
@ -1293,7 +1294,13 @@ public class WolfSSLEngineHelper {
return WolfSSL.SSL_HANDSHAKE_FAILURE;
}
this.session = this.authStore.getSession(ssl, this.clientMode);
if (sessCacheHostname == null && this.peerAddr != null) {
sessCacheHostname = this.peerAddr.getHostAddress();
}
this.session = this.authStore.getSession(ssl, this.clientMode,
sessCacheHostname, this.port);
}
if (this.clientMode) {

View File

@ -147,12 +147,14 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
*
* @param in WolfSSLSession to be used with this object
* @param params WolfSSLAuthStore for this session
* @param host hostname of peer, or null if not available
* @param port port of peer
*/
public WolfSSLImplementSSLSession (WolfSSLSession in,
WolfSSLAuthStore params) {
WolfSSLAuthStore params,
String host, int port) {
this.ssl = in;
this.port = -1;
this.host = null;
this.host = host;
this.authStore = params;
this.valid = false; /* flag if joining or resuming session is allowed */
this.peerCerts = null;
@ -163,6 +165,12 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
creation = new Date();
accessed = new Date();
if (port > 0) {
this.port = port;
} else {
this.port = -1;
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"created new session (no host/port yet)");
}
@ -478,7 +486,9 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
X509Certificate exportCert;
if (ssl == null) {
throw new SSLPeerUnverifiedException("handshake not complete");
throw new SSLPeerUnverifiedException(
"internal WolfSSLSession null, handshake not complete or " +
"SSLSocket/Engine closed");
}
try {

View File

@ -24,6 +24,13 @@ package com.wolfssl.provider.jsse.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
@ -38,20 +45,25 @@ import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.net.InetSocketAddress;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionBindingEvent;
import javax.net.ssl.SSLSessionBindingListener;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLHandshakeException;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLContext;
import com.wolfssl.WolfSSLException;
import com.wolfssl.provider.jsse.WolfSSLProvider;
@ -63,7 +75,7 @@ public class WolfSSLSessionTest {
@BeforeClass
public static void testProviderInstallationAtRuntime()
throws NoSuchProviderException {
throws NoSuchProviderException, WolfSSLException {
System.out.println("WolfSSLImplementSSLSession Class");
@ -73,12 +85,8 @@ public class WolfSSLSessionTest {
Provider p = Security.getProvider("wolfJSSE");
assertNotNull(p);
try {
tf = new WolfSSLTestFactory();
} catch (WolfSSLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* Can throw WolfSSLException on error */
tf = new WolfSSLTestFactory();
}
@ -435,6 +443,162 @@ public class WolfSSLSessionTest {
pass("\t\t... passed");
}
@Test
public void testGetSessionInSocketConnection() throws Exception {
String protocol = null;
SSLContext ctx = null;
System.out.print("\tTesting SSLSocket.getSession");
if (WolfSSL.TLSv12Enabled()) {
protocol = "TLSv1.2";
} else if (WolfSSL.TLSv11Enabled()) {
protocol = "TLSv1.1";
} else if (WolfSSL.TLSv1Enabled()) {
protocol = "TLSv1.0";
} else {
System.out.println("\t... skipped");
return;
}
/* create new CTX */
ctx = tf.createSSLContext(protocol, engineProvider);
/* create SSLServerSocket first to get ephemeral port */
SSLServerSocket ss = (SSLServerSocket)ctx.getServerSocketFactory()
.createServerSocket(0);
SSLSocket cs = (SSLSocket)ctx.getSocketFactory().createSocket();
cs.connect(new InetSocketAddress(ss.getLocalPort()));
final SSLSocket server = (SSLSocket)ss.accept();
server.setNeedClientAuth(true);
ExecutorService es = Executors.newSingleThreadExecutor();
Future<Void> serverFuture = es.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
testSSLSession(server, false);
server.startHandshake();
testSSLSession(server, true);
} catch (SSLException e) {
error("\t... failed");
fail();
}
return null;
}
});
try {
testSSLSession(cs, false);
cs.startHandshake();
testSSLSession(cs, true);
} catch (SSLHandshakeException e) {
error("\t... failed");
fail();
}
es.shutdown();
serverFuture.get();
testSSLSession(cs, true);
cs.close();
testSSLSession(cs, true);
testSSLSession(server, true);
server.close();
testSSLSession(server, true);
ss.close();
pass("\t... passed");
}
/**
* Test SSLSocket.getSession() and calling methods on the
* SSLSession retrieved. */
private void testSSLSession(SSLSocket sock, boolean handshakeDone)
throws Exception {
int ret;
String val;
Certificate[] certs;
byte[] id;
SSLSession session;
if (sock == null) {
throw new Exception("SSLSocket was null in testSSLSession");
}
session = sock.getSession();
if (session == null) {
throw new Exception("SSLSocket.getSession() returned null");
}
val = session.getCipherSuite();
if (val == null || val.isEmpty()) {
throw new Exception(
"SSLSession.getCipherSuite() was null or empty");
}
val = session.getProtocol();
if (val == null || val.isEmpty()) {
throw new Exception(
"SSLSession.getProtocol() was null or empty");
}
val = session.getPeerHost();
if (handshakeDone && !sock.isClosed() &&
(val == null || val.isEmpty())) {
throw new Exception(
"SSLSession.getPeerHost() was null or empty");
}
ret = session.getPeerPort();
if (ret == 0) {
throw new Exception("SSLSession.getPeerPort() was 0");
}
certs = session.getLocalCertificates();
if (certs == null || certs.length == 0) {
throw new Exception(
"SSLSession.getLocalCertificates() was null or 0 length");
}
try {
certs = session.getPeerCertificates();
if (handshakeDone && (certs == null || certs.length == 0)) {
throw new Exception(
"SSLSession.getPeerCertificates was null or 0 length");
}
} catch (SSLPeerUnverifiedException e) {
if (handshakeDone && !sock.isClosed()) {
throw new Exception(
"SSLSession.getPeerCertificates threw " +
"SSLPeerUnverifiedException when handshake was done: " + e);
}
}
id = session.getId();
if (!sock.isClosed() && (id == null || id.length == 0)) {
throw new Exception("SSLSession.getId() was null or 0 length");
}
if (!sock.isClosed() && !session.isValid()) {
throw new Exception("SSLSession.isValid() is false");
}
ret = session.getPacketBufferSize();
if (ret == 0) {
throw new Exception("SSLSession.getPacketBufferSize() is 0");
}
ret = session.getApplicationBufferSize();
if (ret == 0) {
throw new Exception("SSLSession.getApplicationBufferSize() is 0");
}
}
private void pass(String msg) {
WolfSSLTestFactory.pass(msg);

View File

@ -41,6 +41,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLDebug;
@ -991,6 +993,11 @@ public class WolfSSLSessionTest {
final WolfSSLContext srvCtx;
WolfSSLContext cliCtx;
/* Latch used to wait for server to finish handshake before
* test shuts down. Otherwise, we will sometimes miss debug
* messages from the server side. */
final CountDownLatch latch = new CountDownLatch(1);
System.out.print("\tTesting wolfssljni.debug");
/* Save original property value, then enable debug. Make sure
@ -1063,6 +1070,8 @@ public class WolfSSLSessionTest {
if (server != null) {
server.close();
}
latch.countDown();
}
return null;
@ -1129,6 +1138,10 @@ public class WolfSSLSessionTest {
}
} finally {
/* Wait for server to finish processing */
latch.await(10, TimeUnit.SECONDS);
/* Restore original property value */
if (originalProp == null || originalProp.isEmpty()) {
System.setProperty("wolfssljni.debug", "");