Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.launchdarkly.sdk.internal.http;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;

import java.security.GeneralSecurityException;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;

/**
* Classifies a failure into one of two regimes: {@link #NORMAL} or
Expand Down Expand Up @@ -34,8 +36,10 @@ public enum FailureClass {
*/
static boolean hasTlsOrCertificateCause(Throwable t) {
for (Throwable c = t; c != null; c = c.getCause()) {
if (c instanceof SSLException
|| c instanceof GeneralSecurityException) {
if (c instanceof CertificateException
|| c instanceof CertPathValidatorException
|| c instanceof CertPathBuilderException
|| c instanceof SSLPeerUnverifiedException) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import org.junit.Test;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;

import java.io.EOFException;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;

import static com.launchdarkly.sdk.internal.http.FailureClass.NORMAL;
import static com.launchdarkly.sdk.internal.http.FailureClass.UNEXPECTED;
Expand Down Expand Up @@ -57,9 +62,6 @@ public class HttpErrorsClassificationTest {
}

// TLS / certificate validation failures are UNEXPECTED.
@Test public void sslHandshakeIsUnexpected() {
assertEquals(UNEXPECTED, HttpErrors.classifyTransportFailure(new SSLHandshakeException("handshake failed")));
}
@Test public void sslPeerUnverifiedIsUnexpected() {
assertEquals(UNEXPECTED, HttpErrors.classifyTransportFailure(new SSLPeerUnverifiedException("peer not verified")));
}
Expand All @@ -69,10 +71,40 @@ public class HttpErrorsClassificationTest {
@Test public void certificateExpiredIsUnexpected() {
assertEquals(UNEXPECTED, HttpErrors.classifyTransportFailure(new CertificateExpiredException("expired")));
}
@Test public void certificateNotYetValidIsUnexpected() {
assertEquals(UNEXPECTED,
HttpErrors.classifyTransportFailure(new CertificateNotYetValidException("not yet valid")));
}
@Test public void certPathValidatorFailureIsUnexpected() {
assertEquals(UNEXPECTED,
HttpErrors.classifyTransportFailure(new CertPathValidatorException("path invalid")));
}
@Test public void certPathBuilderFailureIsUnexpected() {
assertEquals(UNEXPECTED,
HttpErrors.classifyTransportFailure(new CertPathBuilderException("cannot build path")));
}

@Test public void untrustedChainWrappedInHandshakeExceptionIsUnexpected() {
SSLHandshakeException e = new SSLHandshakeException("PKIX path building failed");
e.initCause(new CertPathBuilderException("unable to find valid certification path"));
assertEquals(UNEXPECTED, HttpErrors.classifyTransportFailure(e));
}

@Test public void bareSslHandshakeFailureIsNormal() {
assertEquals(NORMAL, HttpErrors.classifyTransportFailure(new SSLHandshakeException("handshake failed")));
}
@Test public void peerClosedMidHandshakeIsNormal() {
SSLHandshakeException e = new SSLHandshakeException("Remote host terminated the handshake");
e.initCause(new EOFException("SSL peer shut down incorrectly"));
assertEquals(NORMAL, HttpErrors.classifyTransportFailure(e));
}
@Test public void sslExceptionFromConnectionResetIsNormal() {
assertEquals(NORMAL, HttpErrors.classifyTransportFailure(new SSLException("Connection reset")));
}

// Cause-chain walk finds TLS deep in wrapper exceptions.
@Test public void sslCauseWrappedIsUnexpected() {
IOException wrapper = new IOException("wrapped", new SSLHandshakeException("real cause"));
@Test public void certificateCauseWrappedIsUnexpected() {
IOException wrapper = new IOException("wrapped", new CertificateException("real cause"));
assertEquals(UNEXPECTED, HttpErrors.classifyTransportFailure(wrapper));
}
}
Loading