From 0b5441a8ce9a13ac255609f0a978ccd81b755b6d Mon Sep 17 00:00:00 2001 From: Laurent Goujon Date: Mon, 24 Feb 2014 13:52:33 -0800 Subject: [PATCH] Creates HttpAuthMethod type enum to support auth ordering Refactors HttpAuthMethod to support more authentication methods, still sorted by priority orders. Bug: 428836 Change-Id: I049c1742e7afbc51f3f6033fa4d471b344813cfa Signed-off-by: Laurent Goujon Signed-off-by: Chris Aniszczyk --- .../jgit/transport/HttpAuthMethod.java | 88 +++++++++++++++---- .../eclipse/jgit/transport/TransportHttp.java | 6 +- 2 files changed, 76 insertions(+), 18 deletions(-) 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 225af4b49..4d80acc53 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java @@ -69,8 +69,39 @@ import org.eclipse.jgit.util.Base64; * may need to maintain per-connection state information. */ abstract class HttpAuthMethod { - /** No authentication is configured. */ - static final HttpAuthMethod NONE = new None(); + /** + * Enum listing the http authentication method types supported by jgit. They + * are sorted by priority order!!! + */ + public enum Type { + NONE { + @Override + public HttpAuthMethod method(String hdr) { + return None.INSTANCE; + } + }, + BASIC { + @Override + public HttpAuthMethod method(String hdr) { + return new Basic(); + } + }, + DIGEST { + @Override + public HttpAuthMethod method(String hdr) { + return new Digest(hdr); + } + }; + /** + * Creates a HttpAuthMethod instance configured with the provided HTTP + * WWW-Authenticate header. + * + * @param hdr the http header + * @return a configured HttpAuthMethod instance + */ + public abstract HttpAuthMethod method(String hdr); + } + static final String EMPTY_STRING = ""; //$NON-NLS-1$ static final String SCHEMA_NAME_SEPARATOR = " "; //$NON-NLS-1$ @@ -83,7 +114,7 @@ abstract class HttpAuthMethod { */ static HttpAuthMethod scanResponse(final HttpConnection conn) { final Map> headers = conn.getHeaderFields(); - HttpAuthMethod authentication = NONE; + HttpAuthMethod authentication = Type.NONE.method(EMPTY_STRING); for (final Entry> entry : headers.entrySet()) { if (HDR_WWW_AUTHENTICATE.equalsIgnoreCase(entry.getKey())) { @@ -93,19 +124,23 @@ abstract class HttpAuthMethod { final String[] valuePart = value.split( SCHEMA_NAME_SEPARATOR, 2); - if (Digest.NAME.equalsIgnoreCase(valuePart[0])) { + try { + Type methodType = Type.valueOf(valuePart[0].toUpperCase()); + if (authentication.getType().compareTo(methodType) >= 0) { + continue; + } + final String param; if (valuePart.length == 1) param = EMPTY_STRING; else param = valuePart[1]; - authentication = new Digest(param); - break; + authentication = methodType + .method(param); + } catch (IllegalArgumentException e) { + // This auth method is not supported } - - if (Basic.NAME.equalsIgnoreCase(valuePart[0])) - authentication = new Basic(); } } } @@ -116,6 +151,12 @@ abstract class HttpAuthMethod { return authentication; } + protected final Type type; + + protected HttpAuthMethod(Type type) { + this.type = type; + } + /** * Update this method with the credentials from the URIish. * @@ -170,8 +211,22 @@ abstract class HttpAuthMethod { */ abstract void configureRequest(HttpConnection conn) throws IOException; + /** + * Gives the method type associated to this http auth method + * + * @return the method type + */ + public Type getType() { + return type; + } + /** Performs no user authentication. */ private static class None extends HttpAuthMethod { + static final None INSTANCE = new None(); + public None() { + super(Type.NONE); + } + @Override void authorize(String user, String pass) { // Do nothing when no authentication is enabled. @@ -185,12 +240,14 @@ abstract class HttpAuthMethod { /** Performs HTTP basic authentication (plaintext username/password). */ private static class Basic extends HttpAuthMethod { - static final String NAME = "Basic"; //$NON-NLS-1$ - private String user; private String pass; + public Basic() { + super(Type.BASIC); + } + @Override void authorize(final String username, final String password) { this.user = username; @@ -201,14 +258,13 @@ abstract class HttpAuthMethod { void configureRequest(final HttpConnection conn) throws IOException { String ident = user + ":" + pass; //$NON-NLS-1$ String enc = Base64.encodeBytes(ident.getBytes("UTF-8")); //$NON-NLS-1$ - conn.setRequestProperty(HDR_AUTHORIZATION, NAME + " " + enc); //$NON-NLS-1$ + conn.setRequestProperty(HDR_AUTHORIZATION, type.name() + + " " + enc); //$NON-NLS-1$ } } /** Performs HTTP digest authentication. */ private static class Digest extends HttpAuthMethod { - static final String NAME = "Digest"; //$NON-NLS-1$ - private static final Random PRNG = new Random(); private final Map params; @@ -220,6 +276,7 @@ abstract class HttpAuthMethod { private String pass; Digest(String hdr) { + super(Type.DIGEST); params = parse(hdr); final String qop = params.get("qop"); //$NON-NLS-1$ @@ -288,7 +345,8 @@ abstract class HttpAuthMethod { v.append(e.getValue()); v.append('"'); } - conn.setRequestProperty(HDR_AUTHORIZATION, NAME + " " + v); //$NON-NLS-1$ + conn.setRequestProperty(HDR_AUTHORIZATION, type.name() + + " " + v); //$NON-NLS-1$ } private static String uri(URL u) { 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 f4471bf83..e13bfd300 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -246,7 +246,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, private boolean useSmartHttp = true; - private HttpAuthMethod authMethod = HttpAuthMethod.NONE; + private HttpAuthMethod authMethod = HttpAuthMethod.Type.NONE.method(null); private Map headers; @@ -479,7 +479,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, // background (e.g Kerberos/SPNEGO). // That may not work for streaming requests and jgit // explicit authentication would be required - if (authMethod == HttpAuthMethod.NONE + if (authMethod.getType() == HttpAuthMethod.Type.NONE && conn.getHeaderField(HDR_WWW_AUTHENTICATE) != null) authMethod = HttpAuthMethod.scanResponse(conn); return conn; @@ -490,7 +490,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, case HttpConnection.HTTP_UNAUTHORIZED: authMethod = HttpAuthMethod.scanResponse(conn); - if (authMethod == HttpAuthMethod.NONE) + if (authMethod.getType() == HttpAuthMethod.Type.NONE) throw new TransportException(uri, MessageFormat.format( JGitText.get().authenticationNotSupported, uri)); CredentialsProvider credentialsProvider = getCredentialsProvider();