HTTPCLIENT-1834: NTLN auth refactoring; support for MS CredSsp auth
Contributed by Radovan Semancik <radovan.semancik at evolveum.com> and Karl Wright <kwright at apache.org>
This commit is contained in:
parent
a2a581eba1
commit
44f8924b58
|
@ -252,7 +252,8 @@ public class WindowsNegotiateScheme extends AuthSchemeBase {
|
|||
}
|
||||
} else {
|
||||
final HttpClientContext clientContext = HttpClientContext.adapt(context);
|
||||
final HttpHost target = clientContext.getTargetHost(); if (target != null) {
|
||||
final HttpHost target = clientContext.getTargetHost();
|
||||
if (target != null) {
|
||||
spn = "HTTP/" + target.getHostName();
|
||||
} else {
|
||||
final RouteInfo route = clientContext.getHttpRoute();
|
||||
|
|
|
@ -65,6 +65,11 @@ public final class AuthSchemes {
|
|||
*/
|
||||
public static final String KERBEROS = "Kerberos";
|
||||
|
||||
/**
|
||||
* CredSSP authentication scheme defined in [MS-CSSP].
|
||||
*/
|
||||
public static final String CREDSSP = "CredSSP";
|
||||
|
||||
private AuthSchemes() {
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.impl.auth;
|
||||
|
||||
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
|
||||
public class CredSspSchemeFactory implements AuthSchemeProvider
|
||||
{
|
||||
|
||||
@Override
|
||||
public AuthScheme create( final HttpContext context )
|
||||
{
|
||||
return new CredSspScheme();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.impl.auth;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Simple debugging utility class for CredSSP and NTLM implementations.
|
||||
*/
|
||||
class DebugUtil
|
||||
{
|
||||
|
||||
public static String dump( final ByteBuffer buf )
|
||||
{
|
||||
final ByteBuffer dup = buf.duplicate();
|
||||
final StringBuilder sb = new StringBuilder( dup.toString() );
|
||||
sb.append( ": " );
|
||||
while ( dup.position() < dup.limit() )
|
||||
{
|
||||
sb.append( String.format( "%02X ", dup.get() ) );
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static void dump( final StringBuilder sb, final byte[] bytes )
|
||||
{
|
||||
if ( bytes == null )
|
||||
{
|
||||
sb.append( "null" );
|
||||
return;
|
||||
}
|
||||
for ( byte b : bytes )
|
||||
{
|
||||
sb.append( String.format( "%02X ", b ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String dump( final byte[] bytes )
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
dump( sb, bytes );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] fromHex( final String hex )
|
||||
{
|
||||
int i = 0;
|
||||
final byte[] bytes = new byte[200000];
|
||||
int h = 0;
|
||||
while ( h < hex.length() )
|
||||
{
|
||||
if ( hex.charAt( h ) == ' ' )
|
||||
{
|
||||
h++;
|
||||
}
|
||||
final String str = hex.substring( h, h + 2 );
|
||||
bytes[i] = ( byte ) Integer.parseInt( str, 16 );
|
||||
i++;
|
||||
h = h + 2;
|
||||
}
|
||||
final byte[] outbytes = new byte[i];
|
||||
System.arraycopy( bytes, 0, outbytes, 0, i );
|
||||
return outbytes;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -73,9 +73,9 @@ abstract class AuthenticationStrategyImpl implements AuthenticationStrategy {
|
|||
AuthSchemes.SPNEGO,
|
||||
AuthSchemes.KERBEROS,
|
||||
AuthSchemes.NTLM,
|
||||
AuthSchemes.CREDSSP,
|
||||
AuthSchemes.DIGEST,
|
||||
AuthSchemes.BASIC));
|
||||
|
||||
private final int challengeCode;
|
||||
private final String headerName;
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@ package org.apache.http.impl.auth;
|
|||
import org.apache.http.Consts;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import java.util.Random;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.Certificate;
|
||||
|
||||
public class TestNTLMEngineImpl {
|
||||
|
||||
|
@ -51,6 +56,9 @@ public class TestNTLMEngineImpl {
|
|||
if (c >= 'a' && c <= 'f') {
|
||||
return (byte) (c - 'a' + 0x0a);
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return (byte) (c - 'A' + 0x0a);
|
||||
}
|
||||
return (byte) (c - '0');
|
||||
}
|
||||
|
||||
|
@ -89,6 +97,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testLMResponse() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
null,
|
||||
null,
|
||||
"SecREt01",
|
||||
|
@ -107,6 +117,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testNTLMResponse() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
null,
|
||||
null,
|
||||
"SecREt01",
|
||||
|
@ -125,6 +137,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testLMv2Response() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"DOMAIN",
|
||||
"user",
|
||||
"SecREt01",
|
||||
|
@ -143,6 +157,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testNTLMv2Response() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"DOMAIN",
|
||||
"user",
|
||||
"SecREt01",
|
||||
|
@ -163,6 +179,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testLM2SessionResponse() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"DOMAIN",
|
||||
"user",
|
||||
"SecREt01",
|
||||
|
@ -181,6 +199,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testNTLM2SessionResponse() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"DOMAIN",
|
||||
"user",
|
||||
"SecREt01",
|
||||
|
@ -199,6 +219,8 @@ public class TestNTLMEngineImpl {
|
|||
@Test
|
||||
public void testNTLMUserSessionKey() throws Exception {
|
||||
final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"DOMAIN",
|
||||
"user",
|
||||
"SecREt01",
|
||||
|
@ -216,20 +238,74 @@ public class TestNTLMEngineImpl {
|
|||
|
||||
@Test
|
||||
public void testType1Message() throws Exception {
|
||||
new NTLMEngineImpl().getType1Message("myhost", "mydomain");
|
||||
final byte[] bytes = new NTLMEngineImpl.Type1Message("myhost", "mydomain").getBytes();
|
||||
final byte[] bytes2 = toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400");
|
||||
checkArraysMatch(bytes2, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testType3Message() throws Exception {
|
||||
new NTLMEngineImpl().getType3Message("me", "mypassword", "myhost", "mydomain",
|
||||
final byte[] bytes = new NTLMEngineImpl.Type3Message(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"me", "mypassword", "myhost", "mydomain",
|
||||
toBytes("0001020304050607"),
|
||||
0xffffffff,
|
||||
null,null);
|
||||
new NTLMEngineImpl().getType3Message("me", "mypassword", "myhost", "mydomain",
|
||||
null,null).getBytes();
|
||||
checkArraysMatch(toBytes("4E544C4D53535000030000001800180048000000180018006000000004000400780000000C000C007C0000001400140088000000100010009C000000FFFFFFFF0501280A0000000FA86886A5D297814200000000000000000000000000000000EEC7568E00798491244959B9C942F4F367C5CBABEEF546F74D0045006D00790068006F00730074006D007900700061007300730077006F007200640094DDAB1EBB82C9A1AB914CAE6F199644"),
|
||||
bytes);
|
||||
final byte[] bytes2 = new NTLMEngineImpl.Type3Message(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"me", "mypassword", "myhost", "mydomain",
|
||||
toBytes("0001020304050607"),
|
||||
0xffffffff,
|
||||
"mytarget",
|
||||
toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"));
|
||||
toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000")).getBytes();
|
||||
checkArraysMatch(toBytes("4E544C4D53535000030000001800180048000000920092006000000004000400F20000000C000C00F600000014001400020100001000100016010000FFFFFFFF0501280A0000000F3695F1EA7B164788A437892FA7504320DA2D8CF378EBC83CE856A8FB985BF7783545828A91A13AE8010100000000000020CBFAD5DEB19D01A86886A5D29781420000000002000C0044004F004D00410049004E0001000C005300450052005600450052000400140064006F006D00610069006E002E0063006F006D00030022007300650072007600650072002E0064006F006D00610069006E002E0063006F006D0000000000000000004D0045006D00790068006F00730074006D007900700061007300730077006F0072006400BB1AAD36F11631CC7CBC8800CEEE1C99"),
|
||||
bytes2);
|
||||
}
|
||||
|
||||
private static String cannedCert =
|
||||
"-----BEGIN CERTIFICATE-----\n"+
|
||||
"MIIDIDCCAgigAwIBAgIEOqKaWTANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEQMA4GA1UEBxMH\n"+
|
||||
"TXkgQ2l0eTEYMBYGA1UEChMPTXkgT3JnYW5pemF0aW9uMRcwFQYDVQQDEw5NeSBBcHBsaWNhdGlvbjAe\n"+
|
||||
"Fw0xNzAzMTcxNDAyMzRaFw0yNzAzMTUxNDAyMzRaMFIxCzAJBgNVBAYTAlVTMRAwDgYDVQQHEwdNeSBD\n"+
|
||||
"aXR5MRgwFgYDVQQKEw9NeSBPcmdhbml6YXRpb24xFzAVBgNVBAMTDk15IEFwcGxpY2F0aW9uMIIBIjAN\n"+
|
||||
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArc+mbViBaHeRSt82KrJ5IF+62b/Qob95Lca4DJIislTY\n"+
|
||||
"vLPIo0R1faBV8BkEeUQwo01srkf3RaGLCHNZnFal4KEzbtiUy6W+n08G5E9w9YG+WSwW2dmjvEI7k2a2\n"+
|
||||
"xqlaM4NdMKL4ONPXcxfZsMDqxDgpdkaNPKpZ10NDq6rmBTkQw/OSG0z1KLtwLkF1ZQ/3mXdjVzvP83V2\n"+
|
||||
"g17AqBazb0Z1YHsVKmkGjPqnq3niJH/6Oke4N+5k/1cE5lSJcQNGP0nqeGdJfvqQZ+gk6gH/sOngZL9X\n"+
|
||||
"hPVkpseAwHa+xuPneDSjibLgLmMt3XGDK6jGfjdp5FWqFvAD5E3LHbW9gwIDAQABMA0GCSqGSIb3DQEB\n"+
|
||||
"CwUAA4IBAQCpUXUHhl5LyMSO5Q0OktEc9AaFjZtVfknpPde6Zeh35Pqd2354ErvJSBWgzFAphda0oh2s\n"+
|
||||
"OIAFkM6LJQEnVDTbXDXN+YY8e3gb9ryfh85hkhC0XI9qp17WPSkmw8XgDfvRd6YQgKm1AnLxjOCwG2jg\n"+
|
||||
"i09iZBIWkW3ZeRAMvWPHHjvq44iZB5ZrEl0apgumS6MxpUzKOr5Pcq0jxJDw2UCj5YloFMNl+UINv2vV\n"+
|
||||
"aL/DR6ivc61dOfN1E/VNBGkkCk/AogNyucGiFMCq9hd25Y9EbkBBqObYTH1XMX+ufsJh+6hG7KDQ1e/F\n"+
|
||||
"nRrlhKwM2uRe+aSH0D6/erjDBT7tXvwn\n"+
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
@Test
|
||||
public void testType3MessageWithCert() throws Exception {
|
||||
final ByteArrayInputStream fis = new ByteArrayInputStream(cannedCert.getBytes(Consts.ASCII));
|
||||
|
||||
final CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
|
||||
final Certificate cert = cf.generateCertificate(fis);
|
||||
|
||||
final byte[] bytes = new NTLMEngineImpl.Type3Message(
|
||||
new Random(1234),
|
||||
1234L,
|
||||
"me", "mypassword", "myhost", "mydomain",
|
||||
toBytes("0001020304050607"),
|
||||
0xffffffff,
|
||||
"mytarget",
|
||||
toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"),
|
||||
cert,
|
||||
toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400"),
|
||||
toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400FFFEFDFCFBFA")).getBytes();
|
||||
|
||||
checkArraysMatch(toBytes("4E544C4D53535000030000001800180058000000AE00AE0070000000040004001E0100000C000C0022010000140014002E0100001000100042010000FFFFFFFF0501280A0000000FEEFCCE4187D6CDF1F91C686C4E571D943695F1EA7B164788A437892FA7504320DA2D8CF378EBC83C59D7A3B2951929079B66621D7CF4326B010100000000000020CBFAD5DEB19D01A86886A5D29781420000000002000C0044004F004D00410049004E0001000C005300450052005600450052000400140064006F006D00610069006E002E0063006F006D00030022007300650072007600650072002E0064006F006D00610069006E002E0063006F006D0006000400020000000A00100038EDC0B7EF8D8FE9E1E6A83F6DFEB8FF00000000000000004D0045006D00790068006F00730074006D007900700061007300730077006F0072006400BB1AAD36F11631CC7CBC8800CEEE1C99"),
|
||||
bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -247,4 +323,5 @@ public class TestNTLMEngineImpl {
|
|||
Assert.assertEquals(a1[i],a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue