You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ol...@apache.org on 2016/05/01 12:57:03 UTC

[05/15] maven-aether git commit: Bug 445283 - HTTP transporter can mistake server authentication for proxy authentication

Bug 445283 - HTTP transporter can mistake server authentication for proxy authentication

Stored server and proxy credentials in separate providers and used new DemuxCredentialsProvider to delegate to one of those providers depending on host in auth request


Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/535df408
Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/535df408
Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/535df408

Branch: refs/heads/1.0.x
Commit: 535df4084a29e9aa91a7d0bbeac5a5e6e7948454
Parents: e114670
Author: Benjamin Bentmann <be...@sonatype.com>
Authored: Tue Nov 11 15:00:35 2014 +0100
Committer: Benjamin Bentmann <be...@sonatype.com>
Committed: Tue Nov 11 15:00:35 2014 +0100

----------------------------------------------------------------------
 .../http/DemuxCredentialsProvider.java          | 67 ++++++++++++++++++++
 .../aether/transport/http/HttpTransporter.java  | 28 +++++---
 .../transport/http/HttpTransporterTest.java     | 42 +++++++++++-
 3 files changed, 126 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-aether/blob/535df408/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/DemuxCredentialsProvider.java
----------------------------------------------------------------------
diff --git a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/DemuxCredentialsProvider.java b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/DemuxCredentialsProvider.java
new file mode 100644
index 0000000..4b89639
--- /dev/null
+++ b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/DemuxCredentialsProvider.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.aether.transport.http;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.client.CredentialsProvider;
+
+/**
+ * Credentials provider that helps to isolate server from proxy credentials. Apache HttpClient uses a single provider
+ * for both server and proxy auth, using the auth scope (host, port, etc.) to select the proper credentials. With regard
+ * to redirects, we use an auth scope for server credentials that's not specific enough to not be mistaken for proxy
+ * auth. This provider helps to maintain the proper isolation.
+ */
+final class DemuxCredentialsProvider
+    implements CredentialsProvider
+{
+
+    private final CredentialsProvider serverCredentialsProvider;
+
+    private final CredentialsProvider proxyCredentialsProvider;
+
+    private final HttpHost proxy;
+
+    public DemuxCredentialsProvider( CredentialsProvider serverCredentialsProvider,
+                                     CredentialsProvider proxyCredentialsProvider, HttpHost proxy )
+    {
+        this.serverCredentialsProvider = serverCredentialsProvider;
+        this.proxyCredentialsProvider = proxyCredentialsProvider;
+        this.proxy = proxy;
+    }
+
+    private CredentialsProvider getDelegate( AuthScope authScope )
+    {
+        if ( proxy.getPort() == authScope.getPort() && proxy.getHostName().equalsIgnoreCase( authScope.getHost() ) )
+        {
+            return proxyCredentialsProvider;
+        }
+        return serverCredentialsProvider;
+    }
+
+    public Credentials getCredentials( AuthScope authScope )
+    {
+        return getDelegate( authScope ).getCredentials( authScope );
+    }
+
+    public void setCredentials( AuthScope authScope, Credentials credentials )
+    {
+        getDelegate( authScope ).setCredentials( authScope, credentials );
+    }
+
+    public void clear()
+    {
+        serverCredentialsProvider.clear();
+        proxyCredentialsProvider.clear();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/535df408/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 1eda25e..001d760 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Sonatype, Inc.
+ * Copyright (c) 2013, 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
@@ -32,6 +32,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.params.AuthParams;
+import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.HttpResponseException;
 import org.apache.http.client.methods.HttpGet;
@@ -134,13 +135,7 @@ final class HttpTransporter
 
         configureClient( client.getParams(), session, repository, proxy );
 
-        DeferredCredentialsProvider credsProvider = new DeferredCredentialsProvider();
-        addCredentials( credsProvider, server.getHostName(), AuthScope.ANY_PORT, repoAuthContext );
-        if ( proxy != null )
-        {
-            addCredentials( credsProvider, proxy.getHostName(), proxy.getPort(), proxyAuthContext );
-        }
-        client.setCredentialsProvider( credsProvider );
+        client.setCredentialsProvider( toCredentialsProvider( server, repoAuthContext, proxy, proxyAuthContext ) );
 
         this.client = new DecompressingHttpClient( client );
     }
@@ -182,9 +177,21 @@ final class HttpTransporter
                                                                         ConfigurationProperties.USER_AGENT ) );
     }
 
-    private static void addCredentials( DeferredCredentialsProvider provider, String host, int port,
-                                        AuthenticationContext ctx )
+    private static CredentialsProvider toCredentialsProvider( HttpHost server, AuthenticationContext serverAuthCtx,
+                                                              HttpHost proxy, AuthenticationContext proxyAuthCtx )
+    {
+        CredentialsProvider provider = toCredentialsProvider( server.getHostName(), AuthScope.ANY_PORT, serverAuthCtx );
+        if ( proxy != null )
+        {
+            CredentialsProvider p = toCredentialsProvider( proxy.getHostName(), proxy.getPort(), proxyAuthCtx );
+            provider = new DemuxCredentialsProvider( provider, p, proxy );
+        }
+        return provider;
+    }
+
+    private static CredentialsProvider toCredentialsProvider( String host, int port, AuthenticationContext ctx )
     {
+        DeferredCredentialsProvider provider = new DeferredCredentialsProvider();
         if ( ctx != null )
         {
             AuthScope basicScope = new AuthScope( host, port );
@@ -193,6 +200,7 @@ final class HttpTransporter
             AuthScope ntlmScope = new AuthScope( host, port, AuthScope.ANY_REALM, "ntlm" );
             provider.setCredentials( ntlmScope, new DeferredCredentialsProvider.NtlmFactory( ctx ) );
         }
+        return provider;
     }
 
     LocalState getState()

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/535df408/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 16fe0c4..1c85c38 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Sonatype, Inc.
+ * Copyright (c) 2013, 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
@@ -1042,6 +1042,46 @@ public class HttpTransporterTest
     }
 
     @Test
+    public void testServerAuthScope_NotUsedForProxy()
+        throws Exception
+    {
+        String username = "testuser", password = "testpass";
+        httpServer.setProxyAuthentication( username, password );
+        auth = new AuthenticationBuilder().addUsername( username ).addPassword( password ).build();
+        proxy = new Proxy( Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort() );
+        newTransporter( "http://" + httpServer.getHost() + ":12/" );
+        try
+        {
+            transporter.get( new GetTask( URI.create( "repo/file.txt" ) ) );
+            fail( "Server auth must not be used as proxy auth" );
+        }
+        catch ( HttpResponseException e )
+        {
+            assertEquals( 407, e.getStatusCode() );
+        }
+    }
+
+    @Test
+    public void testProxyAuthScope_NotUsedForServer()
+        throws Exception
+    {
+        String username = "testuser", password = "testpass";
+        httpServer.setAuthentication( username, password );
+        Authentication auth = new AuthenticationBuilder().addUsername( username ).addPassword( password ).build();
+        proxy = new Proxy( Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth );
+        newTransporter( "http://" + httpServer.getHost() + ":12/" );
+        try
+        {
+            transporter.get( new GetTask( URI.create( "repo/file.txt" ) ) );
+            fail( "Proxy auth must not be used as server auth" );
+        }
+        catch ( HttpResponseException e )
+        {
+            assertEquals( 401, e.getStatusCode() );
+        }
+    }
+
+    @Test
     public void testAuthSchemeReuse()
         throws Exception
     {