From c159f758c71b25bf1c4ad918716695cbb0de8a15 Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Mon, 25 Mar 2024 17:44:45 +0100 Subject: [PATCH] fix: added CompositeX509ExtendedTrustManager, removed ext one (#212) Signed-off-by: Andre Dietisheim --- build.gradle | 3 +- .../CompositeX509ExtendedTrustManager.java | 108 ++++++++++++++++++ .../intellij/common/ssl/IDEATrustManager.java | 7 +- .../common/ssl/IDEATrustManagerTest.java | 3 +- 4 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/intellij/common/ssl/CompositeX509ExtendedTrustManager.java diff --git a/build.gradle b/build.gradle index 630eb65..a5c34f1 100755 --- a/build.gradle +++ b/build.gradle @@ -56,8 +56,7 @@ dependencies { 'io.fabric8:kubernetes-httpclient-okhttp:6.4.1', 'org.apache.commons:commons-exec:1.3', 'org.apache.commons:commons-lang3:3.12.0', - 'com.twelvemonkeys.common:common-lang:3.9.4', - 'io.github.hakky54:sslcontext-kickstart:8.3.2' + 'com.twelvemonkeys.common:common-lang:3.9.4' ) testImplementation( 'org.assertj:assertj-core:3.17.1', diff --git a/src/main/java/com/redhat/devtools/intellij/common/ssl/CompositeX509ExtendedTrustManager.java b/src/main/java/com/redhat/devtools/intellij/common/ssl/CompositeX509ExtendedTrustManager.java new file mode 100644 index 0000000..5272508 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/common/ssl/CompositeX509ExtendedTrustManager.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Based on nl.altindag.ssl.trustmanager.CompositeX509ExtendedTrustManager at https://github.com/Hakky54/sslcontext-kickstart + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.redhat.devtools.intellij.common.ssl; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; +import java.net.Socket; +import java.security.InvalidAlgorithmParameterException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class CompositeX509ExtendedTrustManager extends X509ExtendedTrustManager { + + private static final String CERTIFICATE_EXCEPTION_MESSAGE = "None of the TrustManagers trust this certificate chain"; + + private final List innerTrustManagers; + private final X509Certificate[] acceptedIssuers; + + public CompositeX509ExtendedTrustManager(List trustManagers) { + this.innerTrustManagers = Collections.unmodifiableList(trustManagers); + this.acceptedIssuers = trustManagers.stream() + .map((manager) -> + Objects.requireNonNullElseGet(manager.getAcceptedIssuers(), () -> new X509Certificate[]{}) + ) + .flatMap(Arrays::stream) + .toArray(X509Certificate[]::new); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return Arrays.copyOf(acceptedIssuers, acceptedIssuers.length); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkClientTrusted(chain, authType)); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkServerTrusted(chain, authType)); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkClientTrusted(chain, authType, socket)); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkServerTrusted(chain, authType, socket)); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkClientTrusted(chain, authType, engine)); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { + checkTrusted((trustManager) -> trustManager.checkServerTrusted(chain, authType, engine)); + } + + public List getInnerTrustManagers() { + return innerTrustManagers; + } + + private void checkTrusted(TrustManagerConsumer consumer) throws CertificateException { + List certificateExceptions = new ArrayList<>(); + for (X509ExtendedTrustManager trustManager : innerTrustManagers) { + try { + consumer.checkTrusted(trustManager); + return; + } catch (CertificateException e) { + certificateExceptions.add(e); + } catch (RuntimeException e) { + Throwable cause = e.getCause(); + if (!(cause instanceof InvalidAlgorithmParameterException)) { + throw e; + } + + certificateExceptions.add(new CertificateException(cause)); + } + } + CertificateException certificateException = new CertificateException(CERTIFICATE_EXCEPTION_MESSAGE); + certificateExceptions.forEach(certificateException::addSuppressed); + throw certificateException; + } + + interface TrustManagerConsumer { + void checkTrusted(X509ExtendedTrustManager var1) throws CertificateException; + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManager.java b/src/main/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManager.java index 4bf44d9..d8934f4 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManager.java +++ b/src/main/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManager.java @@ -12,7 +12,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.net.ssl.CertificateManager; -import nl.altindag.ssl.trustmanager.CompositeX509ExtendedTrustManager; import org.apache.commons.lang3.reflect.FieldUtils; import javax.net.ssl.X509ExtendedTrustManager; @@ -134,10 +133,12 @@ private void addCompositeManager( if (!(object instanceof List)) return; List managers = (List) object; - List nonCompositeManagers = managers.stream().filter(x509TrustManager -> !(x509TrustManager instanceof CompositeX509ExtendedTrustManager)).collect(Collectors.toList()); + List nonCompositeManagers = managers.stream() + .filter(x509TrustManager -> !(x509TrustManager instanceof CompositeX509ExtendedTrustManager)) + .collect(Collectors.toList()); CompositeX509ExtendedTrustManager clientTrustManager = new CompositeX509ExtendedTrustManager(new ArrayList<>(trustManagers)); managers.clear(); managers.addAll(nonCompositeManagers); managers.add(clientTrustManager); } -} \ No newline at end of file +} diff --git a/src/test/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManagerTest.java b/src/test/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManagerTest.java index 8fcf570..e965b8d 100644 --- a/src/test/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManagerTest.java +++ b/src/test/java/com/redhat/devtools/intellij/common/ssl/IDEATrustManagerTest.java @@ -19,7 +19,6 @@ import javax.net.ssl.X509ExtendedTrustManager; import javax.net.ssl.X509TrustManager; -import nl.altindag.ssl.trustmanager.CompositeX509ExtendedTrustManager; import org.junit.Test; import static junit.framework.TestCase.assertTrue; @@ -207,4 +206,4 @@ public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } -} \ No newline at end of file +}