From 1c004a4870fbb4768585c3aeaa416826106a322b Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Tue, 4 Oct 2016 14:01:06 +0000 Subject: [PATCH] HTTPCLIENT-1779: [OSGi] support NTLM proxy authentication git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1763279 13f79535-47bb-0310-9956-ffa450edef68 --- .../osgi/impl/OSGiCredentialsProvider.java | 53 +++++++-- .../impl/OSGiCredentialsProviderTest.java | 101 ++++++++++++++++++ 2 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java index 2f6631bea..7643c4347 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java @@ -28,8 +28,11 @@ package org.apache.http.osgi.impl; import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; +import org.apache.http.auth.NTCredentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.osgi.services.ProxyConfiguration; @@ -39,9 +42,17 @@ import org.apache.http.osgi.services.ProxyConfiguration; */ final class OSGiCredentialsProvider implements CredentialsProvider { - private List proxyConfigurations; + private static final Log log = LogFactory.getLog(OSGiCredentialsProvider.class); - public OSGiCredentialsProvider(final List proxyConfigurations) { + private static final int HOST_AND_PORT_MATCH = 12; + + private static final String BASIC_SCHEME_NAME = "BASIC"; + + private static final String NTLM_SCHEME_NAME = "NTLM"; + + private final List proxyConfigurations; + + OSGiCredentialsProvider(final List proxyConfigurations) { this.proxyConfigurations = proxyConfigurations; } @@ -57,15 +68,17 @@ final class OSGiCredentialsProvider implements CredentialsProvider { * {@inheritDoc} */ @Override - public Credentials getCredentials(final AuthScope authscope) { + public Credentials getCredentials(final AuthScope authScope) { // iterate over all active proxy configurations at the moment of getting the credential - for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) { - if (proxyConfiguration.isEnabled()) { - final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); - if (authscope.match(actual) >= 12) { - final String username = proxyConfiguration.getUsername(); - final String password = proxyConfiguration.getPassword(); - return new UsernamePasswordCredentials(username, password != null ? password : null); + for (final ProxyConfiguration config : proxyConfigurations) { + if (config.isEnabled() && isSuitable(config, authScope)) { + final String scheme = authScope.getScheme(); + if (BASIC_SCHEME_NAME.equals(scheme)) { + return new UsernamePasswordCredentials(config.getUsername(), config.getPassword()); + } else if (NTLM_SCHEME_NAME.equals(scheme)) { + return createNTCredentials(config); + } else { + log.debug("credentials requested for unsupported authentication scheme " + scheme); } } } @@ -81,4 +94,24 @@ final class OSGiCredentialsProvider implements CredentialsProvider { // do nothing, not used in this version } + // suitable configurations match at least the host and port of the AuthScope + private boolean isSuitable(final ProxyConfiguration config, final AuthScope authScope) { + return authScope.match(new AuthScope(config.getHostname(), config.getPort())) >= HOST_AND_PORT_MATCH; + } + + private static Credentials createNTCredentials(final ProxyConfiguration config) { + final String domainAndUsername = config.getUsername(); + final String username; + final String domain; + final int index = domainAndUsername.indexOf("\\"); + if (index > -1) { + username = domainAndUsername.substring(index + 1); + domain = domainAndUsername.substring(0, index); + } else { + username = domainAndUsername; + domain = null; + } + return new NTCredentials(username, config.getPassword(), null, domain); + } + } diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java new file mode 100644 index 000000000..81703fbc2 --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java @@ -0,0 +1,101 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.NTCredentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.osgi.services.ProxyConfiguration; +import org.junit.Test; + +import java.util.Hashtable; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertThat; + +public class OSGiCredentialsProviderTest { + + private static final String HOST = "proxy.example.org"; + + private static final int PORT = 8080; + + @Test + public void basicAuthentication() { + final CredentialsProvider provider = credentialsProvider(proxy("user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "BASIC")); + assertThat(credentials, instanceOf(UsernamePasswordCredentials.class)); + assertCredentials((UsernamePasswordCredentials) credentials, "user", "secret"); + } + + @Test + public void ntlmAuthenticationWithoutDomain() { + final CredentialsProvider provider = credentialsProvider(proxy("user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "NTLM")); + assertThat(credentials, instanceOf(NTCredentials.class)); + assertCredentials((NTCredentials) credentials, "user", "secret", null); + } + + @Test + public void ntlmAuthenticationWithDomain() { + final CredentialsProvider provider = credentialsProvider(proxy("DOMAIN\\user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "NTLM")); + assertThat(credentials, instanceOf(NTCredentials.class)); + assertCredentials((NTCredentials) credentials, "user", "secret", "DOMAIN"); + } + + private CredentialsProvider credentialsProvider(final ProxyConfiguration... proxies) { + return new OSGiCredentialsProvider(asList(proxies)); + } + + private void assertCredentials(final UsernamePasswordCredentials credentials, final String user, final String password) { + assertThat("Username mismatch", credentials.getUserName(), equalTo(user)); + assertThat("Password mismatch", credentials.getPassword(), equalTo(password)); + } + + private void assertCredentials(final NTCredentials credentials, final String user, final String password, final String domain) { + assertThat("Username mismatch", credentials.getUserName(), equalTo(user)); + assertThat("Password mismatch", credentials.getPassword(), equalTo(password)); + assertThat("Domain mismatch", credentials.getDomain(), equalTo(domain)); + } + + private ProxyConfiguration proxy(final String username, final String password) { + final OSGiProxyConfiguration proxyConfiguration = new OSGiProxyConfiguration(); + final Hashtable config = new Hashtable(); + config.put("proxy.enabled", true); + config.put("proxy.host", HOST); + config.put("proxy.port", PORT); + config.put("proxy.user", username); + config.put("proxy.password", password); + config.put("proxy.exceptions", new String[0]); + proxyConfiguration.update(config); + return proxyConfiguration; + } +}