Bug 447812 - Allow authentication to follow HTTP redirects Introduced configuration property aether.connector.http.redirectedAuthentication which HttpTransporter uses to control the applicable hosts for server auth
Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/07e1a845 Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/07e1a845 Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/07e1a845 Branch: refs/heads/master Commit: 07e1a845afd00cbc6b57e3c400c72f77f22b41f5 Parents: 32267bf Author: Benjamin Bentmann <bentm...@sonatype.com> Authored: Sun Oct 19 17:05:27 2014 +0200 Committer: Benjamin Bentmann <bentm...@sonatype.com> Committed: Sun Oct 19 17:05:27 2014 +0200 ---------------------------------------------------------------------- .../eclipse/aether/ConfigurationProperties.java | 24 ++++++++- .../aether/transport/http/HttpTransporter.java | 43 ++++++++++++++--- .../transport/http/HttpTransporterTest.java | 51 ++++++++++++++++++++ 3 files changed, 111 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-aether/blob/07e1a845/aether-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java ---------------------------------------------------------------------- diff --git a/aether-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java b/aether-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java index 16c483e..3cbd59c 100644 --- a/aether-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java +++ b/aether-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2013 Sonatype, Inc. + * Copyright (c) 2010, 2014 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -123,6 +123,28 @@ public final class ConfigurationProperties public static final String DEFAULT_HTTP_CREDENTIAL_ENCODING = "ISO-8859-1"; /** + * An option indicating whether authentication configured for a HTTP repository should also be used with any host + * that the original server might redirect requests to. Unless enabled, credentials are only exchanged with the + * original host from the repository URL and not supplied to different hosts encountered during redirects. The + * option value can either be a boolean flag or a comma-separated list of host names denoting the whitelist of + * original hosts whose redirects can be trusted and should use the configured authentication no matter the + * destination host(s). Alternatively, the suffix {@code .<repoId>} can be appended to this configuration key to + * control the behavior for a specific repository id. + * + * @see #DEFAULT_HTTP_REDIRECTED_AUTHENTICATION + * @since 1.1.0 + */ + public static final String HTTP_REDIRECTED_AUTHENTICATION = PREFIX_CONNECTOR + "http.redirectedAuthentication"; + + /** + * The default handling of authentication during HTTP redirects if {@link #HTTP_REDIRECTED_AUTHENTICATION} isn't + * set. + * + * @since 1.1.0 + */ + public static final String DEFAULT_HTTP_REDIRECTED_AUTHENTICATION = "false"; + + /** * A flag indicating whether checksums which are retrieved during checksum validation should be persisted in the * local filesystem next to the file they provide the checksum for. * http://git-wip-us.apache.org/repos/asf/maven-aether/blob/07e1a845/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java index 931e04e..1a4ac00 100644 --- a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java +++ b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java @@ -76,6 +76,8 @@ final class HttpTransporter private static final Pattern CONTENT_RANGE_PATTERN = Pattern.compile( "\\s*bytes\\s+([0-9]+)\\s*-\\s*([0-9]+)\\s*/.*" ); + private static final Pattern HOST_SPLIT_PATTERN = Pattern.compile( "\\s*[,]\\s*" ); + private final Logger logger; private final AuthenticationContext repoAuthContext; @@ -135,7 +137,8 @@ final class HttpTransporter configureClient( client.getParams(), session, repository, proxy ); - client.setCredentialsProvider( toCredentialsProvider( server, repoAuthContext, proxy, proxyAuthContext ) ); + boolean redirectedAuth = getRedirectedAuth( session, repository, server ); + client.setCredentialsProvider( toCredentials( server, repoAuthContext, redirectedAuth, proxy, proxyAuthContext ) ); this.client = new DecompressingHttpClient( client ); } @@ -177,19 +180,47 @@ final class HttpTransporter ConfigurationProperties.USER_AGENT ) ); } - private static CredentialsProvider toCredentialsProvider( HttpHost server, AuthenticationContext serverAuthCtx, - HttpHost proxy, AuthenticationContext proxyAuthCtx ) + private static boolean getRedirectedAuth( RepositorySystemSession session, RemoteRepository repo, HttpHost server ) + { + String mode = + ConfigUtils.getString( session, ConfigurationProperties.DEFAULT_HTTP_REDIRECTED_AUTHENTICATION, + ConfigurationProperties.HTTP_REDIRECTED_AUTHENTICATION + '.' + repo.getId(), + ConfigurationProperties.HTTP_REDIRECTED_AUTHENTICATION ); + if ( "false".equalsIgnoreCase( mode ) ) + { + return false; + } + if ( "true".equalsIgnoreCase( mode ) ) + { + return true; + } + String host = server.getHostName(); + for ( String allowed : HOST_SPLIT_PATTERN.split( mode.trim() ) ) + { + if ( allowed.equalsIgnoreCase( host ) ) + { + return true; + } + } + return false; + } + + private static CredentialsProvider toCredentials( HttpHost server, AuthenticationContext serverAuthCtx, + boolean redirectedAuth, HttpHost proxy, + AuthenticationContext proxyAuthCtx ) { - CredentialsProvider provider = toCredentialsProvider( server.getHostName(), AuthScope.ANY_PORT, serverAuthCtx ); + CredentialsProvider provider = + toCredentials( redirectedAuth ? AuthScope.ANY_HOST : server.getHostName(), AuthScope.ANY_PORT, + serverAuthCtx ); if ( proxy != null ) { - CredentialsProvider p = toCredentialsProvider( proxy.getHostName(), proxy.getPort(), proxyAuthCtx ); + CredentialsProvider p = toCredentials( proxy.getHostName(), proxy.getPort(), proxyAuthCtx ); provider = new DemuxCredentialsProvider( provider, p, proxy ); } return provider; } - private static CredentialsProvider toCredentialsProvider( String host, int port, AuthenticationContext ctx ) + private static CredentialsProvider toCredentials( String host, int port, AuthenticationContext ctx ) { DeferredCredentialsProvider provider = new DeferredCredentialsProvider(); if ( ctx != null ) http://git-wip-us.apache.org/repos/asf/maven-aether/blob/07e1a845/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java index 4dbc730..eed95b4 100644 --- a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java +++ b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java @@ -1141,6 +1141,57 @@ public class HttpTransporterTest } @Test + public void testServerAuthScope_FollowsRedirectToDifferentHost_EnabledByRepoId() + throws Exception + { + session.setConfigProperty( ConfigurationProperties.HTTP_REDIRECTED_AUTHENTICATION + "." + REPO_ID, "true" ); + String username = "testuser", password = "testpass"; + httpServer.setAuthentication( username, password ); + auth = new AuthenticationBuilder().addUsername( username ).addPassword( password ).build(); + proxy = new Proxy( Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort() ); + newTransporter( "http://redirect.localhost:1/" ); + GetTask task = new GetTask( URI.create( "redirect/file.txt?host=" + httpServer.getHost() ) ); + transporter.get( task ); + assertEquals( "test", task.getDataString() ); + } + + @Test + public void testServerAuthScope_FollowsRedirectToDifferentHost_EnabledByHostName() + throws Exception + { + session.setConfigProperty( ConfigurationProperties.HTTP_REDIRECTED_AUTHENTICATION, " REDIRECT.localhost , foo" ); + String username = "testuser", password = "testpass"; + httpServer.setAuthentication( username, password ); + auth = new AuthenticationBuilder().addUsername( username ).addPassword( password ).build(); + proxy = new Proxy( Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort() ); + newTransporter( "http://redirect.localhost:1/" ); + GetTask task = new GetTask( URI.create( "redirect/file.txt?host=" + httpServer.getHost() ) ); + transporter.get( task ); + assertEquals( "test", task.getDataString() ); + } + + @Test + public void testServerAuthScope_FollowsRedirectToDifferentHost_DisabledByDefault() + throws Exception + { + String username = "testuser", password = "testpass"; + httpServer.setAuthentication( username, password ); + auth = new AuthenticationBuilder().addUsername( username ).addPassword( password ).build(); + proxy = new Proxy( Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort() ); + newTransporter( "http://redirect.localhost:1/" ); + GetTask task = new GetTask( URI.create( "redirect/file.txt?host=" + httpServer.getHost() ) ); + try + { + transporter.get( task ); + fail( "Server auth must not be used for redirect destination" ); + } + catch ( HttpResponseException e ) + { + assertEquals( 401, e.getStatusCode() ); + } + } + + @Test public void testServerAuthScope_NotUsedForProxy() throws Exception {