Skip to content

Commit 7cbaabf

Browse files
authored
SNOW-2177175 Fix for default trust manager not extending X509ExtendedTrustManager (#2266)
1 parent a51c8fd commit 7cbaabf

4 files changed

Lines changed: 98 additions & 11 deletions

File tree

ci/container/build_component.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ mvn clean install --batch-mode --show-version
1212

1313
cd FIPS
1414
rm -f lib/*.jar
15-
mvn clean install --batch-mode --show-version
15+
mvn clean install -Dsurefire.argLine="-Djavax.net.debug=ssl:handshake" -Dfailsafe.argLine="-Djavax.net.debug=ssl:handshake" --batch-mode --show-version
1616
$THIS_DIR/upload_artifact.sh

src/main/java/net/snowflake/client/core/HttpUtil.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ public class HttpUtil {
106106

107107
private static boolean socksProxyDisabled = false;
108108

109+
@SnowflakeJdbcInternalApi
110+
public static void reset() {
111+
httpClient.clear();
112+
httpClientWithoutDecompression.clear();
113+
httpClientRoutePlanner.clear();
114+
}
115+
109116
@SnowflakeJdbcInternalApi
110117
public static Duration getConnectionTimeout() {
111118
return connectionTimeout != null

src/main/java/net/snowflake/client/core/SFTrustManager.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,12 @@ public class SFTrustManager extends X509ExtendedTrustManager {
267267
this.proxySettingsKey = key;
268268
this.trustManager = getTrustManager(TrustManagerFactory.getDefaultAlgorithm());
269269

270-
this.exTrustManager =
271-
(X509ExtendedTrustManager) getTrustManager(TrustManagerFactory.getDefaultAlgorithm());
270+
if (trustManager instanceof X509ExtendedTrustManager) {
271+
this.exTrustManager = (X509ExtendedTrustManager) trustManager;
272+
} else {
273+
logger.debug("Standard X509TrustManager is used instead of X509ExtendedTrustManager.");
274+
this.exTrustManager = null;
275+
}
272276

273277
checkNewOCSPEndpointAvailability();
274278

@@ -725,31 +729,43 @@ public void checkServerTrusted(X509Certificate[] chain, String authType)
725729
@Override
726730
public void checkClientTrusted(X509Certificate[] chain, String authType, java.net.Socket socket)
727731
throws CertificateException {
728-
// default behavior
729-
this.exTrustManager.checkClientTrusted(chain, authType, socket);
732+
if (exTrustManager != null) {
733+
exTrustManager.checkClientTrusted(chain, authType, socket);
734+
} else {
735+
trustManager.checkClientTrusted(chain, authType);
736+
}
730737
}
731738

732739
@Override
733740
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine)
734741
throws CertificateException {
735-
// default behavior
736-
exTrustManager.checkClientTrusted(chain, authType, sslEngine);
742+
if (exTrustManager != null) {
743+
exTrustManager.checkClientTrusted(chain, authType, sslEngine);
744+
} else {
745+
trustManager.checkClientTrusted(chain, authType);
746+
}
737747
}
738748

739749
@Override
740750
public void checkServerTrusted(X509Certificate[] chain, String authType, java.net.Socket socket)
741751
throws CertificateException {
742-
// default behavior
743-
exTrustManager.checkServerTrusted(chain, authType, socket);
752+
if (exTrustManager != null) {
753+
exTrustManager.checkServerTrusted(chain, authType, socket);
754+
} else {
755+
trustManager.checkServerTrusted(chain, authType);
756+
}
744757
String host = socket.getInetAddress().getHostName();
745758
this.validateRevocationStatus(chain, host);
746759
}
747760

748761
@Override
749762
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine)
750763
throws CertificateException {
751-
// default behavior
752-
exTrustManager.checkServerTrusted(chain, authType, sslEngine);
764+
if (exTrustManager != null) {
765+
exTrustManager.checkServerTrusted(chain, authType, sslEngine);
766+
} else {
767+
trustManager.checkServerTrusted(chain, authType);
768+
}
753769
this.validateRevocationStatus(chain, sslEngine.getPeerHost());
754770
}
755771

src/test/java/net/snowflake/client/core/SFTrustManagerIT.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,29 @@
1212
import java.io.IOException;
1313
import java.io.InputStream;
1414
import java.net.URL;
15+
import java.security.InvalidAlgorithmParameterException;
16+
import java.security.KeyStore;
17+
import java.security.KeyStoreException;
18+
import java.security.Provider;
19+
import java.security.Security;
1520
import java.security.cert.Certificate;
21+
import java.security.cert.CertificateException;
1622
import java.security.cert.CertificateFactory;
1723
import java.security.cert.X509Certificate;
24+
import java.sql.Connection;
25+
import java.sql.Statement;
1826
import java.time.Duration;
1927
import java.util.ArrayList;
2028
import java.util.Arrays;
2129
import java.util.List;
2230
import java.util.Properties;
2331
import java.util.concurrent.TimeUnit;
2432
import java.util.stream.Stream;
33+
import javax.net.ssl.ManagerFactoryParameters;
2534
import javax.net.ssl.SSLHandshakeException;
35+
import javax.net.ssl.TrustManager;
36+
import javax.net.ssl.TrustManagerFactorySpi;
37+
import javax.net.ssl.X509TrustManager;
2638
import net.snowflake.client.SystemPropertyOverrider;
2739
import net.snowflake.client.category.TestTags;
2840
import net.snowflake.client.jdbc.BaseJDBCTest;
@@ -36,6 +48,7 @@
3648
import org.junit.jupiter.api.AfterEach;
3749
import org.junit.jupiter.api.BeforeEach;
3850
import org.junit.jupiter.api.Tag;
51+
import org.junit.jupiter.api.Test;
3952
import org.junit.jupiter.api.extension.ExtensionContext;
4053
import org.junit.jupiter.api.io.TempDir;
4154
import org.junit.jupiter.params.ParameterizedTest;
@@ -316,9 +329,60 @@ void testOCSPCacheServerUrlWithProxy(String sfHost, String ocspHost) {
316329
}
317330
}
318331

332+
@Test
333+
void shouldNotFailWhenSimpleTrustManagerIsUsed() throws Exception {
334+
Security.insertProviderAt(new TestSecurityProvider(), 1);
335+
HttpUtil.reset();
336+
try (Connection connection = getConnection()) {
337+
Statement statement = connection.createStatement();
338+
statement.execute("SELECT 1");
339+
} finally {
340+
Security.removeProvider(TestSecurityProvider.class.getSimpleName());
341+
HttpUtil.reset();
342+
}
343+
}
344+
319345
@BeforeEach
320346
@AfterEach
321347
void cleanup() {
322348
SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE = null;
323349
}
324350
}
351+
352+
// Standard JCA implementation for registering custom TrustManagerFactory
353+
class TestTrustManagerSpi extends TrustManagerFactorySpi {
354+
355+
@Override
356+
protected void engineInit(KeyStore ks) throws KeyStoreException {}
357+
358+
@Override
359+
protected void engineInit(ManagerFactoryParameters spec)
360+
throws InvalidAlgorithmParameterException {}
361+
362+
@Override
363+
protected TrustManager[] engineGetTrustManagers() {
364+
return new TrustManager[] {
365+
new X509TrustManager() {
366+
@Override
367+
public void checkClientTrusted(X509Certificate[] chain, String authType)
368+
throws CertificateException {}
369+
370+
@Override
371+
public void checkServerTrusted(X509Certificate[] chain, String authType)
372+
throws CertificateException {}
373+
374+
@Override
375+
public X509Certificate[] getAcceptedIssuers() {
376+
return new X509Certificate[0];
377+
}
378+
}
379+
};
380+
}
381+
}
382+
383+
class TestSecurityProvider extends Provider {
384+
public TestSecurityProvider() {
385+
super(TestSecurityProvider.class.getSimpleName(), 1.0, "Test security provider");
386+
put("TrustManagerFactory.PKIX", TestTrustManagerSpi.class.getName());
387+
}
388+
}

0 commit comments

Comments
 (0)