[maven] IDEA-225239 add caching to maven ssl trust manager

GitOrigin-RevId: 86ac3a38731d03764fea77bcb25ba2345d37fcba
This commit is contained in:
Alexander Bubenchikov
2024-07-18 17:55:44 +02:00
committed by intellij-monorepo-bot
parent f97efb5603
commit b11f4f0d83
4 changed files with 80 additions and 6 deletions

View File

@@ -6,7 +6,7 @@ import org.jetbrains.idea.maven.server.security.ssl.SslIDEConfirmingTrustStore;
public class RemoteMavenServerBase extends RemoteServer {
protected static void startMavenServer(MavenServerBase mavenServer, String[] args) throws Exception {
if(System.getProperty("delegate.ssl.to.ide")!=null) {
if (Boolean.getBoolean("delegate.ssl.to.ide")) {
setupDelegatingSsl();
}

View File

@@ -1,19 +1,25 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.maven.server.security.ssl;
import org.jetbrains.idea.maven.server.MavenServerGlobals;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public final class SslIDEConfirmingTrustStore {
@@ -40,7 +46,8 @@ public final class SslIDEConfirmingTrustStore {
// it depends on the library you're using.
SSLContext.setDefault(sslContext);
}
catch (NoSuchAlgorithmException | KeyManagementException ignore) {
catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
MavenServerGlobals.getLogger().error(e);
}
}
@@ -48,10 +55,56 @@ public final class SslIDEConfirmingTrustStore {
ourMultiplexor.start();
}
private static class TrustRequestKey {
private final X509Certificate[] myChain;
private final String myType;
TrustRequestKey(X509Certificate[] chain, String authType) {
myChain = chain;
myType = authType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TrustRequestKey)) return false;
TrustRequestKey key = (TrustRequestKey)o;
return Objects.deepEquals(myChain, key.myChain) && Objects.equals(myType, key.myType);
}
@Override
public int hashCode() {
return Objects.hash(Arrays.hashCode(myChain), myType);
}
}
private static class IdeDelegateTrustManager implements X509TrustManager {
private ConcurrentHashMap<TrustRequestKey, Boolean> succeed = new ConcurrentHashMap<>();
private final List<X509TrustManager> myTrustManagers;
IdeDelegateTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null);
myTrustManagers = new ArrayList<>();
for (TrustManager m : trustManagerFactory.getTrustManagers()) {
if (m instanceof X509TrustManager) {
myTrustManagers.add((X509TrustManager)m);
}
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
checkTrusted(chain, authType, CHECK_CLIENT_TRUSTED);
for (X509TrustManager m : myTrustManagers) {
try {
m.checkClientTrusted(chain, authType);
return;
}
catch (CertificateException ignore) {
}
}
throw new CertificateException();
}
@SuppressWarnings("UseOfSystemOutOrSystemErr")
@@ -64,10 +117,24 @@ public final class SslIDEConfirmingTrustStore {
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
checkTrusted(chain, authType, CHECK_SERVER_TRUSTED);
for (X509TrustManager m : myTrustManagers) {
try {
m.checkClientTrusted(chain, authType);
return;
}
catch (CertificateException ignore) {
}
}
TrustRequestKey key = new TrustRequestKey(chain, authType);
Boolean cached = succeed.get(key);
if (cached != null && cached) {
return;
}
doCheckTrusted(chain, authType, CHECK_SERVER_TRUSTED);
succeed.put(key, Boolean.TRUE);
}
private void checkTrusted(X509Certificate[] chain, String authType, String methodSignature) throws CertificateException {
private void doCheckTrusted(X509Certificate[] chain, String authType, String methodSignature) throws CertificateException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Integer key = ourMultiplexor.getKey();
try (PrintStream out = new PrintStream(os, false, "ISO-8859-1")) {

View File

@@ -112,6 +112,10 @@ public class MavenServerCMDState extends CommandLineState {
params.getVMParametersList().addProperty("maven.collect.local.stat", "true");
}
if (Registry.is("maven.delegate.trust.ssl.to.ide")) {
params.getVMParametersList().addProperty("delegate.ssl.to.ide", "true");
}
String profilerOption = getProfilerVMString();
if (profilerOption != null) {
params.getVMParametersList()

View File

@@ -402,6 +402,9 @@
<registryKey key="maven.incremental.sync.resolve.dependencies.incrementally" defaultValue="true"
description="During incremental sync, resolve dependencies incrementally"/>
<registryKey key="maven.delegate.trust.ssl.to.ide" defaultValue="false"
description="Use IDEA confirming trust manager for maven importer"/>
<intentionAction>
<language>XML</language>
<className>org.jetbrains.idea.maven.dom.converters.MavenArtifactCoordinatesConverter$MyUpdateIndicesIntention</className>