mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
svn: Refactored IdeaSvnkitBasedAuthenticationCallback - inner classes moved to separate files
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.idea.svn.auth;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnConfiguration;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNErrorMessage;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.auth.*;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
abstract class AbstractAuthenticator {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(AbstractAuthenticator.class);
|
||||
|
||||
@NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService;
|
||||
@NotNull protected final SvnVcs myVcs;
|
||||
@NotNull protected final SVNURL myUrl;
|
||||
protected final String myRealm;
|
||||
protected boolean myStoreInUsual;
|
||||
protected SvnAuthenticationManager myTmpDirManager;
|
||||
|
||||
AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) {
|
||||
myAuthService = authService;
|
||||
myVcs = myAuthService.getVcs();
|
||||
myUrl = url;
|
||||
myRealm = realm;
|
||||
}
|
||||
|
||||
protected boolean tryAuthenticate() {
|
||||
final SvnAuthenticationManager passive = myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject());
|
||||
final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs);
|
||||
|
||||
try {
|
||||
boolean authenticated = getWithPassive(passive) || getWithActive(active);
|
||||
if (!authenticated) return false;
|
||||
|
||||
SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager();
|
||||
manager.setArtificialSaving(true);
|
||||
return acknowledge(manager);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
|
||||
return false;
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.info(e);
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected SvnAuthenticationManager createTmpManager() throws IOException {
|
||||
if (myTmpDirManager == null) {
|
||||
myAuthService.initTmpDir(myVcs.getSvnConfiguration());
|
||||
myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory());
|
||||
myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE);
|
||||
myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager));
|
||||
}
|
||||
|
||||
return myTmpDirManager;
|
||||
}
|
||||
|
||||
protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException {
|
||||
MessageBusConnection connection = null;
|
||||
try {
|
||||
final Project project = myVcs.getProject();
|
||||
connection = project.getMessageBus().connect(project);
|
||||
connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, new MyAuthenticationProviderListener());
|
||||
|
||||
makeAuthCall(active);
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return afterAuthCall();
|
||||
}
|
||||
|
||||
protected void makeAuthCall(@NotNull SvnAuthenticationManager manager) throws SVNException {
|
||||
myVcs.createWCClient(manager).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
}
|
||||
|
||||
protected void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) {
|
||||
}
|
||||
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
}
|
||||
|
||||
protected abstract boolean afterAuthCall();
|
||||
|
||||
protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException;
|
||||
|
||||
protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException;
|
||||
|
||||
private class MyAuthenticationProviderListener implements SvnAuthenticationManager.ISVNAuthenticationProviderListener {
|
||||
@Override
|
||||
public void requestClientAuthentication(String kind,
|
||||
SVNURL url,
|
||||
String realm,
|
||||
SVNErrorMessage errorMessage,
|
||||
SVNAuthentication previousAuth,
|
||||
boolean authMayBeStored,
|
||||
SVNAuthentication authentication) {
|
||||
AbstractAuthenticator.this.requestClientAuthentication(url, realm, authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptServerAuthentication(SVNURL url,
|
||||
String realm,
|
||||
Object certificate,
|
||||
boolean resultMayBeStored,
|
||||
@MagicConstant int acceptResult) {
|
||||
AbstractAuthenticator.this.acceptServerAuthentication(url, realm, certificate, acceptResult);
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean storeCredentials(@NotNull SvnAuthenticationManager manager, final SVNAuthentication authentication, String realm)
|
||||
throws SVNException {
|
||||
try {
|
||||
if (authentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication)authentication).getCertificateFile() != null)) {
|
||||
manager.acknowledgeForSSL(true, authentication);
|
||||
realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath();
|
||||
}
|
||||
manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL());
|
||||
}
|
||||
catch (SvnAuthenticationManager.CredentialsSavedException e) {
|
||||
return e.isSuccess();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getFromType(SVNAuthentication authentication) {
|
||||
if (authentication instanceof SVNPasswordAuthentication) {
|
||||
return ISVNAuthenticationManager.PASSWORD;
|
||||
}
|
||||
if (authentication instanceof SVNSSHAuthentication) {
|
||||
return ISVNAuthenticationManager.SSH;
|
||||
}
|
||||
if (authentication instanceof SVNSSLAuthentication) {
|
||||
return ISVNAuthenticationManager.SSL;
|
||||
}
|
||||
if (authentication instanceof SVNUserNameAuthentication) {
|
||||
return ISVNAuthenticationManager.USERNAME;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.idea.svn.auth;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNCancelException;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
|
||||
import org.tmatesoft.svn.core.auth.SVNAuthentication;
|
||||
import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication;
|
||||
import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
class CredentialsAuthenticator extends AbstractAuthenticator {
|
||||
private String myKind;
|
||||
// sometimes realm string is different (with <>), so store credentials for both strings..
|
||||
private String myRealm2;
|
||||
private SVNAuthentication myAuthentication;
|
||||
|
||||
CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService,
|
||||
@NotNull SVNURL url,
|
||||
@Nullable String realm) {
|
||||
super(authService, url, realm == null ? url.getHost() : realm);
|
||||
}
|
||||
|
||||
public boolean tryAuthenticate(boolean passwordRequest) {
|
||||
final List<String> kinds = IdeaSvnkitBasedAuthenticationCallback.getKinds(myUrl, passwordRequest);
|
||||
for (String kind : kinds) {
|
||||
myKind = kind;
|
||||
if (!tryAuthenticate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException {
|
||||
myAuthentication = getWithPassiveImpl(passive);
|
||||
if (myAuthentication != null && !checkAuthOk(myAuthentication)) {
|
||||
myAuthService.clearPassiveCredentials(myRealm, myUrl,
|
||||
myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath
|
||||
myAuthentication = null;
|
||||
}
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException {
|
||||
try {
|
||||
return passive.getFirstAuthentication(myKind, myRealm, myUrl);
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAuthOk(SVNAuthentication authentication) {
|
||||
if (authentication instanceof SVNPasswordAuthentication && StringUtil.isEmptyOrSpaces(authentication.getUserName())) return false;
|
||||
if (authentication instanceof SVNSSLAuthentication) {
|
||||
if (StringUtil.isEmptyOrSpaces(((SVNSSLAuthentication)authentication).getPassword())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException {
|
||||
if (ISVNAuthenticationManager.SSL.equals(myKind)) {
|
||||
if (super.getWithActive(active)) return true;
|
||||
}
|
||||
myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true);
|
||||
myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed();
|
||||
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myAuthentication = authentication;
|
||||
myRealm2 = realm;
|
||||
myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean afterAuthCall() {
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException {
|
||||
if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) {
|
||||
storeCredentials(manager, myAuthentication, myRealm2);
|
||||
}
|
||||
return storeCredentials(manager, myAuthentication, myRealm);
|
||||
}
|
||||
}
|
||||
+1
-371
@@ -17,21 +17,16 @@ package org.jetbrains.idea.svn.auth;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.util.PopupUtil;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.net.HttpConfigurable;
|
||||
import com.intellij.util.proxy.CommonProxy;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
@@ -41,18 +36,10 @@ import org.jetbrains.idea.svn.commandLine.AuthenticationCallback;
|
||||
import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.auth.*;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNBase64;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNHashMap;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNSSLUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNWCProperties;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.security.cert.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -290,348 +277,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class AbstractAuthenticator {
|
||||
@NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService;
|
||||
@NotNull protected final SvnVcs myVcs;
|
||||
@NotNull protected final SVNURL myUrl;
|
||||
protected final String myRealm;
|
||||
protected boolean myStoreInUsual;
|
||||
protected SvnAuthenticationManager myTmpDirManager;
|
||||
|
||||
protected AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) {
|
||||
myAuthService = authService;
|
||||
myVcs = myAuthService.getVcs();
|
||||
myUrl = url;
|
||||
myRealm = realm;
|
||||
}
|
||||
|
||||
protected boolean tryAuthenticate() {
|
||||
final SvnAuthenticationManager passive = myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject());
|
||||
final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs);
|
||||
|
||||
try {
|
||||
boolean authenticated = getWithPassive(passive) || getWithActive(active);
|
||||
if (!authenticated) return false;
|
||||
|
||||
SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager();
|
||||
manager.setArtificialSaving(true);
|
||||
return acknowledge(manager);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
|
||||
return false;
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.info(e);
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected SvnAuthenticationManager createTmpManager() throws IOException {
|
||||
if (myTmpDirManager == null) {
|
||||
myAuthService.initTmpDir(myVcs.getSvnConfiguration());
|
||||
myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory());
|
||||
myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE);
|
||||
myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager));
|
||||
}
|
||||
|
||||
return myTmpDirManager;
|
||||
}
|
||||
|
||||
protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException {
|
||||
MessageBusConnection connection = null;
|
||||
try {
|
||||
final Project project = myVcs.getProject();
|
||||
connection = project.getMessageBus().connect(project);
|
||||
connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, new MyAuthenticationProviderListener());
|
||||
|
||||
makeAuthCall(active);
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return afterAuthCall();
|
||||
}
|
||||
|
||||
protected void makeAuthCall(@NotNull SvnAuthenticationManager manager) throws SVNException {
|
||||
myVcs.createWCClient(manager).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
}
|
||||
|
||||
protected void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) {
|
||||
}
|
||||
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
}
|
||||
|
||||
protected abstract boolean afterAuthCall();
|
||||
|
||||
protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException;
|
||||
|
||||
protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException;
|
||||
|
||||
private class MyAuthenticationProviderListener implements SvnAuthenticationManager.ISVNAuthenticationProviderListener {
|
||||
@Override
|
||||
public void requestClientAuthentication(String kind,
|
||||
SVNURL url,
|
||||
String realm,
|
||||
SVNErrorMessage errorMessage,
|
||||
SVNAuthentication previousAuth,
|
||||
boolean authMayBeStored,
|
||||
SVNAuthentication authentication) {
|
||||
AbstractAuthenticator.this.requestClientAuthentication(url, realm, authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptServerAuthentication(SVNURL url,
|
||||
String realm,
|
||||
Object certificate,
|
||||
boolean resultMayBeStored,
|
||||
@MagicConstant int acceptResult) {
|
||||
AbstractAuthenticator.this.acceptServerAuthentication(url, realm, certificate, acceptResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// plus seems that we also should ask for credentials; but we didn't receive realm name yet
|
||||
private static class SSLServerCertificateAuthenticator extends AbstractAuthenticator {
|
||||
private String myCertificateRealm;
|
||||
private String myCredentialsRealm;
|
||||
private Object myCertificate;
|
||||
private int myResult;
|
||||
private SVNAuthentication myAuthentication;
|
||||
|
||||
protected SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService,
|
||||
@NotNull SVNURL url,
|
||||
String realm) {
|
||||
super(authService, url, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAuthenticate() {
|
||||
myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
|
||||
myStoreInUsual = false;
|
||||
return super.tryAuthenticate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException {
|
||||
String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
|
||||
if (stored == null) return false;
|
||||
|
||||
myCertificate = createCertificate(stored);
|
||||
myCertificateRealm = myRealm;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myCredentialsRealm = realm;
|
||||
myAuthentication = authentication;
|
||||
if (myAuthentication != null) {
|
||||
myStoreInUsual &= myAuthentication.isStorageAllowed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myCertificateRealm = realm;
|
||||
myCertificate = certificate;
|
||||
myResult = acceptResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean afterAuthCall() {
|
||||
myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult;
|
||||
// TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate().
|
||||
// TODO: This was most likely error in code - check once again.
|
||||
return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException {
|
||||
// we should store certificate, if it wasn't accepted (if temporally tmp)
|
||||
if (myCertificate == null) { // this is if certificate was stored only in passive area
|
||||
String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
|
||||
if (StringUtil.isEmptyOrSpaces(stored)) {
|
||||
throw new SVNException(
|
||||
SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime"));
|
||||
}
|
||||
myCertificate = createCertificate(stored);
|
||||
myCertificateRealm = myRealm;
|
||||
}
|
||||
if (myAuthService.getTempDirectory() != null && myCertificate != null) {
|
||||
storeServerCertificate();
|
||||
|
||||
if (myAuthentication != null) {
|
||||
final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm;
|
||||
return storeCredentials(manager, myAuthentication, realm);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Certificate createCertificate(@NotNull String stored) throws SVNException {
|
||||
CertificateFactory factory;
|
||||
try {
|
||||
factory = CertificateFactory.getInstance("X509");
|
||||
final byte[] buffer = new byte[stored.length()];
|
||||
SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer);
|
||||
|
||||
return factory.generateCertificate(new ByteArrayInputStream(buffer));
|
||||
}
|
||||
catch (CertificateException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e));
|
||||
}
|
||||
}
|
||||
|
||||
private void storeServerCertificate() throws SVNException {
|
||||
if (!(myCertificate instanceof X509Certificate)) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate));
|
||||
}
|
||||
X509Certificate x509Certificate = (X509Certificate)myCertificate;
|
||||
String stored;
|
||||
try {
|
||||
stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded());
|
||||
}
|
||||
catch (CertificateEncodingException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e));
|
||||
}
|
||||
|
||||
int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost());
|
||||
storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures);
|
||||
}
|
||||
|
||||
private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
configDir.mkdirs();
|
||||
|
||||
File file = new File(configDir, "auth/svn.ssl.server/" + SVNFileUtil.computeChecksum(realm));
|
||||
SVNHashMap map = new SVNHashMap();
|
||||
map.put("ascii_cert", data);
|
||||
map.put("svn:realmstring", realm);
|
||||
map.put("failures", Integer.toString(failures));
|
||||
|
||||
SVNFileUtil.deleteFile(file);
|
||||
|
||||
File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true);
|
||||
try {
|
||||
SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR);
|
||||
}
|
||||
finally {
|
||||
SVNFileUtil.deleteFile(tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean storeCredentials(@NotNull SvnAuthenticationManager manager, final SVNAuthentication authentication, String realm)
|
||||
throws SVNException {
|
||||
try {
|
||||
if (authentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication)authentication).getCertificateFile() != null)) {
|
||||
manager.acknowledgeForSSL(true, authentication);
|
||||
realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath();
|
||||
}
|
||||
manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL());
|
||||
}
|
||||
catch (SvnAuthenticationManager.CredentialsSavedException e) {
|
||||
return e.isSuccess();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class CredentialsAuthenticator extends AbstractAuthenticator {
|
||||
private String myKind;
|
||||
// sometimes realm string is different (with <>), so store credentials for both strings..
|
||||
private String myRealm2;
|
||||
private SVNAuthentication myAuthentication;
|
||||
|
||||
protected CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService,
|
||||
@NotNull SVNURL url,
|
||||
@Nullable String realm) {
|
||||
super(authService, url, realm == null ? url.getHost() : realm);
|
||||
}
|
||||
|
||||
public boolean tryAuthenticate(boolean passwordRequest) {
|
||||
final List<String> kinds = getKinds(myUrl, passwordRequest);
|
||||
for (String kind : kinds) {
|
||||
myKind = kind;
|
||||
if (!tryAuthenticate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException {
|
||||
myAuthentication = getWithPassiveImpl(passive);
|
||||
if (myAuthentication != null && !checkAuthOk(myAuthentication)) {
|
||||
myAuthService.clearPassiveCredentials(myRealm, myUrl,
|
||||
myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath
|
||||
myAuthentication = null;
|
||||
}
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException {
|
||||
try {
|
||||
return passive.getFirstAuthentication(myKind, myRealm, myUrl);
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAuthOk(SVNAuthentication authentication) {
|
||||
if (authentication instanceof SVNPasswordAuthentication && StringUtil.isEmptyOrSpaces(authentication.getUserName())) return false;
|
||||
if (authentication instanceof SVNSSLAuthentication) {
|
||||
if (StringUtil.isEmptyOrSpaces(((SVNSSLAuthentication)authentication).getPassword())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException {
|
||||
if (ISVNAuthenticationManager.SSL.equals(myKind)) {
|
||||
if (super.getWithActive(active)) return true;
|
||||
}
|
||||
myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true);
|
||||
myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed();
|
||||
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myAuthentication = authentication;
|
||||
myRealm2 = realm;
|
||||
myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean afterAuthCall() {
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException {
|
||||
if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) {
|
||||
storeCredentials(manager, myAuthentication, myRealm2);
|
||||
}
|
||||
return storeCredentials(manager, myAuthentication, myRealm);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<String> getKinds(final SVNURL url, boolean passwordRequest) {
|
||||
public static List<String> getKinds(final SVNURL url, boolean passwordRequest) {
|
||||
if (passwordRequest || "http".equals(url.getProtocol())) {
|
||||
return Collections.singletonList(ISVNAuthenticationManager.PASSWORD);
|
||||
}
|
||||
@@ -659,21 +306,4 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall
|
||||
FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getFromType(SVNAuthentication authentication) {
|
||||
if (authentication instanceof SVNPasswordAuthentication) {
|
||||
return ISVNAuthenticationManager.PASSWORD;
|
||||
}
|
||||
if (authentication instanceof SVNSSHAuthentication) {
|
||||
return ISVNAuthenticationManager.SSH;
|
||||
}
|
||||
if (authentication instanceof SVNSSLAuthentication) {
|
||||
return ISVNAuthenticationManager.SSL;
|
||||
}
|
||||
if (authentication instanceof SVNUserNameAuthentication) {
|
||||
return ISVNAuthenticationManager.USERNAME;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.idea.svn.auth;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
|
||||
import org.tmatesoft.svn.core.auth.SVNAuthentication;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNBase64;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNHashMap;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNSSLUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNWCProperties;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.security.cert.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/ // plus seems that we also should ask for credentials; but we didn't receive realm name yet
|
||||
class SSLServerCertificateAuthenticator extends AbstractAuthenticator {
|
||||
private String myCertificateRealm;
|
||||
private String myCredentialsRealm;
|
||||
private Object myCertificate;
|
||||
private int myResult;
|
||||
private SVNAuthentication myAuthentication;
|
||||
|
||||
SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService,
|
||||
@NotNull SVNURL url,
|
||||
String realm) {
|
||||
super(authService, url, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAuthenticate() {
|
||||
myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
|
||||
myStoreInUsual = false;
|
||||
return super.tryAuthenticate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException {
|
||||
String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
|
||||
if (stored == null) return false;
|
||||
|
||||
myCertificate = createCertificate(stored);
|
||||
myCertificateRealm = myRealm;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myCredentialsRealm = realm;
|
||||
myAuthentication = authentication;
|
||||
if (myAuthentication != null) {
|
||||
myStoreInUsual &= myAuthentication.isStorageAllowed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) {
|
||||
if (!myUrl.equals(url)) return;
|
||||
myCertificateRealm = realm;
|
||||
myCertificate = certificate;
|
||||
myResult = acceptResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean afterAuthCall() {
|
||||
myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult;
|
||||
// TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate().
|
||||
// TODO: This was most likely error in code - check once again.
|
||||
return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException {
|
||||
// we should store certificate, if it wasn't accepted (if temporally tmp)
|
||||
if (myCertificate == null) { // this is if certificate was stored only in passive area
|
||||
String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
|
||||
if (StringUtil.isEmptyOrSpaces(stored)) {
|
||||
throw new SVNException(
|
||||
SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime"));
|
||||
}
|
||||
myCertificate = createCertificate(stored);
|
||||
myCertificateRealm = myRealm;
|
||||
}
|
||||
if (myAuthService.getTempDirectory() != null && myCertificate != null) {
|
||||
storeServerCertificate();
|
||||
|
||||
if (myAuthentication != null) {
|
||||
final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm;
|
||||
return storeCredentials(manager, myAuthentication, realm);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Certificate createCertificate(@NotNull String stored) throws SVNException {
|
||||
CertificateFactory factory;
|
||||
try {
|
||||
factory = CertificateFactory.getInstance("X509");
|
||||
final byte[] buffer = new byte[stored.length()];
|
||||
SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer);
|
||||
|
||||
return factory.generateCertificate(new ByteArrayInputStream(buffer));
|
||||
}
|
||||
catch (CertificateException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e));
|
||||
}
|
||||
}
|
||||
|
||||
private void storeServerCertificate() throws SVNException {
|
||||
if (!(myCertificate instanceof X509Certificate)) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate));
|
||||
}
|
||||
X509Certificate x509Certificate = (X509Certificate)myCertificate;
|
||||
String stored;
|
||||
try {
|
||||
stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded());
|
||||
}
|
||||
catch (CertificateEncodingException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e));
|
||||
}
|
||||
|
||||
int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost());
|
||||
storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures);
|
||||
}
|
||||
|
||||
private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
configDir.mkdirs();
|
||||
|
||||
File file = new File(configDir, "auth/svn.ssl.server/" + SVNFileUtil.computeChecksum(realm));
|
||||
SVNHashMap map = new SVNHashMap();
|
||||
map.put("ascii_cert", data);
|
||||
map.put("svn:realmstring", realm);
|
||||
map.put("failures", Integer.toString(failures));
|
||||
|
||||
SVNFileUtil.deleteFile(file);
|
||||
|
||||
File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true);
|
||||
try {
|
||||
SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR);
|
||||
}
|
||||
finally {
|
||||
SVNFileUtil.deleteFile(tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user