From ac3d3af632b2b98e1ae176e4cd484934d1f49e1d Mon Sep 17 00:00:00 2001 From: Christian Pontesegger Date: Wed, 20 Apr 2016 08:31:18 +0200 Subject: [PATCH] http transport does not use authentication fallback Git servers supporting HTTP transport can send multiple WWW-Authenticate challenges [1] for different authentication schemes the server supports. If authentication fails now retry all authentication types proposed by the server. [1] https://tools.ietf.org/html/rfc2617#page-3 Bug: 492057 Change-Id: I01d438a5896f9b1008bd6b751ad9c7cbf780af1a Signed-off-by: Christian Pontesegger Signed-off-by: Matthias Sohn --- .../eclipse/jgit/transport/HttpAuthTest.java | 2 +- .../jgit/transport/HttpAuthMethod.java | 12 +++++- .../eclipse/jgit/transport/TransportHttp.java | 40 ++++++++++++++----- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java index 523301358..3dc022d38 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java @@ -100,7 +100,7 @@ public class HttpAuthTest { } catch (IOException e) { fail("Couldn't instantiate AuthHeadersResponse: " + e.toString()); } - HttpAuthMethod authMethod = HttpAuthMethod.scanResponse(response); + HttpAuthMethod authMethod = HttpAuthMethod.scanResponse(response, null); if (!expectedAuthMethod.equals(getAuthMethodName(authMethod))) { fail("Wrong authentication method: expected " + expectedAuthMethod diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java index 998f28001..81e6904bf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java @@ -51,6 +51,7 @@ import java.io.UnsupportedEncodingException; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -149,9 +150,12 @@ abstract class HttpAuthMethod { * * @param conn * the connection that failed. + * @param ignoreTypes + * authentication types to be ignored. * @return new authentication method to try. */ - static HttpAuthMethod scanResponse(final HttpConnection conn) { + static HttpAuthMethod scanResponse(final HttpConnection conn, + Collection ignoreTypes) { final Map> headers = conn.getHeaderFields(); HttpAuthMethod authentication = Type.NONE.method(EMPTY_STRING); @@ -165,6 +169,12 @@ abstract class HttpAuthMethod { try { Type methodType = Type.valueOf(valuePart[0].toUpperCase()); + + if ((ignoreTypes != null) + && (ignoreTypes.contains(methodType))) { + continue; + } + if (authentication.getType().compareTo(methodType) >= 0) { continue; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java index 414e8790c..1166080f2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -73,6 +73,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -95,6 +96,7 @@ import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.SymbolicRef; +import org.eclipse.jgit.transport.HttpAuthMethod.Type; import org.eclipse.jgit.transport.http.HttpConnection; import org.eclipse.jgit.util.HttpSupport; import org.eclipse.jgit.util.IO; @@ -448,9 +450,11 @@ public class TransportHttp extends HttpTransport implements WalkTransport, throw new NotSupportedException(MessageFormat.format(JGitText.get().invalidURL, uri), e); } - try { - int authAttempts = 1; - for (;;) { + + int authAttempts = 1; + Collection ignoreTypes = null; + for (;;) { + try { final HttpConnection conn = httpOpen(u); if (useSmartHttp) { String exp = "application/x-" + service + "-advertisement"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -467,7 +471,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, // explicit authentication would be required if (authMethod.getType() == HttpAuthMethod.Type.NONE && conn.getHeaderField(HDR_WWW_AUTHENTICATE) != null) - authMethod = HttpAuthMethod.scanResponse(conn); + authMethod = HttpAuthMethod.scanResponse(conn, ignoreTypes); return conn; case HttpConnection.HTTP_NOT_FOUND: @@ -475,7 +479,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, MessageFormat.format(JGitText.get().uriNotFound, u)); case HttpConnection.HTTP_UNAUTHORIZED: - authMethod = HttpAuthMethod.scanResponse(conn); + authMethod = HttpAuthMethod.scanResponse(conn, ignoreTypes); if (authMethod.getType() == HttpAuthMethod.Type.NONE) throw new TransportException(uri, MessageFormat.format( JGitText.get().authenticationNotSupported, uri)); @@ -501,13 +505,27 @@ public class TransportHttp extends HttpTransport implements WalkTransport, String err = status + " " + conn.getResponseMessage(); //$NON-NLS-1$ throw new TransportException(uri, err); } + } catch (NotSupportedException e) { + throw e; + } catch (TransportException e) { + throw e; + } catch (IOException e) { + if (authMethod.getType() != HttpAuthMethod.Type.NONE) { + if (ignoreTypes == null) { + ignoreTypes = new HashSet(); + } + + ignoreTypes.add(authMethod.getType()); + + // reset auth method & attempts for next authentication type + authMethod = HttpAuthMethod.Type.NONE.method(null); + authAttempts = 1; + + continue; + } + + throw new TransportException(uri, MessageFormat.format(JGitText.get().cannotOpenService, service), e); } - } catch (NotSupportedException e) { - throw e; - } catch (TransportException e) { - throw e; - } catch (IOException e) { - throw new TransportException(uri, MessageFormat.format(JGitText.get().cannotOpenService, service), e); } }