Merge pull request #162 from cconlon/sslSessionGetPeerCertificates
SSLSession fix for getPeerCertificates() and cached certpull/165/head
commit
67aee347cd
|
@ -5567,3 +5567,12 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setDevId
|
||||||
return (jint)wolfSSL_CTX_SetDevId(ctx, (int)devId);
|
return (jint)wolfSSL_CTX_SetDevId(ctx, (int)devId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JNICALL Java_com_wolfssl_WolfSSLContext_flushSessions
|
||||||
|
(JNIEnv* jenv, jobject jcl, jlong ctxPtr, jint tm)
|
||||||
|
{
|
||||||
|
WOLFSSL_CTX* ctx = (WOLFSSL_CTX*)(uintptr_t)ctxPtr;
|
||||||
|
(void)jcl;
|
||||||
|
|
||||||
|
wolfSSL_CTX_flush_sessions(ctx, (int)tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -415,6 +415,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setMinEccKeySz
|
||||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setDevId
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setDevId
|
||||||
(JNIEnv *, jobject, jlong, jint);
|
(JNIEnv *, jobject, jlong, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_wolfssl_WolfSSLContext
|
||||||
|
* Method: flushSessions
|
||||||
|
* Signature: (JI)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_flushSessions
|
||||||
|
(JNIEnv *, jobject, jlong, jint);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -387,6 +387,7 @@ public class WolfSSLContext {
|
||||||
private native int setMinRsaKeySz(long ctx, int keySzBits);
|
private native int setMinRsaKeySz(long ctx, int keySzBits);
|
||||||
private native int setMinEccKeySz(long ctx, int keySzBits);
|
private native int setMinEccKeySz(long ctx, int keySzBits);
|
||||||
private native int setDevId(long ctx, int devId);
|
private native int setDevId(long ctx, int devId);
|
||||||
|
private native void flushSessions(long ctx, int tm);
|
||||||
|
|
||||||
/* ------------------- context-specific methods --------------------- */
|
/* ------------------- context-specific methods --------------------- */
|
||||||
|
|
||||||
|
@ -2000,6 +2001,22 @@ public class WolfSSLContext {
|
||||||
return setDevId(getContextPtr(), devId);
|
return setDevId(getContextPtr(), devId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove / flush expired sessions from the native wolfSSL session cache.
|
||||||
|
*
|
||||||
|
* @param tm the time used to determine the expiration date for sessions,
|
||||||
|
* should be result of equivalent of native time(0), or
|
||||||
|
* desired expiration time in seconds from the unix epoch
|
||||||
|
* (Jan 1, 1970).
|
||||||
|
* @throws IllegalStateException WolfSSLSession has been freed
|
||||||
|
*/
|
||||||
|
public void flushSessions(int tm) throws IllegalStateException {
|
||||||
|
|
||||||
|
confirmObjectIsActive();
|
||||||
|
|
||||||
|
flushSessions(getContextPtr(), tm);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable
|
protected void finalize() throws Throwable
|
||||||
|
|
|
@ -506,6 +506,7 @@ public class WolfSSLAuthStore {
|
||||||
session.getSideString());
|
session.getSideString());
|
||||||
store.put(hashCode, session);
|
store.put(hashCode, session);
|
||||||
session.isInTable = true;
|
session.isInTable = true;
|
||||||
|
printSessionStoreStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -427,6 +427,14 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
/**
|
/**
|
||||||
* Get peer certificates for this session
|
* Get peer certificates for this session
|
||||||
*
|
*
|
||||||
|
* This method first tries to call down to native wolfSSL with
|
||||||
|
* ssl.getPeerCertificate(). If that succeeds, it caches the peer
|
||||||
|
* certificate inside this object (this.peerCerts) so that in a resumed
|
||||||
|
* session when this method is called, the caller will still have access
|
||||||
|
* to the original certificate (matches SunJSSE behavior). If calling
|
||||||
|
* ssl.getPeerCertificate() fails, then we return the cached cert if
|
||||||
|
* we have it.
|
||||||
|
*
|
||||||
* @return Certificate array of peer certs for session
|
* @return Certificate array of peer certs for session
|
||||||
*
|
*
|
||||||
* @throws SSLPeerUnverifiedException if handshake is not complete,
|
* @throws SSLPeerUnverifiedException if handshake is not complete,
|
||||||
|
@ -444,23 +452,31 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
throw new SSLPeerUnverifiedException("handshake not complete");
|
throw new SSLPeerUnverifiedException("handshake not complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If peer cert is already cached, just return that */
|
|
||||||
if (this.peerCerts != null) {
|
|
||||||
return this.peerCerts.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
x509 = this.ssl.getPeerCertificate();
|
x509 = this.ssl.getPeerCertificate();
|
||||||
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
||||||
Logger.getLogger(
|
Logger.getLogger(
|
||||||
WolfSSLImplementSSLSession.class.getName()).log(
|
WolfSSLImplementSSLSession.class.getName()).log(
|
||||||
Level.SEVERE, null, ex);
|
Level.SEVERE, null, ex);
|
||||||
return null;
|
x509 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if no peer cert, throw SSLPeerUnverifiedException */
|
/* if no peer cert, throw SSLPeerUnverifiedException */
|
||||||
if (x509 == 0) {
|
if (x509 == 0) {
|
||||||
throw new SSLPeerUnverifiedException("No peer certificate");
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"ssl.getPeerCertificates() returned null, trying cached cert");
|
||||||
|
|
||||||
|
if (this.peerCerts != null) {
|
||||||
|
/* If peer cert is already cached, just return that */
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"peer cert already cached, returning it");
|
||||||
|
return this.peerCerts.clone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"No peer cert sent and none cached");
|
||||||
|
throw new SSLPeerUnverifiedException("No peer certificate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -23,10 +23,12 @@ package com.wolfssl.provider.jsse.test;
|
||||||
import com.wolfssl.WolfSSL;
|
import com.wolfssl.WolfSSL;
|
||||||
import com.wolfssl.WolfSSLException;
|
import com.wolfssl.WolfSSLException;
|
||||||
import com.wolfssl.provider.jsse.WolfSSLProvider;
|
import com.wolfssl.provider.jsse.WolfSSLProvider;
|
||||||
|
import com.wolfssl.provider.jsse.WolfSSLContext;
|
||||||
import com.wolfssl.provider.jsse.WolfSSLTrustX509;
|
import com.wolfssl.provider.jsse.WolfSSLTrustX509;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
@ -35,6 +37,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.time.Instant;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
@ -59,6 +62,9 @@ import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLParameters;
|
import javax.net.ssl.SSLParameters;
|
||||||
import javax.net.ssl.SNIHostName;
|
import javax.net.ssl.SNIHostName;
|
||||||
import javax.net.ssl.SNIServerName;
|
import javax.net.ssl.SNIServerName;
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.KeyManager;
|
||||||
|
import javax.net.ssl.X509KeyManager;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
@ -1459,6 +1465,9 @@ public class WolfSSLTrustX509Test {
|
||||||
/* SSLSocket should fail if trying to use bad endoint alg */
|
/* SSLSocket should fail if trying to use bad endoint alg */
|
||||||
testX509ExtendedTrustManagerSSLSocketEndpointAlgFail();
|
testX509ExtendedTrustManagerSSLSocketEndpointAlgFail();
|
||||||
|
|
||||||
|
/* SSLSocket should succeed if server cert changes after resume */
|
||||||
|
testX509ExtendedTrustManagerSSLSocketCertChangeSuccess();
|
||||||
|
|
||||||
/* Basic SSLEngine success case, SNI matches server cert CN */
|
/* Basic SSLEngine success case, SNI matches server cert CN */
|
||||||
testX509ExtendedTrustManagerSSLEngineBasicSuccess();
|
testX509ExtendedTrustManagerSSLEngineBasicSuccess();
|
||||||
|
|
||||||
|
@ -1486,13 +1495,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, true);
|
"HTTPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1538,13 +1547,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, false);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, false, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, false);
|
"HTTPS", "www.wolfssl.com", false, false, false, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1590,13 +1599,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, false);
|
"HTTPS", "www.wolfssl.com", false, false, false, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1642,13 +1651,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, false);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, false, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, true);
|
"HTTPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1694,14 +1703,14 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
/* Correct SNI is www.wolfssl.com, this should cause a failure */
|
/* Correct SNI is www.wolfssl.com, this should cause a failure */
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.invalid.com", false, false, true);
|
"HTTPS", "www.invalid.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1739,15 +1748,15 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
/* We only support "HTTPS" as an endpoint algorithm. Setting
|
/* We only support "HTTPS" as an endpoint algorithm. Setting
|
||||||
* "LDAPS" should fail as unsupported */
|
* "LDAPS" should fail as unsupported */
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"LDAPS", "www.wolfssl.com", false, false, true);
|
"LDAPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -1881,6 +1890,221 @@ public class WolfSSLTrustX509Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get expected peer certificate from this KeyStore, used to compare
|
||||||
|
* cert we get to what we expect.
|
||||||
|
*
|
||||||
|
* This method mimmics behavior inside our WolfSSLContext when we choose
|
||||||
|
* the client/server cert to load into native wolfSSL.
|
||||||
|
*
|
||||||
|
* @param jks path to Java KeyStore (.jks file) to get peer cert from
|
||||||
|
* @param pwd KeyStore password
|
||||||
|
* @return peer cert if found, or null if not or keystore is null/empty
|
||||||
|
*/
|
||||||
|
private X509Certificate getPeerCertFromKeyStore(String jks, String pwd) {
|
||||||
|
|
||||||
|
if (jks == null | jks.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String javaVersion = System.getProperty("java.version");
|
||||||
|
|
||||||
|
FileInputStream stream = new FileInputStream(jks);
|
||||||
|
KeyStore store = KeyStore.getInstance("JKS");
|
||||||
|
store.load(stream, pwd.toCharArray());
|
||||||
|
stream.close();
|
||||||
|
|
||||||
|
KeyManagerFactory km = KeyManagerFactory.getInstance("SunX509");
|
||||||
|
km.init(store, pwd.toCharArray());
|
||||||
|
|
||||||
|
KeyManager[] kms = km.getKeyManagers();
|
||||||
|
if (!(kms[0] instanceof X509KeyManager)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
X509KeyManager x509km = (X509KeyManager)kms[0];
|
||||||
|
|
||||||
|
ArrayList<String> keyAlgos = new ArrayList<String>();
|
||||||
|
if (WolfSSL.EccEnabled() &&
|
||||||
|
(!javaVersion.equals("1.7.0_201") &&
|
||||||
|
!javaVersion.equals("1.7.0_171"))) {
|
||||||
|
keyAlgos.add("EC");
|
||||||
|
}
|
||||||
|
if (WolfSSL.RsaEnabled()) {
|
||||||
|
keyAlgos.add("RSA");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] keyStrings = new String[keyAlgos.size()];
|
||||||
|
keyStrings = keyAlgos.toArray(keyStrings);
|
||||||
|
|
||||||
|
String alias = x509km.chooseClientAlias(keyStrings, null, null);
|
||||||
|
X509Certificate[] cert = x509km.getCertificateChain(alias);
|
||||||
|
/* this is only set up to handle one cert currently for these
|
||||||
|
* test cases */
|
||||||
|
if (cert == null || cert.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cert[0];
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testX509ExtendedTrustManagerSSLSocketCertChangeSuccess()
|
||||||
|
throws CertificateException, IOException, Exception {
|
||||||
|
|
||||||
|
int serverPort = 0;
|
||||||
|
Exception cliException = null;
|
||||||
|
Exception srvException = null;
|
||||||
|
TestSSLSocketClient client = null;
|
||||||
|
TestSSLSocketServer server = null;
|
||||||
|
TestArgs serverArgs = null;
|
||||||
|
TestArgs clientArgs = null;
|
||||||
|
|
||||||
|
/* Expected server certificates */
|
||||||
|
X509Certificate serverCertA = getPeerCertFromKeyStore(tf.serverJKS,
|
||||||
|
"wolfSSL test");
|
||||||
|
X509Certificate serverCertB = getPeerCertFromKeyStore(tf.clientJKS,
|
||||||
|
"wolfSSL test");
|
||||||
|
|
||||||
|
SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider,
|
||||||
|
tf.createTrustManager("SunX509", tf.caClientJKS, provider),
|
||||||
|
tf.createKeyManager("SunX509", tf.serverJKS, provider));
|
||||||
|
|
||||||
|
/* Loading caJKS so client SSLContext can verify server both
|
||||||
|
* before and after cert changes */
|
||||||
|
SSLContext cliCtx = tf.createSSLContext("TLSv1.2", provider,
|
||||||
|
tf.createTrustManager("SunX509", tf.caJKS, provider),
|
||||||
|
tf.createKeyManager("SunX509", tf.clientJKS, provider));
|
||||||
|
|
||||||
|
/* create SSLServerSocket first to get ephemeral port */
|
||||||
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
|
.createServerSocket(serverPort);
|
||||||
|
serverPort = ss.getLocalPort();
|
||||||
|
|
||||||
|
serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
|
server = new TestSSLSocketServer(srvCtx, ss, serverArgs, 2);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
/* FIRST client connection will do a full TLS handshake */
|
||||||
|
clientArgs = new TestArgs(
|
||||||
|
"HTTPS", "www.wolfssl.com", false, false, true, serverCertA);
|
||||||
|
client = new TestSSLSocketClient(cliCtx, serverPort, clientArgs);
|
||||||
|
client.start();
|
||||||
|
try {
|
||||||
|
client.join(1000);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("interrupt happened");
|
||||||
|
fail("ExtendedX509TrustManager cert change test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We shouldn't have any exceptions at this point, if so error out */
|
||||||
|
cliException = client.getException();
|
||||||
|
if (cliException != null) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
if (cliException != null) {
|
||||||
|
cliException.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
String traceString = sw.toString();
|
||||||
|
throw new Exception(traceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SECOND client connection will do a TLS resumed handshake. Server
|
||||||
|
* should shut down after two client connections. */
|
||||||
|
clientArgs = new TestArgs(
|
||||||
|
"HTTPS", "www.wolfssl.com", false, false, true, serverCertA);
|
||||||
|
client = new TestSSLSocketClient(cliCtx, serverPort, clientArgs);
|
||||||
|
client.start();
|
||||||
|
try {
|
||||||
|
client.join(1000);
|
||||||
|
server.join(1000);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("interrupt happened");
|
||||||
|
fail("ExtendedX509TrustManager cert change test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We shouldn't have any exceptions at this point, if so error out */
|
||||||
|
srvException = server.getException();
|
||||||
|
cliException = client.getException();
|
||||||
|
if (srvException != null || cliException != null) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
if (srvException != null) {
|
||||||
|
srvException.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
if (cliException != null) {
|
||||||
|
cliException.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
String traceString = sw.toString();
|
||||||
|
throw new Exception(traceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start up server, but with different certificate loaded. Here we just
|
||||||
|
* switch to loading the client cert, since we have that available.
|
||||||
|
* Also re-create the client SSLContext to make sure the client has the
|
||||||
|
* correct root CA loaded to correctly verify the new/updated server
|
||||||
|
* cert. */
|
||||||
|
ss.close();
|
||||||
|
srvCtx = tf.createSSLContext("TLSv1.2", provider,
|
||||||
|
tf.createTrustManager("SunX509", tf.caClientJKS, provider),
|
||||||
|
tf.createKeyManager("SunX509", tf.clientJKS, provider));
|
||||||
|
|
||||||
|
/* Clear session cache on server side so we don't resume. We just
|
||||||
|
* create a new WolfSSLContext here since the native session cache
|
||||||
|
* is static and shared between WOLFSSL_CONTEXT objects. */
|
||||||
|
com.wolfssl.WolfSSLContext wctx =
|
||||||
|
new com.wolfssl.WolfSSLContext(WolfSSL.SSLv23_ServerMethod());
|
||||||
|
wctx.flushSessions((int)(Instant.now().getEpochSecond() + 1000));
|
||||||
|
wctx.free();
|
||||||
|
|
||||||
|
ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
|
.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
|
server = new TestSSLSocketServer(srvCtx, ss, serverArgs, 1);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
/* THIRD client connection will try to do a TLS resumed handshake,
|
||||||
|
* since we connect to the same host+port, but the server has
|
||||||
|
* been restarted and certificate has changed, so server will
|
||||||
|
* do a new full TLS session. Client should update the cached peer
|
||||||
|
* cert since session is not resumed, and connection + hostname
|
||||||
|
* verificaiton + validation should succeed. */
|
||||||
|
clientArgs = new TestArgs(
|
||||||
|
"HTTPS", "example.com", false, false, true, serverCertB);
|
||||||
|
client = new TestSSLSocketClient(cliCtx, serverPort, clientArgs);
|
||||||
|
client.start();
|
||||||
|
try {
|
||||||
|
client.join(1000);
|
||||||
|
server.join(1000);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("interrupt happened");
|
||||||
|
fail("ExtendedX509TrustManager cert change test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We shouldn't have any exceptions at this point, if so error out */
|
||||||
|
srvException = server.getException();
|
||||||
|
cliException = client.getException();
|
||||||
|
if (srvException != null || cliException != null) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
if (srvException != null) {
|
||||||
|
srvException.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
if (cliException != null) {
|
||||||
|
cliException.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
String traceString = sw.toString();
|
||||||
|
throw new Exception(traceString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testX509ExtendedTrustManagerExternal()
|
public void testX509ExtendedTrustManagerExternal()
|
||||||
throws CertificateException, IOException, Exception {
|
throws CertificateException, IOException, Exception {
|
||||||
|
@ -1979,13 +2203,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, true);
|
"HTTPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -2031,13 +2255,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, true);
|
"HTTPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -2075,13 +2299,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, false);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, false, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, false);
|
"HTTPS", "www.wolfssl.com", false, false, false, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -2128,13 +2352,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, true);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, true, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, false);
|
"HTTPS", "www.wolfssl.com", false, false, false, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -2181,13 +2405,13 @@ public class WolfSSLTrustX509Test {
|
||||||
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
SSLServerSocket ss = (SSLServerSocket)srvCtx.getServerSocketFactory()
|
||||||
.createServerSocket(0);
|
.createServerSocket(0);
|
||||||
|
|
||||||
TestArgs serverArgs = new TestArgs(null, null, true, true, false);
|
TestArgs serverArgs = new TestArgs(null, null, true, true, false, null);
|
||||||
TestSSLSocketServer server = new TestSSLSocketServer(
|
TestSSLSocketServer server = new TestSSLSocketServer(
|
||||||
srvCtx, ss, serverArgs);
|
srvCtx, ss, serverArgs, 1);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
TestArgs clientArgs = new TestArgs(
|
TestArgs clientArgs = new TestArgs(
|
||||||
"HTTPS", "www.wolfssl.com", false, false, true);
|
"HTTPS", "www.wolfssl.com", false, false, true, null);
|
||||||
TestSSLSocketClient client = new TestSSLSocketClient(
|
TestSSLSocketClient client = new TestSSLSocketClient(
|
||||||
cliCtx, ss.getLocalPort(), clientArgs);
|
cliCtx, ss.getLocalPort(), clientArgs);
|
||||||
client.start();
|
client.start();
|
||||||
|
@ -2238,18 +2462,20 @@ public class WolfSSLTrustX509Test {
|
||||||
private boolean wantClientAuth = true;
|
private boolean wantClientAuth = true;
|
||||||
private boolean needClientAuth = true;
|
private boolean needClientAuth = true;
|
||||||
private boolean callStartHandshake = true;
|
private boolean callStartHandshake = true;
|
||||||
|
private X509Certificate expectedPeerCert = null;
|
||||||
|
|
||||||
public TestArgs() { }
|
public TestArgs() { }
|
||||||
|
|
||||||
public TestArgs(String endpointID, String sni,
|
public TestArgs(String endpointID, String sni,
|
||||||
boolean wantClientAuth, boolean needClientAuth,
|
boolean wantClientAuth, boolean needClientAuth,
|
||||||
boolean callStartHandshake) {
|
boolean callStartHandshake, X509Certificate expectedPeerCert) {
|
||||||
|
|
||||||
this.endpointIDAlg = endpointID;
|
this.endpointIDAlg = endpointID;
|
||||||
this.sniName = sni;
|
this.sniName = sni;
|
||||||
this.wantClientAuth = wantClientAuth;
|
this.wantClientAuth = wantClientAuth;
|
||||||
this.needClientAuth = needClientAuth;
|
this.needClientAuth = needClientAuth;
|
||||||
this.callStartHandshake = callStartHandshake;
|
this.callStartHandshake = callStartHandshake;
|
||||||
|
this.expectedPeerCert = expectedPeerCert;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEndpointIdentificationAlg(String alg) {
|
public void setEndpointIdentificationAlg(String alg) {
|
||||||
|
@ -2272,6 +2498,10 @@ public class WolfSSLTrustX509Test {
|
||||||
this.wantClientAuth = want;
|
this.wantClientAuth = want;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setExpectedPeerCert(X509Certificate cert) {
|
||||||
|
this.expectedPeerCert = cert;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getWantClientAuth() {
|
public boolean getWantClientAuth() {
|
||||||
return this.wantClientAuth;
|
return this.wantClientAuth;
|
||||||
}
|
}
|
||||||
|
@ -2291,49 +2521,57 @@ public class WolfSSLTrustX509Test {
|
||||||
public boolean getCallStartHandshake() {
|
public boolean getCallStartHandshake() {
|
||||||
return this.callStartHandshake;
|
return this.callStartHandshake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public X509Certificate getExpectedPeerCert() {
|
||||||
|
return this.expectedPeerCert;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class TestSSLSocketServer extends Thread
|
protected class TestSSLSocketServer extends Thread
|
||||||
{
|
{
|
||||||
private SSLContext ctx;
|
private SSLContext ctx;
|
||||||
private int port;
|
private int port;
|
||||||
|
private int numConnections;
|
||||||
private Exception exception = null;
|
private Exception exception = null;
|
||||||
private TestArgs args = null;
|
private TestArgs args = null;
|
||||||
SSLServerSocket ss = null;
|
SSLServerSocket ss = null;
|
||||||
|
|
||||||
public TestSSLSocketServer(SSLContext ctx, SSLServerSocket ss,
|
public TestSSLSocketServer(SSLContext ctx, SSLServerSocket ss,
|
||||||
TestArgs args) {
|
TestArgs args, int numConnections) {
|
||||||
|
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.ss = ss;
|
this.ss = ss;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
this.numConnections = numConnections;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SSLSocket sock = (SSLSocket)ss.accept();
|
for (int i = 0; i < numConnections; i++) {
|
||||||
sock.setUseClientMode(false);
|
SSLSocket sock = (SSLSocket)ss.accept();
|
||||||
|
sock.setUseClientMode(false);
|
||||||
|
|
||||||
/* Not enabling endpoint identification algo here since
|
/* Not enabling endpoint identification algo here since
|
||||||
* cert does not match client hostname */
|
* cert does not match client hostname */
|
||||||
SSLParameters params = sock.getSSLParameters();
|
SSLParameters params = sock.getSSLParameters();
|
||||||
|
|
||||||
/* Enable client auth */
|
/* Enable client auth */
|
||||||
params.setWantClientAuth(this.args.getWantClientAuth());
|
params.setWantClientAuth(this.args.getWantClientAuth());
|
||||||
params.setNeedClientAuth(this.args.getNeedClientAuth());
|
params.setNeedClientAuth(this.args.getNeedClientAuth());
|
||||||
sock.setSSLParameters(params);
|
sock.setSSLParameters(params);
|
||||||
|
|
||||||
if (this.args.getCallStartHandshake()) {
|
if (this.args.getCallStartHandshake()) {
|
||||||
sock.startHandshake();
|
sock.startHandshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
int in = sock.getInputStream().read();
|
||||||
|
assertEquals(in, (int)'A');
|
||||||
|
sock.getOutputStream().write('B');
|
||||||
|
sock.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int in = sock.getInputStream().read();
|
|
||||||
assertEquals(in, (int)'A');
|
|
||||||
sock.getOutputStream().write('B');
|
|
||||||
sock.close();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.exception = e;
|
this.exception = e;
|
||||||
}
|
}
|
||||||
|
@ -2389,6 +2627,40 @@ public class WolfSSLTrustX509Test {
|
||||||
sock.getOutputStream().write('A');
|
sock.getOutputStream().write('A');
|
||||||
int in = sock.getInputStream().read();
|
int in = sock.getInputStream().read();
|
||||||
assertEquals(in, (int)'B');
|
assertEquals(in, (int)'B');
|
||||||
|
|
||||||
|
X509Certificate expectedPeerCert =
|
||||||
|
this.args.getExpectedPeerCert();
|
||||||
|
if (expectedPeerCert != null) {
|
||||||
|
SSLSession sess = sock.getSession();
|
||||||
|
if (sess == null) {
|
||||||
|
sock.close();
|
||||||
|
throw new Exception(
|
||||||
|
"SSLSocket.getSession() returned null");
|
||||||
|
}
|
||||||
|
Certificate[] certs = sess.getPeerCertificates();
|
||||||
|
if (certs == null || certs.length == 0) {
|
||||||
|
sock.close();
|
||||||
|
throw new Exception(
|
||||||
|
"SSLSession.getPeerCertificates() was null " +
|
||||||
|
"or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(certs[0] instanceof X509Certificate)) {
|
||||||
|
sock.close();
|
||||||
|
throw new Exception(
|
||||||
|
"Peer cert from SSLSession not of type " +
|
||||||
|
"X509Certificate");
|
||||||
|
}
|
||||||
|
X509Certificate peerCert = (X509Certificate)certs[0];
|
||||||
|
if (!peerCert.equals(expectedPeerCert)) {
|
||||||
|
sock.close();
|
||||||
|
throw new Exception(
|
||||||
|
"Peer cert from SSLSession did not match " +
|
||||||
|
"expected\nExpected:" + expectedPeerCert +
|
||||||
|
"\nGot:" + peerCert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sock.close();
|
sock.close();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
Loading…
Reference in New Issue