SVN: prompt if any of "config" or "servers" files properties prevent authentication credentials from being stored

(cherry picked from commit f458405c00f76bda6659f077a55c46bd69baa562)
This commit is contained in:
irengrig
2010-07-14 16:18:52 +04:00
parent e04b0ff189
commit 42404f3339
4 changed files with 146 additions and 20 deletions
@@ -18,17 +18,20 @@ package org.jetbrains.idea.svn;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier;
import com.intellij.util.containers.SoftHashMap;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.Nullable;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.auth.ISVNProxyManager;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.internal.wc.SVNConfigFile;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.io.SVNRepository;
import java.io.File;
@@ -41,13 +44,15 @@ import java.util.StringTokenizer;
*/
public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager {
private final Project myProject;
private final File myConfigDirectory;
private PersistentAuthenticationProviderProxy myPersistentAuthenticationProviderProxy;
private SvnConfiguration myConfig;
public SvnAuthenticationManager(final Project project, final File configDirectory) {
super(configDirectory, true, null, null);
myProject = project;
myConfig = SvnConfiguration.getInstance(myProject);
myConfigDirectory = configDirectory;
myConfig = SvnConfiguration.getInstance(myProject);
if (myPersistentAuthenticationProviderProxy != null) {
myPersistentAuthenticationProviderProxy.setProject(myProject);
}
@@ -317,4 +322,115 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager {
return SvnAuthEquals.hashCode(getT());
}
}
private void setPropertyForHost(final String host, final String property, final String value) {
final SVNConfigFile userConfig = new SVNConfigFile(new File(myConfigDirectory, "servers"));
String groupName = getGroupName(userConfig.getProperties("groups"), host);
if (groupName != null) {
userConfig.setPropertyValue(groupName, property, value, true);
} else {
final SVNConfigFile systemConfig = new SVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), "servers"));
final String systemGroupName = getGroupName(systemConfig.getProperties("groups"), host);
if (systemGroupName != null) {
systemConfig.setPropertyValue(systemGroupName, property, value, true);
} else {
// global
userConfig.setPropertyValue("global", property, value, true);
}
}
}
// default = yes
private boolean isTurned(final String value) {
return value == null || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
}
@Nullable
protected Boolean isAuthStorageEnabledMy(SVNURL url) {
String host = url != null ? url.getHost() : null;
Map properties = getHostProperties(host);
String storeAuthCreds = (String) properties.get("store-auth-creds");
if (storeAuthCreds == null) {
return null;
}
return "yes".equalsIgnoreCase(storeAuthCreds) || "on".equalsIgnoreCase(storeAuthCreds) || "true".equalsIgnoreCase(storeAuthCreds);
}
public boolean checkContinueSaveCredentials(final SVNAuthentication auth, final String kind, final String realm) {
final SVNURL url = auth.getURL();
//final SVNConfigFile userConfig = new SVNConfigFile(new File(myConfigDirectory, "config"));
final boolean authStorageEnabled = isAuthStorageEnabled(url);
final String storeCredentials = getConfigFile().getPropertyValue("auth", "store-auth-creds");
if ((Boolean.FALSE.equals(isAuthStorageEnabledMy(url))) || (! isTurned(storeCredentials))) {
//userConfig.setPropertyValue("auth", "store-auth-creds", "yes", true);
ChangesViewBalloonProblemNotifier.showMe(myProject, "Cannot store credentials: forbidden by \"store-auth-creds\"=\"no\"", MessageType.ERROR);
return false;
}
final boolean passwordStorageEnabled = isStorePasswords(url);
// check can store
final String storePasswords = getConfigFile().getPropertyValue("auth", "store-passwords");
if ((! ISVNAuthenticationManager.SSL.equals(kind)) && (! passwordStorageEnabled)) {
// but it should be
//userConfig.setPropertyValue("auth", "store-passwords", "yes", true);
ChangesViewBalloonProblemNotifier.showMe(myProject, "Cannot store password: forbidden by \"store-passwords\"=\"no\"", MessageType.ERROR);
return false;
}
if (ISVNAuthenticationManager.SSL.equals(kind) && (! isStoreSSLClientCertificatePassphrases(url))) {
//setPropertyForHost(url.getHost(), "store-ssl-client-cert-pp", "yes");
ChangesViewBalloonProblemNotifier.showMe(myProject, "Cannot store passphrase: forbidden by \"store-ssl-client-cert-pp\"=\"no\"", MessageType.ERROR);
return false;
}
// check can encrypt
if (! SystemInfo.isWindows) {
if (ISVNAuthenticationManager.SSL.equals(kind)) {
try {
if (! isStorePlainTextPassphrases(realm, auth)) {
final SVNSSLAuthentication svnsslAuthentication = (SVNSSLAuthentication)auth;
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
Messages.showWarningDialog(myProject, "Your passphrase for client certificate:\n\n" +
svnsslAuthentication.getCertificateFile().getPath() +
"\n\ncan only be stored to disk unencrypted. (Encryption is not supported)\n\n" +
"But storage in plain text is not allowed.\nTo allow plain text passphrases caching, set \"store-ssl-client-cert-pp-plaintext\"=\"yes\"",
"Cannot save passphrase");
}
});
/*ChangesViewBalloonProblemNotifier.showMe(myProject, "Your passphrase for client certificate:\n" +
svnsslAuthentication.getCertificateFile().getPath() +
"\ncan only be stored to disk unencrypted! (Encryption is not supported)\n" +
"But storage in plain text is not allowed.\nTo allow plain text passphrases caching, set \"store-ssl-client-cert-pp-plaintext\"=\"yes\"", MessageType.ERROR);*/
return false;
}
}
catch (SVNException e) {
// should not occur, anyway means not allowed
}
} else {
try {
if (! isStorePlainTextPasswords(realm, auth)) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
Messages.showWarningDialog(myProject, "Your password for authentication realm:\n\n" + realm +
"\n\ncan only be stored to disk unencrypted. (Encryption is not supported)\n\n" +
"But storage in plain text is not allowed.\nTo allow plain text passwords caching, set \"store-plaintext-passwords\"=\"yes\"",
"Cannot save password");
}
});
/*ChangesViewBalloonProblemNotifier.showMe(myProject, "Your password for authentication realm:\n" + realm +
"\ncan only be stored to disk unencrypted! (Encryption is not supported)\n" +
"But storage in plain text is not allowed.\nTo allow plain text passwords caching, set \"store-plaintext-passwords\"=\"yes\"", MessageType.ERROR);*/
return false;
}
}
catch (SVNException e) {
//
}
}
}
return true;
}
}
@@ -216,11 +216,11 @@ public class SvnConfiguration implements ProjectComponent, JDOMExternalizable {
return myOptions;
}
public ISVNAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
if (myAuthManager == null) {
// reloaded when configuration directory changes
myAuthManager = new SvnAuthenticationManager(myProject, new File(getConfigurationDirectory()));
myAuthManager.setAuthenticationProvider(new SvnAuthenticationProvider(svnVcs));
myAuthManager.setAuthenticationProvider(new SvnAuthenticationProvider(svnVcs, myInteractiveManager));
myAuthManager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
}
return myAuthManager;
@@ -234,11 +234,11 @@ public class SvnConfiguration implements ProjectComponent, JDOMExternalizable {
return myPassiveAuthManager;
}
public ISVNAuthenticationManager getInteractiveManager(final SvnVcs svnVcs) {
public SvnAuthenticationManager getInteractiveManager(final SvnVcs svnVcs) {
if (myInteractiveManager == null) {
myInteractiveManager = new SvnAuthenticationManager(myProject, new File(getConfigurationDirectory()));
myInteractiveManager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
myInteractiveManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(svnVcs));
myInteractiveManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(svnVcs, myInteractiveManager));
}
return myInteractiveManager;
}
@@ -20,14 +20,16 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.ui.GuiUtils;
import com.intellij.util.SystemProperties;
import org.jetbrains.idea.svn.SvnAuthenticationManager;
import org.jetbrains.idea.svn.SvnAuthenticationNotifier;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.auth.SVNUserNameAuthentication;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.X509Certificate;
@@ -40,10 +42,10 @@ public class SvnAuthenticationProvider implements ISVNAuthenticationProvider {
private final SvnAuthenticationNotifier myAuthenticationNotifier;
private final SvnInteractiveAuthenticationProvider mySvnInteractiveAuthenticationProvider;
public SvnAuthenticationProvider(final SvnVcs svnVcs) {
public SvnAuthenticationProvider(final SvnVcs svnVcs, final SvnAuthenticationManager manager) {
myProject = svnVcs.getProject();
myAuthenticationNotifier = svnVcs.getAuthNotifier();
mySvnInteractiveAuthenticationProvider = new SvnInteractiveAuthenticationProvider(svnVcs);
mySvnInteractiveAuthenticationProvider = new SvnInteractiveAuthenticationProvider(svnVcs, manager);
}
private void log(final String s) {
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.ui.GuiUtils;
import com.intellij.util.SystemProperties;
import org.jetbrains.idea.svn.SvnAuthenticationManager;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
@@ -35,9 +36,11 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
private final Project myProject;
private static final ThreadLocal<MyCallState> myCallState = new ThreadLocal<MyCallState>();
private final SvnVcs myVcs;
private final SvnAuthenticationManager myManager;
public SvnInteractiveAuthenticationProvider(final SvnVcs vcs) {
public SvnInteractiveAuthenticationProvider(final SvnVcs vcs, SvnAuthenticationManager manager) {
myVcs = vcs;
myManager = manager;
myProject = vcs.getProject();
}
@@ -83,7 +86,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
}
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNPasswordAuthentication(dialog.getUserName(), dialog.getPassword(), dialog.isSaveAllowed());
result[0] = new SVNPasswordAuthentication(dialog.getUserName(), dialog.getPassword(), dialog.isSaveAllowed(), url, false);
}
}
};
@@ -104,7 +107,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
}
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNUserNameAuthentication(dialog.getUserName(), dialog.isSaveAllowed());
result[0] = new SVNUserNameAuthentication(dialog.getUserName(), dialog.isSaveAllowed(), url, false);
}
}
};
@@ -129,10 +132,11 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
passphrase = null;
}
result[0] =
new SVNSSHAuthentication(dialog.getUserName(), new File(dialog.getKeyFile()), passphrase, port, dialog.isSaveAllowed());
new SVNSSHAuthentication(dialog.getUserName(), new File(dialog.getKeyFile()), passphrase, port, dialog.isSaveAllowed(),
url, false);
}
else {
result[0] = new SVNSSHAuthentication(dialog.getUserName(), dialog.getPassword(), port, dialog.isSaveAllowed());
result[0] = new SVNSSHAuthentication(dialog.getUserName(), dialog.getPassword(), port, dialog.isSaveAllowed(), url, false);
}
}
}
@@ -150,7 +154,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNSSLAuthentication(new File(dialog.getCertificatePath()), String.valueOf(dialog.getCertificatePassword()),
dialog.getSaveAuth());
dialog.getSaveAuth(), url, false);
}
}
};
@@ -168,7 +172,11 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
}
log("3 authentication result: " + result[0]);
}
callState.setWasCancelled(result[0] == null);
final boolean wasCanceled = result[0] == null;
callState.setWasCancelled(wasCanceled);
if ((! wasCanceled) && (ISVNAuthenticationManager.USERNAME != kind) && (result[0].isStorageAllowed())) {
myManager.checkContinueSaveCredentials(result[0], kind, realm);
}
return result[0];
}