mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
store proxy login and password in a separate encrypted file
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -18,10 +18,12 @@ package com.intellij.util.net;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -40,6 +42,7 @@ import com.intellij.util.WaitForProgressToShow;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.proxy.CommonProxy;
|
||||
import com.intellij.util.proxy.JavaProxyProperty;
|
||||
import com.intellij.util.proxy.PropertiesEncryptionSupport;
|
||||
import com.intellij.util.proxy.SharedProxyConfig;
|
||||
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
@@ -59,13 +62,13 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
@State(
|
||||
name = "HttpConfigurable",
|
||||
@@ -76,6 +79,8 @@ import java.util.Set;
|
||||
}
|
||||
)
|
||||
public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable");
|
||||
private static final File PROXY_CREDENTIALS_FILE = new File(PathManager.getOptionsPath(), "proxy.settings.pwd");
|
||||
public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("idea.connection.timeout", 10000);
|
||||
public static final int READ_TIMEOUT = SystemProperties.getIntProperty("idea.read.timeout", 60000);
|
||||
public static final int REDIRECT_LIMIT = SystemProperties.getIntProperty("idea.redirect.limit", 10);
|
||||
@@ -88,8 +93,6 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
public int PROXY_PORT = 80;
|
||||
|
||||
public volatile boolean PROXY_AUTHENTICATION;
|
||||
public volatile String PROXY_LOGIN;
|
||||
public volatile String PROXY_PASSWORD_CRYPT;
|
||||
public boolean KEEP_PROXY_PASSWORD;
|
||||
public transient String LAST_ERROR;
|
||||
|
||||
@@ -101,9 +104,24 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
public String PAC_URL;
|
||||
|
||||
private transient IdeaWideProxySelector mySelector;
|
||||
|
||||
private transient final Object myLock = new Object();
|
||||
|
||||
private transient final PropertiesEncryptionSupport myEncryptionSupport = new PropertiesEncryptionSupport(new SecretKeySpec(new byte[] {
|
||||
(byte)0x50, (byte)0x72, (byte)0x6f, (byte)0x78, (byte)0x79, (byte)0x20, (byte)0x43, (byte)0x6f,
|
||||
(byte)0x6e, (byte)0x66, (byte)0x69, (byte)0x67, (byte)0x20, (byte)0x53, (byte)0x65, (byte)0x63
|
||||
}, "AES"));
|
||||
private transient final NotNullLazyValue<Properties> myProxyCredentials = NotNullLazyValue.createValue(() -> {
|
||||
try {
|
||||
return myEncryptionSupport.load(PROXY_CREDENTIALS_FILE);
|
||||
}
|
||||
catch (FileNotFoundException ignored) {
|
||||
}
|
||||
catch (Throwable th) {
|
||||
LOG.info(th);
|
||||
}
|
||||
return new Properties();
|
||||
});
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public transient Getter<PasswordAuthentication> myTestAuthRunnable = new StaticGetter<PasswordAuthentication>(null);
|
||||
public transient Getter<PasswordAuthentication> myTestGenericAuthRunnable = new StaticGetter<PasswordAuthentication>(null);
|
||||
@@ -123,7 +141,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
HttpConfigurable state = new HttpConfigurable();
|
||||
XmlSerializerUtil.copyBean(this, state);
|
||||
if (!KEEP_PROXY_PASSWORD) {
|
||||
state.PROXY_PASSWORD_CRYPT = null;
|
||||
removeSecure("proxy.password");
|
||||
}
|
||||
correctPasswords(state);
|
||||
return state;
|
||||
@@ -147,7 +165,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
PROXY_PORT = cfg.port;
|
||||
if (cfg.login != null) {
|
||||
setPlainProxyPassword(new String(cfg.password));
|
||||
PROXY_LOGIN = cfg.login;
|
||||
storeSecure("proxy.login", cfg.login);
|
||||
PROXY_AUTHENTICATION = true;
|
||||
KEEP_PROXY_PASSWORD = true;
|
||||
}
|
||||
@@ -196,7 +214,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
public void loadState(@NotNull HttpConfigurable state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
if (!KEEP_PROXY_PASSWORD) {
|
||||
PROXY_PASSWORD_CRYPT = null;
|
||||
removeSecure("proxy.password");
|
||||
}
|
||||
correctPasswords(this);
|
||||
}
|
||||
@@ -233,17 +251,29 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
|
||||
@Transient
|
||||
@Nullable
|
||||
public String getPlainProxyPassword() {
|
||||
return PROXY_PASSWORD_CRYPT == null ? null : decode(PROXY_PASSWORD_CRYPT);
|
||||
public String getProxyLogin() {
|
||||
return getSecure("proxy.login");
|
||||
}
|
||||
|
||||
private static String decode(String value) {
|
||||
return new String(Base64.decode(value), CharsetToolkit.UTF8_CHARSET);
|
||||
@Transient
|
||||
public void setProxyLogin(String login) {
|
||||
storeSecure("proxy.login", login);
|
||||
}
|
||||
|
||||
@Transient
|
||||
@Nullable
|
||||
public String getPlainProxyPassword() {
|
||||
return getSecure("proxy.password");
|
||||
}
|
||||
|
||||
@Transient
|
||||
public void setPlainProxyPassword (String password) {
|
||||
PROXY_PASSWORD_CRYPT = encode(password);
|
||||
storeSecure("proxy.password", password);
|
||||
}
|
||||
|
||||
|
||||
private static String decode(String value) {
|
||||
return new String(Base64.decode(value), CharsetToolkit.UTF8_CHARSET);
|
||||
}
|
||||
|
||||
private static String encode(String password) {
|
||||
@@ -288,8 +318,11 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
return null;
|
||||
}
|
||||
final String password = getPlainProxyPassword();
|
||||
if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password)) {
|
||||
return new PasswordAuthentication(PROXY_LOGIN, password.toCharArray());
|
||||
if (PROXY_AUTHENTICATION) {
|
||||
final String login = getSecure("proxy.login");
|
||||
if (!StringUtil.isEmptyOrSpaces(login) && !StringUtil.isEmptyOrSpaces(password)) {
|
||||
return new PasswordAuthentication(login, password.toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
// do not try to show any dialogs if application is exiting
|
||||
@@ -306,20 +339,35 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
}
|
||||
|
||||
// password might have changed, and the check below is for that
|
||||
String password1 = getPlainProxyPassword();
|
||||
if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password1)) {
|
||||
value[0] = new PasswordAuthentication(PROXY_LOGIN, password1.toCharArray());
|
||||
return;
|
||||
final String password1 = getPlainProxyPassword();
|
||||
if (PROXY_AUTHENTICATION) {
|
||||
final String login = getSecure("proxy.login");
|
||||
if (!StringUtil.isEmptyOrSpaces(login) && !StringUtil.isEmptyOrSpaces(password1)) {
|
||||
value[0] = new PasswordAuthentication(login, password1.toCharArray());
|
||||
return;
|
||||
}
|
||||
}
|
||||
AuthenticationDialog dialog = new AuthenticationDialog(PopupUtil.getActiveComponent(), "Proxy authentication: " + host,
|
||||
"Please enter credentials for: " + prompt, PROXY_LOGIN, "", KEEP_PROXY_PASSWORD);
|
||||
AuthenticationDialog dialog = new AuthenticationDialog(
|
||||
PopupUtil.getActiveComponent(),
|
||||
"Proxy authentication: " + host,
|
||||
"Please enter credentials for: " + prompt,
|
||||
getSecure("proxy.login"),
|
||||
"",
|
||||
KEEP_PROXY_PASSWORD
|
||||
);
|
||||
dialog.show();
|
||||
if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
|
||||
PROXY_AUTHENTICATION = true;
|
||||
AuthenticationPanel panel = dialog.getPanel();
|
||||
KEEP_PROXY_PASSWORD = panel.isRememberPassword();
|
||||
PROXY_LOGIN = StringUtil.nullize(panel.getLogin());
|
||||
setPlainProxyPassword(String.valueOf(panel.getPassword()));
|
||||
final boolean keepPass = panel.isRememberPassword();
|
||||
KEEP_PROXY_PASSWORD = keepPass;
|
||||
storeSecure("proxy.login", StringUtil.nullize(panel.getLogin()));
|
||||
if (keepPass) {
|
||||
setPlainProxyPassword(String.valueOf(panel.getPassword()));
|
||||
}
|
||||
else {
|
||||
removeSecure("proxy.password");
|
||||
}
|
||||
value[0] = new PasswordAuthentication(panel.getLogin(), panel.getPassword());
|
||||
} else {
|
||||
AUTHENTICATION_CANCELLED = true;
|
||||
@@ -462,9 +510,13 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
@NotNull
|
||||
public CredentialsProvider setProxyCredentials(@NotNull CredentialsProvider provider) {
|
||||
if (USE_HTTP_PROXY && PROXY_AUTHENTICATION) {
|
||||
String ntlmUserPassword = PROXY_LOGIN.replace('\\', '/') + ":" + getPlainProxyPassword();
|
||||
String login = getSecure("proxy.login");
|
||||
if (login == null) {
|
||||
login = "";
|
||||
}
|
||||
String ntlmUserPassword = login.replace('\\', '/') + ":" + getPlainProxyPassword();
|
||||
provider.setCredentials(new AuthScope(PROXY_HOST, PROXY_PORT, AuthScope.ANY_REALM, AuthSchemes.NTLM), new NTCredentials(ntlmUserPassword));
|
||||
provider.setCredentials(new AuthScope(PROXY_HOST, PROXY_PORT), new UsernamePasswordCredentials(PROXY_LOGIN, getPlainProxyPassword()));
|
||||
provider.setCredentials(new AuthScope(PROXY_HOST, PROXY_PORT), new UsernamePasswordCredentials(login, getPlainProxyPassword()));
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
@@ -496,12 +548,12 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
}
|
||||
final List<KeyValue<String, String>> result = new ArrayList<KeyValue<String, String>>();
|
||||
if (me.USE_HTTP_PROXY) {
|
||||
final boolean putCredentials = me.KEEP_PROXY_PASSWORD && StringUtil.isNotEmpty(me.PROXY_LOGIN);
|
||||
final boolean putCredentials = me.KEEP_PROXY_PASSWORD && StringUtil.isNotEmpty(me.getProxyLogin());
|
||||
if (me.PROXY_TYPE_IS_SOCKS) {
|
||||
result.add(KeyValue.create(JavaProxyProperty.SOCKS_HOST, me.PROXY_HOST));
|
||||
result.add(KeyValue.create(JavaProxyProperty.SOCKS_PORT, String.valueOf(me.PROXY_PORT)));
|
||||
if (putCredentials) {
|
||||
result.add(KeyValue.create(JavaProxyProperty.SOCKS_USERNAME, me.PROXY_LOGIN));
|
||||
result.add(KeyValue.create(JavaProxyProperty.SOCKS_USERNAME, me.getProxyLogin()));
|
||||
result.add(KeyValue.create(JavaProxyProperty.SOCKS_PASSWORD, me.getPlainProxyPassword()));
|
||||
}
|
||||
} else {
|
||||
@@ -510,7 +562,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
result.add(KeyValue.create(JavaProxyProperty.HTTPS_HOST, me.PROXY_HOST));
|
||||
result.add(KeyValue.create(JavaProxyProperty.HTTPS_PORT, String.valueOf(me.PROXY_PORT)));
|
||||
if (putCredentials) {
|
||||
result.add(KeyValue.create(JavaProxyProperty.HTTP_USERNAME, me.PROXY_LOGIN));
|
||||
result.add(KeyValue.create(JavaProxyProperty.HTTP_USERNAME, me.getProxyLogin()));
|
||||
result.add(KeyValue.create(JavaProxyProperty.HTTP_PASSWORD, me.getPlainProxyPassword()));
|
||||
}
|
||||
}
|
||||
@@ -610,4 +662,47 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
|
||||
myPasswordCrypt = passwordCrypt;
|
||||
}
|
||||
}
|
||||
|
||||
private String getSecure(String key) {
|
||||
try {
|
||||
//return PasswordSafe.getInstance().getPassword(null, HttpConfigurable.class, key);
|
||||
synchronized (myProxyCredentials) {
|
||||
final Properties props = myProxyCredentials.getValue();
|
||||
return props.getProperty(key, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void storeSecure(String key, String value) {
|
||||
try {
|
||||
//PasswordSafe.getInstance().storePassword(null, HttpConfigurable.class, key, value);
|
||||
synchronized (myProxyCredentials) {
|
||||
final Properties props = myProxyCredentials.getValue();
|
||||
props.setProperty(key, value);
|
||||
myEncryptionSupport.store(props, "Proxy Credentials", PROXY_CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSecure(String key) {
|
||||
try {
|
||||
//PasswordSafe.getInstance().removePassword(null, HttpConfigurable.class, key);
|
||||
synchronized (myProxyCredentials) {
|
||||
final Properties props = myProxyCredentials.getValue();
|
||||
props.remove(key);
|
||||
myEncryptionSupport.store(props, "Proxy Credentials", PROXY_CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class HttpProxySettingsUi implements ConfigurableUi<HttpConfigurable> {
|
||||
settings.PROXY_AUTHENTICATION != myProxyAuthCheckBox.isSelected() ||
|
||||
settings.KEEP_PROXY_PASSWORD != myRememberProxyPasswordCheckBox.isSelected() ||
|
||||
settings.PROXY_TYPE_IS_SOCKS != mySocks.isSelected() ||
|
||||
!Comparing.strEqual(settings.PROXY_LOGIN, myProxyLoginTextField.getText()) ||
|
||||
!Comparing.strEqual(settings.getProxyLogin(), myProxyLoginTextField.getText()) ||
|
||||
!Comparing.strEqual(settings.getPlainProxyPassword(), new String(myProxyPasswordTextField.getPassword())) ||
|
||||
settings.PROXY_PORT != myProxyPortTextField.getNumber() ||
|
||||
!Comparing.strEqual(settings.PROXY_HOST, myProxyHostTextField.getText());
|
||||
@@ -231,7 +231,7 @@ class HttpProxySettingsUi implements ConfigurableUi<HttpConfigurable> {
|
||||
|
||||
enableProxy(settings.USE_HTTP_PROXY);
|
||||
|
||||
myProxyLoginTextField.setText(settings.PROXY_LOGIN);
|
||||
myProxyLoginTextField.setText(settings.getProxyLogin());
|
||||
myProxyPasswordTextField.setText(settings.getPlainProxyPassword());
|
||||
|
||||
myProxyPortTextField.setNumber(settings.PROXY_PORT);
|
||||
@@ -312,7 +312,7 @@ class HttpProxySettingsUi implements ConfigurableUi<HttpConfigurable> {
|
||||
settings.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected();
|
||||
settings.KEEP_PROXY_PASSWORD = myRememberProxyPasswordCheckBox.isSelected();
|
||||
|
||||
settings.PROXY_LOGIN = getText(myProxyLoginTextField);
|
||||
settings.setProxyLogin(getText(myProxyLoginTextField));
|
||||
settings.setPlainProxyPassword(new String(myProxyPasswordTextField.getPassword()));
|
||||
settings.PROXY_EXCEPTIONS = StringUtil.nullize(myProxyExceptions.getText(), true);
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.proxy;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 08-Jul-16
|
||||
*/
|
||||
public class PropertiesEncryptionSupport {
|
||||
private final Key myKey;
|
||||
|
||||
public PropertiesEncryptionSupport(Key key) {
|
||||
myKey = key;
|
||||
}
|
||||
|
||||
public PropertiesEncryptionSupport() {
|
||||
this(generateKey());
|
||||
}
|
||||
|
||||
public static Key generateKey() {
|
||||
final byte[] bytes = new byte[16];
|
||||
new SecureRandom().nextBytes(bytes);
|
||||
return new SecretKeySpec(bytes, "AES");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Properties load(@NotNull File file) throws Exception {
|
||||
final byte[] bytes = decrypt(FileUtil.loadFileBytes(file));
|
||||
final Properties props = new Properties();
|
||||
props.load(new ByteArrayInputStream(bytes));
|
||||
return props;
|
||||
}
|
||||
|
||||
public void store(@NotNull Properties props, @NotNull String comments, @NotNull File file) throws Exception {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
props.store(out, comments);
|
||||
out.close();
|
||||
FileUtil.writeToFile(file, encrypt(out.toByteArray()));
|
||||
}
|
||||
|
||||
private byte[] encrypt(byte[] bytes) throws Exception {
|
||||
return encrypt(bytes, myKey);
|
||||
}
|
||||
|
||||
private byte[] decrypt(byte[] bytes) throws Exception {
|
||||
return decrypt(bytes, myKey);
|
||||
}
|
||||
|
||||
private static byte[] encrypt(byte[] msgBytes, Key key) throws Exception {
|
||||
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
ciph.init(Cipher.ENCRYPT_MODE, key);
|
||||
final byte[] body = ciph.doFinal(msgBytes);
|
||||
final byte[] iv = ciph.getIV();
|
||||
|
||||
final byte[] data = new byte[4 + iv.length + body.length];
|
||||
|
||||
final int length = body.length;
|
||||
data[0] = (byte)((length >> 24)& 0xFF);
|
||||
data[1] = (byte)((length >> 16)& 0xFF);
|
||||
data[2] = (byte)((length >> 8)& 0xFF);
|
||||
data[3] = (byte)(length & 0xFF);
|
||||
|
||||
System.arraycopy(iv, 0, data, 4, iv.length);
|
||||
System.arraycopy(body, 0, data, 4 + iv.length, body.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
private static byte[] decrypt(byte[] data, Key key) throws Exception {
|
||||
int bodyLength = data[0] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[1] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[2] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[3] & 0xFF;
|
||||
|
||||
final int ivlength = data.length - 4 - bodyLength;
|
||||
|
||||
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
ciph.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(data, 4, ivlength));
|
||||
return ciph.doFinal(data, 4 + ivlength, bodyLength);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,14 +20,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Properties;
|
||||
|
||||
public class SharedProxyConfig {
|
||||
@@ -36,12 +29,7 @@ public class SharedProxyConfig {
|
||||
private static final String PORT = "port";
|
||||
private static final String LOGIN = "login";
|
||||
private static final String PASSWORD = "password";
|
||||
private static final Key ENCRYPTION_KEY; // the key is valid for the same session only
|
||||
static {
|
||||
final byte[] bytes = new byte[16];
|
||||
new SecureRandom().nextBytes(bytes);
|
||||
ENCRYPTION_KEY = new SecretKeySpec(bytes, "AES");
|
||||
}
|
||||
private static final PropertiesEncryptionSupport ourEncryptionSupport = new PropertiesEncryptionSupport(); // the key is valid for the same session only
|
||||
|
||||
public static final class ProxyParameters {
|
||||
@Nullable
|
||||
@@ -71,9 +59,7 @@ public class SharedProxyConfig {
|
||||
@Nullable
|
||||
public static ProxyParameters load() {
|
||||
try {
|
||||
final byte[] bytes = decrypt(FileUtil.loadFileBytes(CONFIG_FILE));
|
||||
final Properties props = new Properties();
|
||||
props.load(new ByteArrayInputStream(bytes));
|
||||
final Properties props = ourEncryptionSupport.load(CONFIG_FILE);
|
||||
final String password = props.getProperty(PASSWORD, "");
|
||||
return new ProxyParameters(
|
||||
props.getProperty(HOST, null),
|
||||
@@ -97,10 +83,7 @@ public class SharedProxyConfig {
|
||||
props.setProperty(LOGIN, params.login);
|
||||
props.setProperty(PASSWORD, new String(params.password));
|
||||
}
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
props.store(out, "Proxy Configuration");
|
||||
out.close();
|
||||
FileUtil.writeToFile(CONFIG_FILE, encrypt(out.toByteArray()));
|
||||
ourEncryptionSupport.store(props, "Proxy Configuration", CONFIG_FILE);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
@@ -112,44 +95,4 @@ public class SharedProxyConfig {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static byte[] encrypt(byte[] bytes) throws Exception {
|
||||
return encrypt(bytes, ENCRYPTION_KEY);
|
||||
}
|
||||
|
||||
private static byte[] decrypt(byte[] bytes) throws Exception {
|
||||
return decrypt(bytes, ENCRYPTION_KEY);
|
||||
}
|
||||
|
||||
private static byte[] encrypt(byte[] msgBytes, Key key) throws Exception {
|
||||
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
ciph.init(Cipher.ENCRYPT_MODE, key);
|
||||
final byte[] body = ciph.doFinal(msgBytes);
|
||||
final byte[] iv = ciph.getIV();
|
||||
|
||||
final byte[] data = new byte[4 + iv.length + body.length];
|
||||
|
||||
final int length = body.length;
|
||||
data[0] = (byte)((length >> 24)& 0xFF);
|
||||
data[1] = (byte)((length >> 16)& 0xFF);
|
||||
data[2] = (byte)((length >> 8)& 0xFF);
|
||||
data[3] = (byte)(length & 0xFF);
|
||||
|
||||
System.arraycopy(iv, 0, data, 4, iv.length);
|
||||
System.arraycopy(body, 0, data, 4 + iv.length, body.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
private static byte[] decrypt(byte[] data, Key key) throws Exception {
|
||||
int bodyLength = data[0] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[1] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[2] & 0xFF;
|
||||
bodyLength = (bodyLength << 8) + data[3] & 0xFF;
|
||||
|
||||
final int ivlength = data.length - 4 - bodyLength;
|
||||
|
||||
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
ciph.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(data, 4, ivlength));
|
||||
return ciph.doFinal(data, 4 + ivlength, bodyLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class IdeHttpClientHelpers {
|
||||
|
||||
@NotNull
|
||||
private static String getProxyLogin() {
|
||||
return StringUtil.notNullize(getHttpConfigurable().PROXY_LOGIN);
|
||||
return StringUtil.notNullize(getHttpConfigurable().getProxyLogin());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class CloudConfigurationBase<Self extends CloudConfigurationBase<Self>>
|
||||
|
||||
@Override
|
||||
public String getLogin() {
|
||||
return httpConfigurable.PROXY_LOGIN;
|
||||
return httpConfigurable.getProxyLogin();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -496,7 +496,7 @@ public abstract class GitHandler {
|
||||
myEnv.put(GitSSHHandler.SSH_PROXY_AUTHENTICATION_ENV, String.valueOf(proxyAuthentication));
|
||||
|
||||
if (proxyAuthentication) {
|
||||
myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.PROXY_LOGIN));
|
||||
myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.getProxyLogin()));
|
||||
myEnv.put(GitSSHHandler.SSH_PROXY_PASSWORD_ENV, StringUtil.notNullize(httpConfigurable.getPlainProxyPassword()));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -589,9 +589,9 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
|
||||
extraJvmArgs.add(KeyValue.create("https.nonProxyHosts", nonProxyHosts));
|
||||
}
|
||||
}
|
||||
if (httpConfigurable.USE_HTTP_PROXY && StringUtil.isNotEmpty(httpConfigurable.PROXY_LOGIN)) {
|
||||
extraJvmArgs.add(KeyValue.create("http.proxyUser", httpConfigurable.PROXY_LOGIN));
|
||||
extraJvmArgs.add(KeyValue.create("https.proxyUser", httpConfigurable.PROXY_LOGIN));
|
||||
if (httpConfigurable.USE_HTTP_PROXY && StringUtil.isNotEmpty(httpConfigurable.getProxyLogin())) {
|
||||
extraJvmArgs.add(KeyValue.create("http.proxyUser", httpConfigurable.getProxyLogin()));
|
||||
extraJvmArgs.add(KeyValue.create("https.proxyUser", httpConfigurable.getProxyLogin()));
|
||||
final String plainProxyPassword = httpConfigurable.getPlainProxyPassword();
|
||||
extraJvmArgs.add(KeyValue.create("http.proxyPassword", plainProxyPassword));
|
||||
extraJvmArgs.add(KeyValue.create("https.proxyPassword", plainProxyPassword));
|
||||
|
||||
@@ -346,7 +346,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
|
||||
Proxy proxyToRelease = null;
|
||||
if (! interactive && configuration.isIsUseDefaultProxy()) {
|
||||
final HttpConfigurable instance = HttpConfigurable.getInstance();
|
||||
if (instance.USE_HTTP_PROXY && instance.PROXY_AUTHENTICATION && (StringUtil.isEmptyOrSpaces(instance.PROXY_LOGIN) ||
|
||||
if (instance.USE_HTTP_PROXY && instance.PROXY_AUTHENTICATION && (StringUtil.isEmptyOrSpaces(instance.getProxyLogin()) ||
|
||||
StringUtil.isEmptyOrSpaces(instance.getPlainProxyPassword()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public abstract class BaseRepositoryImpl extends BaseRepository {
|
||||
client.getHostConfiguration().setProxy(proxy.PROXY_HOST, proxy.PROXY_PORT);
|
||||
if (proxy.PROXY_AUTHENTICATION) {
|
||||
AuthScope authScope = new AuthScope(proxy.PROXY_HOST, proxy.PROXY_PORT);
|
||||
Credentials credentials = getCredentials(proxy.PROXY_LOGIN, proxy.getPlainProxyPassword(), proxy.PROXY_HOST);
|
||||
Credentials credentials = getCredentials(proxy.getProxyLogin(), proxy.getPlainProxyPassword(), proxy.PROXY_HOST);
|
||||
client.getState().setProxyCredentials(authScope, credentials);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
if (settings != null && settings.USE_HTTP_PROXY) {
|
||||
final String credentials;
|
||||
if (settings.PROXY_AUTHENTICATION) {
|
||||
credentials = String.format("%s:%s@", settings.PROXY_LOGIN, settings.getPlainProxyPassword());
|
||||
credentials = String.format("%s:%s@", settings.getProxyLogin(), settings.getPlainProxyPassword());
|
||||
}
|
||||
else {
|
||||
credentials = "";
|
||||
|
||||
Reference in New Issue
Block a user