Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,11 @@ private void initHandshakeInternal(SSLSocket socket, SSLEngine engine)
else {
this.session.setSessionContext(authStore.getServerContext());
this.session.setSide(WolfSSL.WOLFSSL_SERVER_END);
/* Track client auth state for getPeerCertificates() */
boolean clientAuthRequested =
this.params.getNeedClientAuth() ||
this.params.getWantClientAuth();
this.session.setClientAuthRequested(clientAuthRequested);
}

if (this.sessionCreation == false && !this.session.isFromTable) {
Expand Down
45 changes: 41 additions & 4 deletions src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession {
byte[] pseudoSessionID = null; /* used with TLS 1.3*/
private int side = 0;

/* Track if client auth was requested, for getPeerCertificates() behavior */
private volatile boolean clientAuthRequested = false;

/* Cache peer certificates after received. Applications assume that
* SSLSocket.getSession().getPeerCertificates() will return the peer
* certificate even on a resumed connection where the cert has not been
Expand Down Expand Up @@ -260,6 +263,7 @@ public WolfSSLImplementSSLSession (WolfSSLImplementSSLSession orig) {
this.pseudoSessionID = orig.pseudoSessionID.clone();
}
this.side = orig.side;
this.clientAuthRequested = orig.clientAuthRequested;
if (orig.peerCerts != null) {
this.peerCerts = orig.peerCerts.clone();
}
Expand Down Expand Up @@ -519,6 +523,15 @@ public synchronized Certificate[] getPeerCertificates()
"SSLSocket/Engine closed");
}

/* Throw if server side with no client auth requested */
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
!this.clientAuthRequested) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "Server side, no client auth, throwing exception");
throw new SSLPeerUnverifiedException(
"peer not authenticated (no client auth requested)");
}

try {
x509 = this.ssl.getPeerCertificate();
} catch (IllegalStateException | WolfSSLJNIException ex) {
Expand Down Expand Up @@ -605,8 +618,8 @@ public Certificate[] getLocalCertificates() {
}

@Override
public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChain()
throws SSLPeerUnverifiedException {
public synchronized javax.security.cert.X509Certificate[]
getPeerCertificateChain() throws SSLPeerUnverifiedException {

long peerX509 = 0;
WolfSSLX509X x509;
Expand All @@ -615,10 +628,17 @@ public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChai
throw new SSLPeerUnverifiedException("handshake not done");
}

/* Throw if server side with no client auth requested */
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
!this.clientAuthRequested) {
throw new SSLPeerUnverifiedException(
"peer not authenticated (no client auth requested)");
}

try {
peerX509 = this.ssl.getPeerCertificate();
if (peerX509 == 0) {
return null;
throw new SSLPeerUnverifiedException("No peer certificate");
}

/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
Expand Down Expand Up @@ -657,10 +677,17 @@ public synchronized Principal getPeerPrincipal()
throw new SSLPeerUnverifiedException("handshake not done");
}

/* Throw if server side with no client auth requested */
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
!this.clientAuthRequested) {
throw new SSLPeerUnverifiedException(
"peer not authenticated (no client auth requested)");
}

try {
peerX509 = this.ssl.getPeerCertificate();
if (peerX509 == 0) {
return null;
throw new SSLPeerUnverifiedException("No peer certificate");
}

/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
Expand Down Expand Up @@ -1039,6 +1066,16 @@ protected int getSide() {
return this.side;
}

/**
* Set whether client auth was requested.
* Used for getPeerCertificates() behavior.
*
* @param requested true if client auth was requested, false otherwise
*/
protected void setClientAuthRequested(boolean requested) {
this.clientAuthRequested = requested;
}

/**
* Return the side session is on (server/client) as a String
* @return "client" or "server" representing the side of this session
Expand Down
50 changes: 50 additions & 0 deletions src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -2494,5 +2495,54 @@ private ByteBuffer enlargeBuffer(ByteBuffer buffer, int size) {
bb.put(buffer);
return bb;
}

/**
* Verify getPeerCertificateChain() throws SSLPeerUnverifiedException
* when no client auth requested, matching SunJSSE/Netty expectations.
*/
@Test
public void testGetPeerCertificateChainNoClientAuth() throws Exception {

System.out.print("\tgetPeerCertChain no client auth");

String protocol = null;
for (String p : enabledProtocols) {
if (!p.equals("TLS") && !p.contains("DTLS")) {
protocol = p;
break;
}
}

if (protocol == null) {
pass("\t... skipped");
return;
}

SSLContext ctx = tf.createSSLContext(protocol, engineProvider);

SSLEngine server = ctx.createSSLEngine();
SSLEngine client = ctx.createSSLEngine("localhost", 11111);

server.setUseClientMode(false);
server.setNeedClientAuth(false);
server.setWantClientAuth(false);
client.setUseClientMode(true);

tf.testConnection(server, client, null, null, "No client auth test");

SSLSession serverSession = server.getSession();

try {
javax.security.cert.X509Certificate[] certs =
serverSession.getPeerCertificateChain();
error("\t... failed");
fail("Expected SSLPeerUnverifiedException, got " +
(certs == null ? "null" : "certs"));
} catch (SSLPeerUnverifiedException e) {
/* Expected */
}

pass("\t... passed");
}
}

Loading