From 430395a6690afcc8dedc2a8425f731668f071eaa Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Sun, 27 Nov 2011 01:16:49 +0100 Subject: [PATCH] Reset SSH connection and credentials on "Auth fail" When SSH user/password authentication failed this may have been caused by changed credentials on the server side. When the SSH credentials of a user change the SSH connection needs to be re-established and credentials which may have been stored by the credentials provider need to be reset in order to enable prompting for the new credentials. Bug: 356233 Change-Id: I7d64c5f39b68a9687c858bb68a961616eabbc751 Signed-off-by: Matthias Sohn --- .../jgit/transport/CredentialsProvider.java | 9 +++ .../transport/JschConfigSessionFactory.java | 66 +++++++++++++------ 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java index 194268f1f..464d0f9ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java @@ -134,4 +134,13 @@ public abstract class CredentialsProvider { throws UnsupportedCredentialItem { return get(uri, items.toArray(new CredentialItem[items.size()])); } + + /** + * Reset the credentials provider for the given URI + * + * @param uri + */ + public void reset(URIish uri) { + // default does nothing + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java index b1f23243e..047ff5867 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java @@ -106,26 +106,29 @@ public abstract class JschConfigSessionFactory extends SshSessionFactory { if (user == null) user = hc.getUser(); - final Session session = createSession(hc, user, host, port, fs); - if (pass != null) - session.setPassword(pass); - final String strictHostKeyCheckingPolicy = hc - .getStrictHostKeyChecking(); - if (strictHostKeyCheckingPolicy != null) - session.setConfig("StrictHostKeyChecking", - strictHostKeyCheckingPolicy); - final String pauth = hc.getPreferredAuthentications(); - if (pauth != null) - session.setConfig("PreferredAuthentications", pauth); - if (credentialsProvider != null - && (!hc.isBatchMode() || !credentialsProvider.isInteractive())) { - session.setUserInfo(new CredentialsProviderUserInfo(session, - credentialsProvider)); - } - configure(hc, session); + Session session = createSession(credentialsProvider, fs, user, + pass, host, port, hc); - if (!session.isConnected()) - session.connect(tms); + int retries = 0; + while (!session.isConnected() && retries < 3) { + try { + retries++; + session.connect(tms); + } catch (JSchException e) { + session.disconnect(); + session = null; + // if authentication failed maybe credentials changed at the + // remote end therefore reset credentials and retry + if (credentialsProvider != null && e.getCause() == null + && e.getMessage().equals("Auth fail")) { + credentialsProvider.reset(uri); + session = createSession(credentialsProvider, fs, user, + pass, host, port, hc); + } else { + throw e; + } + } + } return new JschSession(session, uri); @@ -140,9 +143,32 @@ public abstract class JschConfigSessionFactory extends SshSessionFactory { } + private Session createSession(CredentialsProvider credentialsProvider, + FS fs, String user, final String pass, String host, int port, + final OpenSshConfig.Host hc) throws JSchException { + final Session session = createSession(hc, user, host, port, fs); + if (pass != null) + session.setPassword(pass); + final String strictHostKeyCheckingPolicy = hc + .getStrictHostKeyChecking(); + if (strictHostKeyCheckingPolicy != null) + session.setConfig("StrictHostKeyChecking", + strictHostKeyCheckingPolicy); + final String pauth = hc.getPreferredAuthentications(); + if (pauth != null) + session.setConfig("PreferredAuthentications", pauth); + if (credentialsProvider != null + && (!hc.isBatchMode() || !credentialsProvider.isInteractive())) { + session.setUserInfo(new CredentialsProviderUserInfo(session, + credentialsProvider)); + } + configure(hc, session); + return session; + } + /** * Create a new remote session for the requested address. - * + * * @param hc * host configuration * @param user