mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ssl: populate storages through RMI calls
GitOrigin-RevId: e89a0fd55dd2b6aecb67b76b4003c4d4d3d2ee6f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7ee469273a
commit
b65849248d
@@ -175,19 +175,28 @@ public class RemoteServer {
|
||||
|
||||
private static void setupSSL() {
|
||||
setupDisabledAlgorithms();
|
||||
boolean caCert = System.getProperty(SslUtil.SSL_CA_CERT_PATH) != null;
|
||||
boolean clientCert = System.getProperty(SslUtil.SSL_CLIENT_CERT_PATH) != null;
|
||||
boolean clientKey = System.getProperty(SslUtil.SSL_CLIENT_KEY_PATH) != null;
|
||||
String caCertPath = System.getProperty(SslUtil.SSL_CA_CERT_PATH);
|
||||
boolean caCert = caCertPath != null;
|
||||
String clientCertPath = System.getProperty(SslUtil.SSL_CLIENT_CERT_PATH);
|
||||
String clientKeyPath = System.getProperty(SslUtil.SSL_CLIENT_KEY_PATH);
|
||||
boolean clientKey = clientKeyPath != null;
|
||||
boolean deferred = "true".equals(System.getProperty(SslKeyStore.SSL_DEFERRED_KEY_LOADING));
|
||||
boolean deferredCa = "true".equals(System.getProperty(SslKeyStore.SSL_DEFERRED_CA_LOADING));
|
||||
boolean useFactory = "true".equals(System.getProperty(SslUtil.SSL_USE_FACTORY));
|
||||
if (useFactory) {
|
||||
if (caCert || clientCert && clientKey) {
|
||||
if (caCert || clientKey) {
|
||||
Security.setProperty("ssl.SocketFactory.provider", SslSocketFactory.class.getName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (caCert) SslTrustStore.setDefault();
|
||||
if (clientCert && clientKey || deferred) SslKeyStore.setDefault();
|
||||
if (caCert || deferredCa) SslTrustStore.setDefault();
|
||||
if (clientKey || deferred) SslKeyStore.setDefault();
|
||||
}
|
||||
if (caCert) {
|
||||
SslTrustStore.appendUserCert("user-provided-ca", caCertPath);
|
||||
}
|
||||
if (clientKey) {
|
||||
SslKeyStore.loadKey("user-provided-key", clientKeyPath, clientCertPath, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,16 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
Security.addProvider(this);
|
||||
}};
|
||||
|
||||
protected final KeyStore delegate;
|
||||
private final KeyStore delegate;
|
||||
|
||||
protected KeyStore getDelegate() {
|
||||
validate(delegate);
|
||||
return delegate;
|
||||
}
|
||||
|
||||
protected void validate(KeyStore keyStore) {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
static String getDefaultKeyStorePath() {
|
||||
@@ -42,7 +50,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
try {
|
||||
return delegate.getKey(alias, password);
|
||||
return getDelegate().getKey(alias, password);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -52,7 +60,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public java.security.cert.Certificate[] engineGetCertificateChain(String alias) {
|
||||
try {
|
||||
return delegate.getCertificateChain(alias);
|
||||
return getDelegate().getCertificateChain(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -62,7 +70,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public java.security.cert.Certificate engineGetCertificate(String alias) {
|
||||
try {
|
||||
return delegate.getCertificate(alias);
|
||||
return getDelegate().getCertificate(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -72,7 +80,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
try {
|
||||
return delegate.getCreationDate(alias);
|
||||
return getDelegate().getCreationDate(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -81,28 +89,28 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
|
||||
@Override
|
||||
public void engineSetKeyEntry(String alias, Key key, char[] password, java.security.cert.Certificate[] chain) throws KeyStoreException {
|
||||
delegate.setKeyEntry(alias, key, password, chain);
|
||||
getDelegate().setKeyEntry(alias, key, password, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineSetKeyEntry(String alias, byte[] key, java.security.cert.Certificate[] chain) throws KeyStoreException {
|
||||
delegate.setKeyEntry(alias, key, chain);
|
||||
getDelegate().setKeyEntry(alias, key, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineSetCertificateEntry(String alias, java.security.cert.Certificate cert) throws KeyStoreException {
|
||||
delegate.setCertificateEntry(alias, cert);
|
||||
getDelegate().setCertificateEntry(alias, cert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineDeleteEntry(String alias) throws KeyStoreException {
|
||||
delegate.deleteEntry(alias);
|
||||
getDelegate().deleteEntry(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> engineAliases() {
|
||||
try {
|
||||
return delegate.aliases();
|
||||
return getDelegate().aliases();
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -112,7 +120,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public boolean engineContainsAlias(String alias) {
|
||||
try {
|
||||
return delegate.containsAlias(alias);
|
||||
return getDelegate().containsAlias(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -122,7 +130,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public int engineSize() {
|
||||
try {
|
||||
return delegate.size();
|
||||
return getDelegate().size();
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -132,7 +140,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public boolean engineIsKeyEntry(String alias) {
|
||||
try {
|
||||
return delegate.isKeyEntry(alias);
|
||||
return getDelegate().isKeyEntry(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -142,7 +150,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public boolean engineIsCertificateEntry(String alias) {
|
||||
try {
|
||||
return delegate.isCertificateEntry(alias);
|
||||
return getDelegate().isCertificateEntry(alias);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -152,7 +160,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public String engineGetCertificateAlias(Certificate cert) {
|
||||
try {
|
||||
return delegate.getCertificateAlias(cert);
|
||||
return getDelegate().getCertificateAlias(cert);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -162,7 +170,7 @@ public class DelegateKeyStore extends KeyStoreSpi {
|
||||
@Override
|
||||
public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
|
||||
try {
|
||||
delegate.store(stream, password);
|
||||
getDelegate().store(stream, password);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
|
||||
@@ -6,26 +6,28 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class SslKeyStore extends DelegateKeyStore {
|
||||
public static final String SSL_DEFERRED_KEY_LOADING = "sslDeferredKeyLoading";
|
||||
public static final String SSL_DEFERRED_CA_LOADING = "sslDeferredCaLoading";
|
||||
public static final String NAME = "idea-key-store";
|
||||
private static final Map<PrivateKey, X509Certificate> ourAutoAdded = new LinkedHashMap<>();
|
||||
private static final List<KeyEntry> ourAdded = new ArrayList<>();
|
||||
private int myAdded;
|
||||
static {
|
||||
ourProvider.setProperty("KeyStore." + NAME, SslKeyStore.class.getName());
|
||||
}
|
||||
|
||||
public SslKeyStore() {
|
||||
super("PKCS12");
|
||||
loadUserCert();
|
||||
}
|
||||
|
||||
public static void setDefault() {
|
||||
@@ -35,40 +37,57 @@ public final class SslKeyStore extends DelegateKeyStore {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadUserCert() {
|
||||
String certPath = System.getProperty(SslUtil.SSL_CLIENT_CERT_PATH);
|
||||
String keyPath = System.getProperty(SslUtil.SSL_CLIENT_KEY_PATH);
|
||||
if (certPath != null && keyPath != null) {
|
||||
try {
|
||||
loadKey(certPath, keyPath, null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
@Nullable
|
||||
public static PrivateKey getUserKey() {
|
||||
return ourAdded.isEmpty() ? null : ourAdded.get(0).key;
|
||||
}
|
||||
|
||||
public static void loadKey(@NotNull String alias,
|
||||
@NotNull String clientKeyPath,
|
||||
@Nullable String clientCertPath,
|
||||
@Nullable char[] password) {
|
||||
try {
|
||||
PrivateKey key = SslUtil.readPrivateKey(clientKeyPath, password);
|
||||
List<X509Certificate> certificates = clientCertPath == null ? null : SslUtil.loadCertificates(clientCertPath);
|
||||
ourAdded.add(new KeyEntry(alias, key, certificates == null ? null : certificates.toArray(new Certificate[0])));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadKey(@NotNull String clientCertPath,
|
||||
@NotNull String clientKeyPath,
|
||||
@Nullable char[] password) throws CertificateException, IOException {
|
||||
PrivateKey key = SslUtil.readPrivateKey(clientKeyPath, password);
|
||||
if (ourAutoAdded.containsKey(key)) return;
|
||||
X509Certificate cert = SslUtil.readCertificate(clientCertPath);
|
||||
ourAutoAdded.put(key, cert);
|
||||
|
||||
@Override
|
||||
protected void validate(KeyStore keyStore) {
|
||||
super.validate(keyStore);
|
||||
for (int i = myAdded, sz = ourAdded.size(); i < sz; ++i) {
|
||||
KeyEntry entry = ourAdded.get(i);
|
||||
if (entry.certChain != null) {
|
||||
try {
|
||||
keyStore.setKeyEntry(entry.alias, entry.key, null, entry.certChain);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
myAdded = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
|
||||
delegate.load(null, null);
|
||||
int i = 0;
|
||||
for (Map.Entry<PrivateKey, X509Certificate> entry : ourAutoAdded.entrySet()) {
|
||||
try {
|
||||
delegate.setKeyEntry("user-provided-key" + (i == 0 ? "" : "#" + i), entry.getKey(), null, new Certificate[]{entry.getValue()});
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
++i;
|
||||
super.engineLoad(null, null);
|
||||
}
|
||||
|
||||
private static class KeyEntry {
|
||||
private final String alias;
|
||||
private final PrivateKey key;
|
||||
private final Certificate[] certChain;
|
||||
|
||||
private KeyEntry(@NotNull String alias, @NotNull PrivateKey key, @Nullable Certificate[] certChain) {
|
||||
this.alias = alias;
|
||||
this.key = key;
|
||||
this.certChain = certChain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.execution.rmi.ssl;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,6 +24,9 @@ public final class SslTrustStore extends DelegateKeyStore {
|
||||
ourProvider.setProperty("KeyStore." + NAME, SslTrustStore.class.getName());
|
||||
}
|
||||
|
||||
private static final List<Pair<String, ? extends Certificate>> ourAdded = new ArrayList<>();
|
||||
private int myAdded;
|
||||
|
||||
public SslTrustStore() {
|
||||
super(KeyStore.getDefaultType());
|
||||
}
|
||||
@@ -34,15 +40,29 @@ public final class SslTrustStore extends DelegateKeyStore {
|
||||
|
||||
@Override
|
||||
public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
|
||||
delegate.load(null, null);
|
||||
appendUserItems(delegate);
|
||||
super.engineLoad(null, null);
|
||||
}
|
||||
|
||||
private static void appendUserCert(KeyStore keyStore, String alias, String path) {
|
||||
@Override
|
||||
protected void validate(KeyStore keyStore) {
|
||||
super.validate(keyStore);
|
||||
for (int i = myAdded, sz = ourAdded.size(); i < sz; ++i) {
|
||||
Pair<String, ? extends Certificate> cert = ourAdded.get(i);
|
||||
try {
|
||||
keyStore.setCertificateEntry(cert.first, cert.second);
|
||||
}
|
||||
catch (KeyStoreException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
myAdded = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void appendUserCert(@NotNull String alias, @NotNull String path) {
|
||||
try {
|
||||
List<X509Certificate> certs = SslUtil.loadCertificates(path);
|
||||
for (int i = 0; i < certs.size(); i++) {
|
||||
keyStore.setCertificateEntry(i == 0 ? alias : alias + "-" + i, certs.get(i));
|
||||
ourAdded.add(Pair.create(i == 0 ? alias : alias + "-" + i, certs.get(i)));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -50,7 +70,7 @@ public final class SslTrustStore extends DelegateKeyStore {
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendUserTrustStore(KeyStore keyStore, String path, char[] password) {
|
||||
public static void appendUserTrustStore(@NotNull String path, char[] password) {
|
||||
try {
|
||||
File file = new File(path);
|
||||
if (!file.exists()) return;
|
||||
@@ -62,28 +82,11 @@ public final class SslTrustStore extends DelegateKeyStore {
|
||||
String alias = aliases.nextElement();
|
||||
Certificate certificate = tmpStore.getCertificate(alias);
|
||||
if (certificate == null) continue;
|
||||
keyStore.setCertificateEntry(alias, certificate);
|
||||
ourAdded.add(Pair.create(alias, certificate));;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendUserItems(KeyStore keyStore) {
|
||||
String userCert = System.getProperty(SslUtil.SSL_CA_CERT_PATH);
|
||||
if (!StringUtilRt.isEmpty(userCert)) {
|
||||
appendUserCert(keyStore, "user-provided-ca", userCert);
|
||||
}
|
||||
String trustStores = System.getProperty(SslUtil.SSL_TRUST_STORE_PATHS);
|
||||
if (!StringUtilRt.isEmpty(trustStores)) {
|
||||
String[] storesPaths = trustStores.split(File.pathSeparator);
|
||||
for (String path : storesPaths) {
|
||||
String pass = "changeit";
|
||||
char[] chars = new char[pass.length()];
|
||||
pass.getChars(0, pass.length(), chars, 0);
|
||||
appendUserTrustStore(keyStore, path, chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,30 +13,44 @@ import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class SslUtil {
|
||||
public static final String SSL_TRUST_STORE_PATHS = "sslTrustStorePaths";
|
||||
public static final String SSL_CA_CERT_PATH = "sslCaCertPath";
|
||||
public static final String SSL_CLIENT_CERT_PATH = "sslClientCertPath";
|
||||
public static final String SSL_CLIENT_KEY_PATH = "sslClientKeyPath";
|
||||
public static final String SSL_TRUST_EVERYBODY = "sslTrustEverybody";
|
||||
public static final String SSL_USE_FACTORY = "sslUseFactory";
|
||||
private static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
|
||||
private static final String BEGIN_MARK = "-----BEGIN";
|
||||
|
||||
@NotNull
|
||||
public static List<X509Certificate> loadCertificates(@NotNull String caCertPath)
|
||||
throws IOException, CertificateException {
|
||||
String string = FileUtilRt.loadFile(new File(caCertPath));
|
||||
String[] tokens = string.split(END_CERTIFICATE);
|
||||
List<X509Certificate> certs = new ArrayList<>(tokens.length);
|
||||
List<X509Certificate> certs = new ArrayList<>();
|
||||
List<String> tokens = splitBundle(string);
|
||||
for (String token : tokens) {
|
||||
if (token == null || token.trim().length() == 0) continue;
|
||||
certs.add(readCertificate(stringStream(token + END_CERTIFICATE)));
|
||||
if (token == null || token.trim().isEmpty()) continue;
|
||||
certs.add(readCertificate(stringStream(token)));
|
||||
}
|
||||
return certs;
|
||||
}
|
||||
|
||||
private static List<String> splitBundle(@NotNull String string) {
|
||||
int idx = string.indexOf(BEGIN_MARK);
|
||||
if (idx == -1) {
|
||||
return Collections.singletonList(string);
|
||||
}
|
||||
List<String> res = new ArrayList<>();
|
||||
while (idx != -1) {
|
||||
int endIdx = string.indexOf(BEGIN_MARK, idx + BEGIN_MARK.length());
|
||||
res.add(string.substring(idx, endIdx == -1 ? string.length() : endIdx));
|
||||
idx = endIdx;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static InputStream stringStream(@NotNull String str) {
|
||||
return new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
Reference in New Issue
Block a user