NTLMEngineImpl.java (httpcomponents-client-4.5.6-src) | : | NTLMEngineImpl.java (httpcomponents-client-4.5.7-src) | ||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
* | * | |||
* This software consists of voluntary contributions made by many | * This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | * <http://www.apache.org/>. | |||
* | * | |||
*/ | */ | |||
package org.apache.http.impl.auth; | package org.apache.http.impl.auth; | |||
import java.nio.charset.Charset; | import java.nio.charset.Charset; | |||
import org.apache.http.Consts; | ||||
import java.security.Key; | import java.security.Key; | |||
import java.security.MessageDigest; | import java.security.MessageDigest; | |||
import java.security.NoSuchAlgorithmException; | ||||
import java.security.cert.Certificate; | ||||
import java.security.cert.CertificateEncodingException; | ||||
import java.util.Arrays; | import java.util.Arrays; | |||
import java.util.Locale; | import java.util.Locale; | |||
import java.util.Random; | import java.util.Random; | |||
import javax.crypto.Cipher; | import javax.crypto.Cipher; | |||
import javax.crypto.spec.SecretKeySpec; | import javax.crypto.spec.SecretKeySpec; | |||
import java.security.NoSuchAlgorithmException; | ||||
import java.security.cert.CertificateEncodingException; | ||||
import java.security.cert.Certificate; | ||||
import org.apache.commons.codec.binary.Base64; | import org.apache.commons.codec.binary.Base64; | |||
import org.apache.http.Consts; | ||||
/** | /** | |||
* Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM | * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM | |||
* authentication protocol. | * authentication protocol. | |||
* | * | |||
* @since 4.1 | * @since 4.1 | |||
*/ | */ | |||
final class NTLMEngineImpl implements NTLMEngine { | final class NTLMEngineImpl implements NTLMEngine { | |||
/** Unicode encoding */ | /** Unicode encoding */ | |||
skipping to change at line 212 | skipping to change at line 212 | |||
* If {@encrypt(byte[],byte[])} fails. | * If {@encrypt(byte[],byte[])} fails. | |||
*/ | */ | |||
static String getType3Message(final String user, final String password, fina l String host, final String domain, | static String getType3Message(final String user, final String password, fina l String host, final String domain, | |||
final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, | final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, | |||
final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) | final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) | |||
throws NTLMEngineException { | throws NTLMEngineException { | |||
return new Type3Message(domain, host, user, password, nonce, type2Flags, target, | return new Type3Message(domain, host, user, password, nonce, type2Flags, target, | |||
targetInformation, peerServerCertificate, type1Message, type2Mes sage).getResponse(); | targetInformation, peerServerCertificate, type1Message, type2Mes sage).getResponse(); | |||
} | } | |||
private static int readULong(final byte[] src, final int index) throws NTLME ngineException { | private static int readULong(final byte[] src, final int index) { | |||
if (src.length < index + 4) { | if (src.length < index + 4) { | |||
return 0; | return 0; | |||
} | } | |||
return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) | return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) | |||
| ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); | | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); | |||
} | } | |||
private static int readUShort(final byte[] src, final int index) throws NTLM EngineException { | private static int readUShort(final byte[] src, final int index) { | |||
if (src.length < index + 2) { | if (src.length < index + 2) { | |||
return 0; | return 0; | |||
} | } | |||
return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); | return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); | |||
} | } | |||
private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { | private static byte[] readSecurityBuffer(final byte[] src, final int index) { | |||
final int length = readUShort(src, index); | final int length = readUShort(src, index); | |||
final int offset = readULong(src, index + 4); | final int offset = readULong(src, index + 4); | |||
if (src.length < offset + length) { | if (src.length < offset + length) { | |||
return new byte[length]; | return new byte[length]; | |||
} | } | |||
final byte[] buffer = new byte[length]; | final byte[] buffer = new byte[length]; | |||
System.arraycopy(src, offset, buffer, 0, length); | System.arraycopy(src, offset, buffer, 0, length); | |||
return buffer; | return buffer; | |||
} | } | |||
/** Calculate a challenge block */ | /** Calculate a challenge block */ | |||
private static byte[] makeRandomChallenge(final Random random) throws NTLMEn gineException { | private static byte[] makeRandomChallenge(final Random random) { | |||
final byte[] rval = new byte[8]; | final byte[] rval = new byte[8]; | |||
synchronized (random) { | synchronized (random) { | |||
random.nextBytes(rval); | random.nextBytes(rval); | |||
} | } | |||
return rval; | return rval; | |||
} | } | |||
/** Calculate a 16-byte secondary key */ | /** Calculate a 16-byte secondary key */ | |||
private static byte[] makeSecondaryKey(final Random random) throws NTLMEngin eException { | private static byte[] makeSecondaryKey(final Random random) { | |||
final byte[] rval = new byte[16]; | final byte[] rval = new byte[16]; | |||
synchronized (random) { | synchronized (random) { | |||
random.nextBytes(rval); | random.nextBytes(rval); | |||
} | } | |||
return rval; | return rval; | |||
} | } | |||
protected static class CipherGen { | protected static class CipherGen { | |||
protected final Random random; | protected final Random random; | |||
skipping to change at line 292 | skipping to change at line 292 | |||
protected byte[] ntlmv2Blob = null; | protected byte[] ntlmv2Blob = null; | |||
protected byte[] ntlmv2Response = null; | protected byte[] ntlmv2Response = null; | |||
protected byte[] ntlm2SessionResponse = null; | protected byte[] ntlm2SessionResponse = null; | |||
protected byte[] lm2SessionResponse = null; | protected byte[] lm2SessionResponse = null; | |||
protected byte[] lmUserSessionKey = null; | protected byte[] lmUserSessionKey = null; | |||
protected byte[] ntlmUserSessionKey = null; | protected byte[] ntlmUserSessionKey = null; | |||
protected byte[] ntlmv2UserSessionKey = null; | protected byte[] ntlmv2UserSessionKey = null; | |||
protected byte[] ntlm2SessionResponseUserSessionKey = null; | protected byte[] ntlm2SessionResponseUserSessionKey = null; | |||
protected byte[] lanManagerSessionKey = null; | protected byte[] lanManagerSessionKey = null; | |||
/** | ||||
* @deprecated Use {@link CipherGen#CipherGen(Random, long, String, Stri | ||||
ng, String, byte[], String, byte[], byte[], byte[], byte[], byte[])} | ||||
*/ | ||||
@Deprecated | @Deprecated | |||
public CipherGen(final String domain, final String user, final String pa ssword, | public CipherGen(final String domain, final String user, final String pa ssword, | |||
final byte[] challenge, final String target, final byte[] targetInfo rmation, | final byte[] challenge, final String target, final byte[] targetInfo rmation, | |||
final byte[] clientChallenge, final byte[] clientChallenge2, | final byte[] clientChallenge, final byte[] clientChallenge2, | |||
final byte[] secondaryKey, final byte[] timestamp) { | final byte[] secondaryKey, final byte[] timestamp) { | |||
this(RND_GEN, System.currentTimeMillis(), | this(RND_GEN, System.currentTimeMillis(), | |||
domain, user, password, challenge, target, targetInformation, | domain, user, password, challenge, target, targetInformation, | |||
clientChallenge, clientChallenge2, | clientChallenge, clientChallenge2, | |||
secondaryKey, timestamp); | secondaryKey, timestamp); | |||
} | } | |||
skipping to change at line 323 | skipping to change at line 326 | |||
this.user = user; | this.user = user; | |||
this.password = password; | this.password = password; | |||
this.challenge = challenge; | this.challenge = challenge; | |||
this.targetInformation = targetInformation; | this.targetInformation = targetInformation; | |||
this.clientChallenge = clientChallenge; | this.clientChallenge = clientChallenge; | |||
this.clientChallenge2 = clientChallenge2; | this.clientChallenge2 = clientChallenge2; | |||
this.secondaryKey = secondaryKey; | this.secondaryKey = secondaryKey; | |||
this.timestamp = timestamp; | this.timestamp = timestamp; | |||
} | } | |||
/** | ||||
* @deprecated Use {@link CipherGen#CipherGen(Random, long, String, Stri | ||||
ng, String, byte[], String, byte[], byte[], byte[], byte[], byte[])} | ||||
*/ | ||||
@Deprecated | @Deprecated | |||
public CipherGen(final String domain, | public CipherGen(final String domain, | |||
final String user, | final String user, | |||
final String password, | final String password, | |||
final byte[] challenge, | final byte[] challenge, | |||
final String target, | final String target, | |||
final byte[] targetInformation) { | final byte[] targetInformation) { | |||
this(RND_GEN, System.currentTimeMillis(), domain, user, password, ch allenge, target, targetInformation); | this(RND_GEN, System.currentTimeMillis(), domain, user, password, ch allenge, target, targetInformation); | |||
} | } | |||
skipping to change at line 750 | skipping to change at line 756 | |||
* @param hash | * @param hash | |||
* The NTLMv2 Hash. | * The NTLMv2 Hash. | |||
* @param clientData | * @param clientData | |||
* The client data (blob or client challenge). | * The client data (blob or client challenge). | |||
* @param challenge | * @param challenge | |||
* The server challenge from the Type 2 message. | * The server challenge from the Type 2 message. | |||
* | * | |||
* @return The response (either NTLMv2 or LMv2, depending on the client | * @return The response (either NTLMv2 or LMv2, depending on the client | |||
* data). | * data). | |||
*/ | */ | |||
private static byte[] lmv2Response(final byte[] hash, final byte[] challenge | private static byte[] lmv2Response(final byte[] hash, final byte[] challenge | |||
, final byte[] clientData) | , final byte[] clientData) { | |||
throws NTLMEngineException { | ||||
final HMACMD5 hmacMD5 = new HMACMD5(hash); | final HMACMD5 hmacMD5 = new HMACMD5(hash); | |||
hmacMD5.update(challenge); | hmacMD5.update(challenge); | |||
hmacMD5.update(clientData); | hmacMD5.update(clientData); | |||
final byte[] mac = hmacMD5.getOutput(); | final byte[] mac = hmacMD5.getOutput(); | |||
final byte[] lmv2Response = new byte[mac.length + clientData.length]; | final byte[] lmv2Response = new byte[mac.length + clientData.length]; | |||
System.arraycopy(mac, 0, lmv2Response, 0, mac.length); | System.arraycopy(mac, 0, lmv2Response, 0, mac.length); | |||
System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.len gth); | System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.len gth); | |||
return lmv2Response; | return lmv2Response; | |||
} | } | |||
skipping to change at line 856 | skipping to change at line 861 | |||
sealMd5.update( sealingKey ); | sealMd5.update( sealingKey ); | |||
final byte[] seqNumBytes = new byte[4]; | final byte[] seqNumBytes = new byte[4]; | |||
writeULong( seqNumBytes, sequenceNumber, 0 ); | writeULong( seqNumBytes, sequenceNumber, 0 ); | |||
sealMd5.update( seqNumBytes ); | sealMd5.update( seqNumBytes ); | |||
sealingKey = sealMd5.digest(); | sealingKey = sealMd5.digest(); | |||
initCipher(); | initCipher(); | |||
} | } | |||
sequenceNumber++; | sequenceNumber++; | |||
} | } | |||
private byte[] encrypt( final byte[] data ) throws NTLMEngineException | private byte[] encrypt( final byte[] data ) | |||
{ | { | |||
return rc4.update( data ); | return rc4.update( data ); | |||
} | } | |||
private byte[] decrypt( final byte[] data ) throws NTLMEngineException | private byte[] decrypt( final byte[] data ) | |||
{ | { | |||
return rc4.update( data ); | return rc4.update( data ); | |||
} | } | |||
private byte[] computeSignature( final byte[] message ) throws NTLMEngin eException | private byte[] computeSignature( final byte[] message ) | |||
{ | { | |||
final byte[] sig = new byte[16]; | final byte[] sig = new byte[16]; | |||
// version | // version | |||
sig[0] = 0x01; | sig[0] = 0x01; | |||
sig[1] = 0x00; | sig[1] = 0x00; | |||
sig[2] = 0x00; | sig[2] = 0x00; | |||
sig[3] = 0x00; | sig[3] = 0x00; | |||
// HMAC (first 8 bytes) | // HMAC (first 8 bytes) | |||
skipping to change at line 892 | skipping to change at line 897 | |||
System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); | System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); | |||
final byte[] encryptedHmac = encrypt( trimmedHmac ); | final byte[] encryptedHmac = encrypt( trimmedHmac ); | |||
System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); | System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); | |||
// sequence number | // sequence number | |||
encodeLong( sig, 12, sequenceNumber ); | encodeLong( sig, 12, sequenceNumber ); | |||
return sig; | return sig; | |||
} | } | |||
private boolean validateSignature( final byte[] signature, final byte me ssage[] ) throws NTLMEngineException | private boolean validateSignature( final byte[] signature, final byte me ssage[] ) | |||
{ | { | |||
final byte[] computedSignature = computeSignature( message ); | final byte[] computedSignature = computeSignature( message ); | |||
// log.info( "SSSSS validateSignature("+seqNumber+")\n" | // log.info( "SSSSS validateSignature("+seqNumber+")\n" | |||
// + " received: " + DebugUtil.dump( signature ) + " \n" | // + " received: " + DebugUtil.dump( signature ) + " \n" | |||
// + " computed: " + DebugUtil.dump( computedSignatu re ) ); | // + " computed: " + DebugUtil.dump( computedSignatu re ) ); | |||
return Arrays.equals( signature, computedSignature ); | return Arrays.equals( signature, computedSignature ); | |||
} | } | |||
public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) thr ows NTLMEngineException | public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) thr ows NTLMEngineException | |||
{ | { | |||
skipping to change at line 1036 | skipping to change at line 1041 | |||
/** | /** | |||
* Find the character set based on the flags. | * Find the character set based on the flags. | |||
* @param flags is the flags. | * @param flags is the flags. | |||
* @return the character set. | * @return the character set. | |||
*/ | */ | |||
private static Charset getCharset(final int flags) throws NTLMEngineExceptio n | private static Charset getCharset(final int flags) throws NTLMEngineExceptio n | |||
{ | { | |||
if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { | if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { | |||
return DEFAULT_CHARSET; | return DEFAULT_CHARSET; | |||
} else { | ||||
if (UNICODE_LITTLE_UNMARKED == null) { | ||||
throw new NTLMEngineException( "Unicode not supported" ); | ||||
} | ||||
return UNICODE_LITTLE_UNMARKED; | ||||
} | } | |||
if (UNICODE_LITTLE_UNMARKED == null) { | ||||
throw new NTLMEngineException( "Unicode not supported" ); | ||||
} | ||||
return UNICODE_LITTLE_UNMARKED; | ||||
} | } | |||
/** Strip dot suffix from a name */ | /** Strip dot suffix from a name */ | |||
private static String stripDotSuffix(final String value) { | private static String stripDotSuffix(final String value) { | |||
if (value == null) { | if (value == null) { | |||
return null; | return null; | |||
} | } | |||
final int index = value.indexOf('.'); | final int index = value.indexOf('.'); | |||
if (index != -1) { | if (index != -1) { | |||
return value.substring(0, index); | return value.substring(0, index); | |||
End of changes. 18 change blocks. | ||||
21 lines changed or deleted | 27 lines changed or added |