diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index c0a55ad22..c8a194331 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -3,6 +3,10 @@ Changes since 4.3 ALPHA1 * [HTTPCLIENT-1317] InetAddressUtils should handle IPv6 Addresses with Embedded IPv4 Addresses Contributed Sebastian Bazley . +* [HTTPCLIENT-1315] NTLM support did not work properly when the target (as returned + in the Type 2 message) differed from the domain as supplied by the user. + Contributed by Karl Wright + * [HTTPCLIENT-1320] SSLSocketFactory#createSystemSSLContext causes UnrecoverableKeyException 'Password verification failed' when a truststore is specified with 'javax.net.ssl.trustStore' system property is used without a password. diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index a113ecb41..9b3ce86fa 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -35,7 +35,6 @@ import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; -import org.apache.http.HttpException; import org.apache.http.util.EncodingUtils; /** @@ -73,7 +72,7 @@ final class NTLMEngineImpl implements NTLMEngine { java.security.SecureRandom rnd = null; try { rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); - } catch (final Exception e) { + } catch (Exception e) { } RND_GEN = rnd; } @@ -88,7 +87,7 @@ final class NTLMEngineImpl implements NTLMEngine { private static byte[] SIGNATURE; static { - final byte[] bytesWithoutNull = EncodingUtils.getBytes("NTLMSSP", "ASCII"); + byte[] bytesWithoutNull = EncodingUtils.getBytes("NTLMSSP", "ASCII"); SIGNATURE = new byte[bytesWithoutNull.length + 1]; System.arraycopy(bytesWithoutNull, 0, SIGNATURE, 0, bytesWithoutNull.length); SIGNATURE[bytesWithoutNull.length] = (byte) 0x00; @@ -111,14 +110,14 @@ final class NTLMEngineImpl implements NTLMEngine { * @throws HttpException * If the messages cannot be retrieved. */ - final String getResponseFor(final String message, final String username, final String password, - final String host, final String domain) throws NTLMEngineException { + final String getResponseFor(String message, String username, String password, + String host, String domain) throws NTLMEngineException { final String response; if (message == null || message.trim().equals("")) { response = getType1Message(host, domain); } else { - final Type2Message t2m = new Type2Message(message); + Type2Message t2m = new Type2Message(message); response = getType3Message(username, password, host, domain, t2m.getChallenge(), t2m .getFlags(), t2m.getTarget(), t2m.getTargetInfo()); } @@ -136,7 +135,7 @@ final class NTLMEngineImpl implements NTLMEngine { * The domain to authenticate with. * @return String the message to add to the HTTP request header. */ - String getType1Message(final String host, final String domain) throws NTLMEngineException { + String getType1Message(String host, String domain) throws NTLMEngineException { return new Type1Message(domain, host).getResponse(); } @@ -160,8 +159,8 @@ final class NTLMEngineImpl implements NTLMEngine { * @throws NTLMEngineException * If {@encrypt(byte[],byte[])} fails. */ - String getType3Message(final String user, final String password, final String host, final String domain, - final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation) + String getType3Message(String user, String password, String host, String domain, + byte[] nonce, int type2Flags, String target, byte[] targetInformation) throws NTLMEngineException { return new Type3Message(domain, host, user, password, nonce, type2Flags, target, targetInformation).getResponse(); @@ -178,52 +177,48 @@ final class NTLMEngineImpl implements NTLMEngine { * @param credentialCharset * The credentialCharset to set. */ - void setCredentialCharset(final String credentialCharset) { + void setCredentialCharset(String credentialCharset) { this.credentialCharset = credentialCharset; } /** Strip dot suffix from a name */ - private static String stripDotSuffix(final String value) { - final int index = value.indexOf("."); - if (index != -1) { + private static String stripDotSuffix(String value) { + int index = value.indexOf("."); + if (index != -1) return value.substring(0, index); - } return value; } /** Convert host to standard form */ - private static String convertHost(final String host) { + private static String convertHost(String host) { return stripDotSuffix(host); } /** Convert domain to standard form */ - private static String convertDomain(final String domain) { + private static String convertDomain(String domain) { return stripDotSuffix(domain); } - private static int readULong(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 4) { + private static int readULong(byte[] src, int index) throws NTLMEngineException { + if (src.length < index + 4) throw new NTLMEngineException("NTLM authentication - buffer too small for DWORD"); - } return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); } - private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 2) { + private static int readUShort(byte[] src, int index) throws NTLMEngineException { + if (src.length < index + 2) throw new NTLMEngineException("NTLM authentication - buffer too small for WORD"); - } return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); } - private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { - final int length = readUShort(src, index); - final int offset = readULong(src, index + 4); - if (src.length < offset + length) { + private static byte[] readSecurityBuffer(byte[] src, int index) throws NTLMEngineException { + int length = readUShort(src, index); + int offset = readULong(src, index + 4); + if (src.length < offset + length) throw new NTLMEngineException( "NTLM authentication - buffer too small for data item"); - } - final byte[] buffer = new byte[length]; + byte[] buffer = new byte[length]; System.arraycopy(src, offset, buffer, 0, length); return buffer; } @@ -233,7 +228,7 @@ final class NTLMEngineImpl implements NTLMEngine { if (RND_GEN == null) { throw new NTLMEngineException("Random generator not available"); } - final byte[] rval = new byte[8]; + byte[] rval = new byte[8]; synchronized (RND_GEN) { RND_GEN.nextBytes(rval); } @@ -245,7 +240,7 @@ final class NTLMEngineImpl implements NTLMEngine { if (RND_GEN == null) { throw new NTLMEngineException("Random generator not available"); } - final byte[] rval = new byte[16]; + byte[] rval = new byte[16]; synchronized (RND_GEN) { RND_GEN.nextBytes(rval); } @@ -254,14 +249,16 @@ final class NTLMEngineImpl implements NTLMEngine { protected static class CipherGen { - protected final String target; + protected final String domain; protected final String user; protected final String password; protected final byte[] challenge; + protected final String target; protected final byte[] targetInformation; // Information we can generate but may be passed in (for testing) protected byte[] clientChallenge; + protected byte[] clientChallenge2; protected byte[] secondaryKey; protected byte[] timestamp; @@ -271,6 +268,7 @@ final class NTLMEngineImpl implements NTLMEngine { protected byte[] ntlmHash = null; protected byte[] ntlmResponse = null; protected byte[] ntlmv2Hash = null; + protected byte[] lmv2Hash = null; protected byte[] lmv2Response = null; protected byte[] ntlmv2Blob = null; protected byte[] ntlmv2Response = null; @@ -282,84 +280,96 @@ final class NTLMEngineImpl implements NTLMEngine { protected byte[] ntlm2SessionResponseUserSessionKey = null; protected byte[] lanManagerSessionKey = null; - public CipherGen(final String target, final String user, final String password, - final byte[] challenge, final byte[] targetInformation, - final byte[] clientChallenge, final byte[] secondaryKey, final byte[] timestamp) { + public CipherGen(String domain, String user, String password, + byte[] challenge, String target, byte[] targetInformation, + byte[] clientChallenge, byte[] clientChallenge2, + byte[] secondaryKey, byte[] timestamp) { + this.domain = domain; this.target = target; this.user = user; this.password = password; this.challenge = challenge; this.targetInformation = targetInformation; this.clientChallenge = clientChallenge; + this.clientChallenge2 = clientChallenge2; this.secondaryKey = secondaryKey; this.timestamp = timestamp; } - public CipherGen(final String target, final String user, final String password, - final byte[] challenge, final byte[] targetInformation) { - this(target, user, password, challenge, targetInformation, null, null, null); + public CipherGen(String domain, String user, String password, + byte[] challenge, String target, byte[] targetInformation) { + this(domain, user, password, challenge, target, targetInformation, null, null, null, null); } /** Calculate and return client challenge */ public byte[] getClientChallenge() throws NTLMEngineException { - if (clientChallenge == null) { + if (clientChallenge == null) clientChallenge = makeRandomChallenge(); - } return clientChallenge; } + /** Calculate and return second client challenge */ + public byte[] getClientChallenge2() + throws NTLMEngineException { + if (clientChallenge2 == null) + clientChallenge2 = makeRandomChallenge(); + return clientChallenge2; + } + /** Calculate and return random secondary key */ public byte[] getSecondaryKey() throws NTLMEngineException { - if (secondaryKey == null) { + if (secondaryKey == null) secondaryKey = makeSecondaryKey(); - } return secondaryKey; } /** Calculate and return the LMHash */ public byte[] getLMHash() throws NTLMEngineException { - if (lmHash == null) { + if (lmHash == null) lmHash = lmHash(password); - } return lmHash; } /** Calculate and return the LMResponse */ public byte[] getLMResponse() throws NTLMEngineException { - if (lmResponse == null) { + if (lmResponse == null) lmResponse = lmResponse(getLMHash(),challenge); - } return lmResponse; } /** Calculate and return the NTLMHash */ public byte[] getNTLMHash() throws NTLMEngineException { - if (ntlmHash == null) { + if (ntlmHash == null) ntlmHash = ntlmHash(password); - } return ntlmHash; } /** Calculate and return the NTLMResponse */ public byte[] getNTLMResponse() throws NTLMEngineException { - if (ntlmResponse == null) { + if (ntlmResponse == null) ntlmResponse = lmResponse(getNTLMHash(),challenge); - } return ntlmResponse; } + /** Calculate the LMv2 hash */ + public byte[] getLMv2Hash() + throws NTLMEngineException { + if (lmv2Hash == null) + lmv2Hash = lmv2Hash(domain, user, getNTLMHash()); + return lmv2Hash; + } + /** Calculate the NTLMv2 hash */ public byte[] getNTLMv2Hash() throws NTLMEngineException { - if (ntlmv2Hash == null) { - ntlmv2Hash = ntlmv2Hash(target, user, password); - } + if (ntlmv2Hash == null) + ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash()); return ntlmv2Hash; } @@ -382,36 +392,32 @@ final class NTLMEngineImpl implements NTLMEngine { /** Calculate the NTLMv2Blob */ public byte[] getNTLMv2Blob() throws NTLMEngineException { - if (ntlmv2Blob == null) { - ntlmv2Blob = createBlob(getClientChallenge(), targetInformation, getTimestamp()); - } + if (ntlmv2Blob == null) + ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp()); return ntlmv2Blob; } /** Calculate the NTLMv2Response */ public byte[] getNTLMv2Response() throws NTLMEngineException { - if (ntlmv2Response == null) { + if (ntlmv2Response == null) ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob()); - } return ntlmv2Response; } /** Calculate the LMv2Response */ public byte[] getLMv2Response() throws NTLMEngineException { - if (lmv2Response == null) { - lmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getClientChallenge()); - } + if (lmv2Response == null) + lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge()); return lmv2Response; } /** Get NTLM2SessionResponse */ public byte[] getNTLM2SessionResponse() throws NTLMEngineException { - if (ntlm2SessionResponse == null) { + if (ntlm2SessionResponse == null) ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge()); - } return ntlm2SessionResponse; } @@ -419,7 +425,7 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getLM2SessionResponse() throws NTLMEngineException { if (lm2SessionResponse == null) { - final byte[] clientChallenge = getClientChallenge(); + byte[] clientChallenge = getClientChallenge(); lm2SessionResponse = new byte[24]; System.arraycopy(clientChallenge, 0, lm2SessionResponse, 0, clientChallenge.length); Arrays.fill(lm2SessionResponse, clientChallenge.length, lm2SessionResponse.length, (byte) 0x00); @@ -431,7 +437,7 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getLMUserSessionKey() throws NTLMEngineException { if (lmUserSessionKey == null) { - final byte[] lmHash = getLMHash(); + byte[] lmHash = getLMHash(); lmUserSessionKey = new byte[16]; System.arraycopy(lmHash, 0, lmUserSessionKey, 0, 8); Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00); @@ -443,8 +449,8 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getNTLMUserSessionKey() throws NTLMEngineException { if (ntlmUserSessionKey == null) { - final byte[] ntlmHash = getNTLMHash(); - final MD4 md4 = new MD4(); + byte[] ntlmHash = getNTLMHash(); + MD4 md4 = new MD4(); md4.update(ntlmHash); ntlmUserSessionKey = md4.getOutput(); } @@ -455,14 +461,10 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getNTLMv2UserSessionKey() throws NTLMEngineException { if (ntlmv2UserSessionKey == null) { - final byte[] ntlmv2Hash = getNTLMv2Hash(); - final byte[] ntlmv2Blob = getNTLMv2Blob(); - final byte[] temp = new byte[ntlmv2Blob.length + challenge.length]; - // "The challenge is concatenated with the blob" - check this (MHL) - System.arraycopy(challenge, 0, temp, 0, challenge.length); - System.arraycopy(ntlmv2Blob, 0, temp, challenge.length, ntlmv2Blob.length); - final byte[] partial = hmacMD5(temp,ntlmv2Hash); - ntlmv2UserSessionKey = hmacMD5(partial,ntlmv2Hash); + byte[] ntlmv2hash = getNTLMv2Hash(); + byte[] truncatedResponse = new byte[16]; + System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16); + ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash); } return ntlmv2UserSessionKey; } @@ -471,9 +473,9 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getNTLM2SessionResponseUserSessionKey() throws NTLMEngineException { if (ntlm2SessionResponseUserSessionKey == null) { - final byte[] ntlmUserSessionKey = getNTLMUserSessionKey(); - final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); - final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; + byte[] ntlmUserSessionKey = getNTLMUserSessionKey(); + byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); + byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length); System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length); ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,ntlmUserSessionKey); @@ -485,26 +487,26 @@ final class NTLMEngineImpl implements NTLMEngine { public byte[] getLanManagerSessionKey() throws NTLMEngineException { if (lanManagerSessionKey == null) { - final byte[] lmHash = getLMHash(); - final byte[] lmResponse = getLMResponse(); + byte[] lmHash = getLMHash(); + byte[] lmResponse = getLMResponse(); try { - final byte[] keyBytes = new byte[14]; + byte[] keyBytes = new byte[14]; System.arraycopy(lmHash, 0, keyBytes, 0, 8); Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] truncatedResponse = new byte[8]; + Key lowKey = createDESKey(keyBytes, 0); + Key highKey = createDESKey(keyBytes, 7); + byte[] truncatedResponse = new byte[8]; System.arraycopy(lmResponse, 0, truncatedResponse, 0, truncatedResponse.length); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowPart = des.doFinal(truncatedResponse); + byte[] lowPart = des.doFinal(truncatedResponse); des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highPart = des.doFinal(truncatedResponse); + byte[] highPart = des.doFinal(truncatedResponse); lanManagerSessionKey = new byte[16]; System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length); System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length); - } catch (final Exception e) { + } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } @@ -513,21 +515,21 @@ final class NTLMEngineImpl implements NTLMEngine { } /** Calculates HMAC-MD5 */ - static byte[] hmacMD5(final byte[] value, final byte[] key) + static byte[] hmacMD5(byte[] value, byte[] key) throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(key); + HMACMD5 hmacMD5 = new HMACMD5(key); hmacMD5.update(value); return hmacMD5.getOutput(); } /** Calculates RC4 */ - static byte[] RC4(final byte[] value, final byte[] key) + static byte[] RC4(byte[] value, byte[] key) throws NTLMEngineException { try { - final Cipher rc4 = Cipher.getInstance("RC4"); + Cipher rc4 = Cipher.getInstance("RC4"); rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4")); return rc4.doFinal(value); - } catch (final Exception e) { + } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } @@ -547,8 +549,8 @@ final class NTLMEngineImpl implements NTLMEngine { * field of the Type 3 message; the LM response field contains the * client challenge, null-padded to 24 bytes. */ - static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, - final byte[] clientChallenge) throws NTLMEngineException { + static byte[] ntlm2SessionResponse(byte[] ntlmHash, byte[] challenge, + byte[] clientChallenge) throws NTLMEngineException { try { // Look up MD5 algorithm (was necessary on jdk 1.4.2) // This used to be needed, but java 1.5.0_07 includes the MD5 @@ -563,18 +565,17 @@ final class NTLMEngineImpl implements NTLMEngine { // byte[] digest = (byte[])digestMethod.invoke(mdInstance,new // Object[0]); - final MessageDigest md5 = MessageDigest.getInstance("MD5"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(challenge); md5.update(clientChallenge); - final byte[] digest = md5.digest(); + byte[] digest = md5.digest(); - final byte[] sessionHash = new byte[8]; + byte[] sessionHash = new byte[8]; System.arraycopy(digest, 0, sessionHash, 0, 8); return lmResponse(ntlmHash, sessionHash); - } catch (final Exception e) { - if (e instanceof NTLMEngineException) { + } catch (Exception e) { + if (e instanceof NTLMEngineException) throw (NTLMEngineException) e; - } throw new NTLMEngineException(e.getMessage(), e); } } @@ -588,25 +589,25 @@ final class NTLMEngineImpl implements NTLMEngine { * @return The LM Hash of the given password, used in the calculation of the * LM Response. */ - private static byte[] lmHash(final String password) throws NTLMEngineException { + private static byte[] lmHash(String password) throws NTLMEngineException { try { - final byte[] oemPassword = password.toUpperCase(Locale.US).getBytes("US-ASCII"); - final int length = Math.min(oemPassword.length, 14); - final byte[] keyBytes = new byte[14]; + byte[] oemPassword = password.toUpperCase(Locale.US).getBytes("US-ASCII"); + int length = Math.min(oemPassword.length, 14); + byte[] keyBytes = new byte[14]; System.arraycopy(oemPassword, 0, keyBytes, 0, length); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII"); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + Key lowKey = createDESKey(keyBytes, 0); + Key highKey = createDESKey(keyBytes, 7); + byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII"); + Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowHash = des.doFinal(magicConstant); + byte[] lowHash = des.doFinal(magicConstant); des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highHash = des.doFinal(magicConstant); - final byte[] lmHash = new byte[16]; + byte[] highHash = des.doFinal(magicConstant); + byte[] lmHash = new byte[16]; System.arraycopy(lowHash, 0, lmHash, 0, 8); System.arraycopy(highHash, 0, lmHash, 8, 8); return lmHash; - } catch (final Exception e) { + } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } @@ -620,17 +621,43 @@ final class NTLMEngineImpl implements NTLMEngine { * @return The NTLM Hash of the given password, used in the calculation of * the NTLM Response and the NTLMv2 and LMv2 Hashes. */ - private static byte[] ntlmHash(final String password) throws NTLMEngineException { + private static byte[] ntlmHash(String password) throws NTLMEngineException { try { - final byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked"); - final MD4 md4 = new MD4(); + byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked"); + MD4 md4 = new MD4(); md4.update(unicodePassword); return md4.getOutput(); - } catch (final java.io.UnsupportedEncodingException e) { + } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e); } } + /** + * Creates the LMv2 Hash of the user's password. + * + * @param target + * The authentication target (i.e., domain). + * @param user + * The username. + * @param password + * The password. + * + * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2 + * Responses. + */ + private static byte[] lmv2Hash(String domain, String user, byte[] ntlmHash) + throws NTLMEngineException { + try { + HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + // Upper case username, upper case domain! + hmacMD5.update(user.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked")); + hmacMD5.update(domain.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked")); + return hmacMD5.getOutput(); + } catch (java.io.UnsupportedEncodingException e) { + throw new NTLMEngineException("Unicode not supported! " + e.getMessage(), e); + } + } + /** * Creates the NTLMv2 Hash of the user's password. * @@ -644,16 +671,15 @@ final class NTLMEngineImpl implements NTLMEngine { * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 * Responses. */ - private static byte[] ntlmv2Hash(final String target, final String user, final String password) + private static byte[] ntlmv2Hash(String domain, String user, byte[] ntlmHash) throws NTLMEngineException { try { - final byte[] ntlmHash = ntlmHash(password); - final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); // Upper case username, mixed case target!! hmacMD5.update(user.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked")); - hmacMD5.update(target.getBytes("UnicodeLittleUnmarked")); + hmacMD5.update(domain.getBytes("UnicodeLittleUnmarked")); return hmacMD5.getOutput(); - } catch (final java.io.UnsupportedEncodingException e) { + } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported! " + e.getMessage(), e); } } @@ -668,26 +694,26 @@ final class NTLMEngineImpl implements NTLMEngine { * * @return The response (either LM or NTLM, depending on the provided hash). */ - private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException { + private static byte[] lmResponse(byte[] hash, byte[] challenge) throws NTLMEngineException { try { - final byte[] keyBytes = new byte[21]; + byte[] keyBytes = new byte[21]; System.arraycopy(hash, 0, keyBytes, 0, 16); - final Key lowKey = createDESKey(keyBytes, 0); - final Key middleKey = createDESKey(keyBytes, 7); - final Key highKey = createDESKey(keyBytes, 14); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + Key lowKey = createDESKey(keyBytes, 0); + Key middleKey = createDESKey(keyBytes, 7); + Key highKey = createDESKey(keyBytes, 14); + Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowResponse = des.doFinal(challenge); + byte[] lowResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, middleKey); - final byte[] middleResponse = des.doFinal(challenge); + byte[] middleResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highResponse = des.doFinal(challenge); - final byte[] lmResponse = new byte[24]; + byte[] highResponse = des.doFinal(challenge); + byte[] lmResponse = new byte[24]; System.arraycopy(lowResponse, 0, lmResponse, 0, 8); System.arraycopy(middleResponse, 0, lmResponse, 8, 8); System.arraycopy(highResponse, 0, lmResponse, 16, 8); return lmResponse; - } catch (final Exception e) { + } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } @@ -706,13 +732,13 @@ final class NTLMEngineImpl implements NTLMEngine { * @return The response (either NTLMv2 or LMv2, depending on the client * data). */ - private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) + private static byte[] lmv2Response(byte[] hash, byte[] challenge, byte[] clientData) throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(hash); + HMACMD5 hmacMD5 = new HMACMD5(hash); hmacMD5.update(challenge); hmacMD5.update(clientData); - final byte[] mac = hmacMD5.getOutput(); - final byte[] lmv2Response = new byte[mac.length + clientData.length]; + byte[] mac = hmacMD5.getOutput(); + byte[] lmv2Response = new byte[mac.length + clientData.length]; System.arraycopy(mac, 0, lmv2Response, 0, mac.length); System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); return lmv2Response; @@ -729,12 +755,12 @@ final class NTLMEngineImpl implements NTLMEngine { * * @return The blob, used in the calculation of the NTLMv2 Response. */ - private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) { - final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; - final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 + private static byte[] createBlob(byte[] clientChallenge, byte[] targetInformation, byte[] timestamp) { + byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; + byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 + unknown1.length + targetInformation.length + unknown2.length]; int offset = 0; System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); @@ -766,10 +792,10 @@ final class NTLMEngineImpl implements NTLMEngine { * @return A DES encryption key created from the key material starting at * the specified offset in the given byte array. */ - private static Key createDESKey(final byte[] bytes, final int offset) { - final byte[] keyBytes = new byte[7]; + private static Key createDESKey(byte[] bytes, int offset) { + byte[] keyBytes = new byte[7]; System.arraycopy(bytes, offset, keyBytes, 0, 7); - final byte[] material = new byte[8]; + byte[] material = new byte[8]; material[0] = keyBytes[0]; material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); @@ -788,10 +814,10 @@ final class NTLMEngineImpl implements NTLMEngine { * @param bytes * The data whose parity bits are to be adjusted for odd parity. */ - private static void oddParity(final byte[] bytes) { + private static void oddParity(byte[] bytes) { for (int i = 0; i < bytes.length; i++) { - final byte b = bytes[i]; - final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) + byte b = bytes[i]; + boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; if (needsParity) { bytes[i] |= (byte) 0x01; @@ -814,28 +840,25 @@ final class NTLMEngineImpl implements NTLMEngine { } /** Constructor to use when message contents are known */ - NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { + NTLMMessage(String messageBody, int expectedType) throws NTLMEngineException { messageContents = Base64.decodeBase64(EncodingUtils.getBytes(messageBody, DEFAULT_CHARSET)); // Look for NTLM message - if (messageContents.length < SIGNATURE.length) { + if (messageContents.length < SIGNATURE.length) throw new NTLMEngineException("NTLM message decoding error - packet too short"); - } int i = 0; while (i < SIGNATURE.length) { - if (messageContents[i] != SIGNATURE[i]) { + if (messageContents[i] != SIGNATURE[i]) throw new NTLMEngineException( "NTLM message expected - instead got unrecognized bytes"); - } i++; } // Check to be sure there's a type 2 message indicator next - final int type = readULong(SIGNATURE.length); - if (type != expectedType) { + int type = readULong(SIGNATURE.length); + if (type != expectedType) throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) + " message expected - instead got type " + Integer.toString(type)); - } currentOutputPosition = messageContents.length; } @@ -854,33 +877,31 @@ final class NTLMEngineImpl implements NTLMEngine { } /** Read a byte from a position within the message buffer */ - protected byte readByte(final int position) throws NTLMEngineException { - if (messageContents.length < position + 1) { + protected byte readByte(int position) throws NTLMEngineException { + if (messageContents.length < position + 1) throw new NTLMEngineException("NTLM: Message too short"); - } return messageContents[position]; } /** Read a bunch of bytes from a position in the message buffer */ - protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException { - if (messageContents.length < position + buffer.length) { + protected void readBytes(byte[] buffer, int position) throws NTLMEngineException { + if (messageContents.length < position + buffer.length) throw new NTLMEngineException("NTLM: Message too short"); - } System.arraycopy(messageContents, position, buffer, 0, buffer.length); } /** Read a ushort from a position within the message buffer */ - protected int readUShort(final int position) throws NTLMEngineException { + protected int readUShort(int position) throws NTLMEngineException { return NTLMEngineImpl.readUShort(messageContents, position); } /** Read a ulong from a position within the message buffer */ - protected int readULong(final int position) throws NTLMEngineException { + protected int readULong(int position) throws NTLMEngineException { return NTLMEngineImpl.readULong(messageContents, position); } /** Read a security buffer from a position within the message buffer */ - protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException { + protected byte[] readSecurityBuffer(int position) throws NTLMEngineException { return NTLMEngineImpl.readSecurityBuffer(messageContents, position); } @@ -892,7 +913,7 @@ final class NTLMEngineImpl implements NTLMEngine { * including the type and the signature (which this method * adds). */ - protected void prepareResponse(final int maxlength, final int messageType) { + protected void prepareResponse(int maxlength, int messageType) { messageContents = new byte[maxlength]; currentOutputPosition = 0; addBytes(SIGNATURE); @@ -905,7 +926,7 @@ final class NTLMEngineImpl implements NTLMEngine { * @param b * the byte to add. */ - protected void addByte(final byte b) { + protected void addByte(byte b) { messageContents[currentOutputPosition] = b; currentOutputPosition++; } @@ -916,21 +937,21 @@ final class NTLMEngineImpl implements NTLMEngine { * @param bytes * the bytes to add. */ - protected void addBytes(final byte[] bytes) { - for (final byte b : bytes) { + protected void addBytes(byte[] bytes) { + for (byte b : bytes) { messageContents[currentOutputPosition] = b; currentOutputPosition++; } } /** Adds a USHORT to the response */ - protected void addUShort(final int value) { + protected void addUShort(int value) { addByte((byte) (value & 0xff)); addByte((byte) (value >> 8 & 0xff)); } /** Adds a ULong to the response */ - protected void addULong(final int value) { + protected void addULong(int value) { addByte((byte) (value & 0xff)); addByte((byte) (value >> 8 & 0xff)); addByte((byte) (value >> 16 & 0xff)); @@ -946,7 +967,7 @@ final class NTLMEngineImpl implements NTLMEngine { String getResponse() { byte[] resp; if (messageContents.length > currentOutputPosition) { - final byte[] tmp = new byte[currentOutputPosition]; + byte[] tmp = new byte[currentOutputPosition]; for (int i = 0; i < currentOutputPosition; i++) { tmp[i] = messageContents[i]; } @@ -969,13 +990,13 @@ final class NTLMEngineImpl implements NTLMEngine { super(); try { // Strip off domain name from the host! - host = convertHost(host); + String unqualifiedHost = convertHost(host); // Use only the base domain name! - domain = convertDomain(domain); + String unqualifiedDomain = convertDomain(domain); - hostBytes = host.getBytes("UnicodeLittleUnmarked"); - domainBytes = domain.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked"); - } catch (final java.io.UnsupportedEncodingException e) { + hostBytes = unqualifiedHost.getBytes("ASCII"); + domainBytes = unqualifiedDomain.toUpperCase(Locale.US).getBytes("ASCII"); + } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode unsupported: " + e.getMessage(), e); } } @@ -988,7 +1009,7 @@ final class NTLMEngineImpl implements NTLMEngine { String getResponse() { // Now, build the message. Calculate its length first, including // signature or type. - final int finalLength = 32 + 8 /*+ hostBytes.length + domainBytes.length */; + int finalLength = 32 + 8 /*+ hostBytes.length + domainBytes.length */; // Set up the response. This will initialize the signature, message // type, and flags. @@ -1000,7 +1021,7 @@ final class NTLMEngineImpl implements NTLMEngine { //FLAG_DOMAIN_PRESENT | // Required flags - FLAG_REQUEST_LAN_MANAGER_KEY | + //FLAG_REQUEST_LAN_MANAGER_KEY | FLAG_REQUEST_NTLMv1 | FLAG_REQUEST_NTLM2_SESSION | @@ -1010,12 +1031,12 @@ final class NTLMEngineImpl implements NTLMEngine { // Recommended privacy settings FLAG_REQUEST_ALWAYS_SIGN | //FLAG_REQUEST_SEAL | - FLAG_REQUEST_SIGN | + //FLAG_REQUEST_SIGN | // These must be set according to documentation, based on use of SEAL above FLAG_REQUEST_128BIT_KEY_EXCH | FLAG_REQUEST_56BIT_ENCRYPTION | - FLAG_REQUEST_EXPLICIT_KEY_EXCH | + //FLAG_REQUEST_EXPLICIT_KEY_EXCH | FLAG_REQUEST_UNICODE_ENCODING); @@ -1060,7 +1081,7 @@ final class NTLMEngineImpl implements NTLMEngine { protected byte[] targetInfo; protected int flags; - Type2Message(final String message) throws NTLMEngineException { + Type2Message(String message) throws NTLMEngineException { super(message, 2); // Type 2 message is laid out as follows: @@ -1083,11 +1104,10 @@ final class NTLMEngineImpl implements NTLMEngine { flags = readULong(20); - if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { + if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) throw new NTLMEngineException( "NTLM type 2 message has flags that make no sense: " + Integer.toString(flags)); - } // Do the target! target = null; @@ -1095,11 +1115,11 @@ final class NTLMEngineImpl implements NTLMEngine { // in Type2 messages, so use the length of the packet to decide // how to proceed instead if (getMessageLength() >= 12 + 8) { - final byte[] bytes = readSecurityBuffer(12); + byte[] bytes = readSecurityBuffer(12); if (bytes.length != 0) { try { target = new String(bytes, "UnicodeLittleUnmarked"); - } catch (final java.io.UnsupportedEncodingException e) { + } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException(e.getMessage(), e); } } @@ -1109,7 +1129,7 @@ final class NTLMEngineImpl implements NTLMEngine { targetInfo = null; // TARGET_DESIRED flag cannot be relied on, so use packet length if (getMessageLength() >= 40 + 8) { - final byte[] bytes = readSecurityBuffer(40); + byte[] bytes = readSecurityBuffer(40); if (bytes.length != 0) { targetInfo = bytes; } @@ -1153,19 +1173,19 @@ final class NTLMEngineImpl implements NTLMEngine { /** Constructor. Pass the arguments we will need */ - Type3Message(String domain, String host, final String user, final String password, final byte[] nonce, - final int type2Flags, final String target, final byte[] targetInformation) + Type3Message(String domain, String host, String user, String password, byte[] nonce, + int type2Flags, String target, byte[] targetInformation) throws NTLMEngineException { // Save the flags this.type2Flags = type2Flags; // Strip off domain name from the host! - host = convertHost(host); + String unqualifiedHost = convertHost(host); // Use only the base domain name! - domain = convertDomain(domain); + String unqualifiedDomain = convertDomain(domain); - // Create a cipher generator class - final CipherGen gen = new CipherGen(target, user, password, nonce, targetInformation); + // Create a cipher generator class. Use domain BEFORE it gets modified! + CipherGen gen = new CipherGen(unqualifiedDomain, user, password, nonce, target, targetInformation); // Use the new code to calculate the responses, including v2 if that // seems warranted. @@ -1178,60 +1198,54 @@ final class NTLMEngineImpl implements NTLMEngine { // NTLMv2 ntResp = gen.getNTLMv2Response(); lmResp = gen.getLMv2Response(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) userSessionKey = gen.getLanManagerSessionKey(); - } else { + else userSessionKey = gen.getNTLMv2UserSessionKey(); - } } else { // NTLMv1 if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) { // NTLM2 session stuff is requested ntResp = gen.getNTLM2SessionResponse(); lmResp = gen.getLM2SessionResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) userSessionKey = gen.getLanManagerSessionKey(); - } - else { + else userSessionKey = gen.getNTLM2SessionResponseUserSessionKey(); - // All the other flags we send (signing, sealing, key - // exchange) are supported, but they don't do anything - // at all in an - // NTLM2 context! So we're done at this point. - } } else { ntResp = gen.getNTLMResponse(); lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) userSessionKey = gen.getLanManagerSessionKey(); - } else { + else userSessionKey = gen.getNTLMUserSessionKey(); - } } } - } catch (final NTLMEngineException e) { + } catch (NTLMEngineException e) { // This likely means we couldn't find the MD4 hash algorithm - // fail back to just using LM ntResp = new byte[0]; lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) userSessionKey = gen.getLanManagerSessionKey(); - } else { + else userSessionKey = gen.getLMUserSessionKey(); - } } - if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { - sessionKey = RC4(gen.getSecondaryKey(), userSessionKey); + if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { + if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) + sessionKey = RC4(gen.getSecondaryKey(), userSessionKey); + else + sessionKey = userSessionKey; } else { sessionKey = null; } try { - domainBytes = domain.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked"); - hostBytes = host.getBytes("UnicodeLittleUnmarked"); + domainBytes = unqualifiedDomain.toUpperCase(Locale.US).getBytes("UnicodeLittleUnmarked"); + hostBytes = unqualifiedHost.getBytes("UnicodeLittleUnmarked"); userBytes = user.getBytes("UnicodeLittleUnmarked"); - } catch (final java.io.UnsupportedEncodingException e) { + } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e); } } @@ -1239,27 +1253,26 @@ final class NTLMEngineImpl implements NTLMEngine { /** Assemble the response */ @Override String getResponse() { - final int ntRespLen = ntResp.length; - final int lmRespLen = lmResp.length; + int ntRespLen = ntResp.length; + int lmRespLen = lmResp.length; - final int domainLen = domainBytes.length; - final int hostLen = hostBytes.length; - final int userLen = userBytes.length; + int domainLen = domainBytes.length; + int hostLen = hostBytes.length; + int userLen = userBytes.length; int sessionKeyLen; - if (sessionKey != null) { + if (sessionKey != null) sessionKeyLen = sessionKey.length; - } else { + else sessionKeyLen = 0; - } // Calculate the layout within the packet - final int lmRespOffset = 72; // allocate space for the version - final int ntRespOffset = lmRespOffset + lmRespLen; - final int domainOffset = ntRespOffset + ntRespLen; - final int userOffset = domainOffset + domainLen; - final int hostOffset = userOffset + userLen; - final int sessionKeyOffset = hostOffset + hostLen; - final int finalLength = sessionKeyOffset + sessionKeyLen; + int lmRespOffset = 72; // allocate space for the version + int ntRespOffset = lmRespOffset + lmRespLen; + int domainOffset = ntRespOffset + ntRespLen; + int userOffset = domainOffset + domainLen; + int hostOffset = userOffset + userLen; + int sessionKeyOffset = hostOffset + hostLen; + int finalLength = sessionKeyOffset + sessionKeyLen; // Start the response. Length includes signature and type prepareResponse(finalLength, 3); @@ -1306,11 +1319,10 @@ final class NTLMEngineImpl implements NTLMEngine { // Session key offset addULong(sessionKeyOffset); - // Flags. Currently: WORKSTATION_PRESENT + DOMAIN_PRESENT + UNICODE_ENCODING + - // TARGET_DESIRED + NEGOTIATE_128 + // Flags. addULong( - FLAG_WORKSTATION_PRESENT | - FLAG_DOMAIN_PRESENT | + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | // Required flags (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) | @@ -1348,34 +1360,33 @@ final class NTLMEngineImpl implements NTLMEngine { addBytes(domainBytes); addBytes(userBytes); addBytes(hostBytes); - if (sessionKey != null) { + if (sessionKey != null) addBytes(sessionKey); - } return super.getResponse(); } } - static void writeULong(final byte[] buffer, final int value, final int offset) { + static void writeULong(byte[] buffer, int value, int offset) { buffer[offset] = (byte) (value & 0xff); buffer[offset + 1] = (byte) (value >> 8 & 0xff); buffer[offset + 2] = (byte) (value >> 16 & 0xff); buffer[offset + 3] = (byte) (value >> 24 & 0xff); } - static int F(final int x, final int y, final int z) { + static int F(int x, int y, int z) { return ((x & y) | (~x & z)); } - static int G(final int x, final int y, final int z) { + static int G(int x, int y, int z) { return ((x & y) | (x & z) | (y & z)); } - static int H(final int x, final int y, final int z) { + static int H(int x, int y, int z) { return (x ^ y ^ z); } - static int rotintlft(final int val, final int numbits) { + static int rotintlft(int val, int numbits) { return ((val << numbits) | (val >>> (32 - numbits))); } @@ -1397,7 +1408,7 @@ final class NTLMEngineImpl implements NTLMEngine { MD4() { } - void update(final byte[] input) { + void update(byte[] input) { // We always deal with 512 bits at a time. Correspondingly, there is // a buffer 64 bytes long that we write data into until it gets // full. @@ -1407,7 +1418,7 @@ final class NTLMEngineImpl implements NTLMEngine { // We have enough data to do the next step. Do a partial copy // and a transform, updating inputIndex and curBufferPos // accordingly - final int transferAmt = dataBuffer.length - curBufferPos; + int transferAmt = dataBuffer.length - curBufferPos; System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); count += transferAmt; curBufferPos = 0; @@ -1418,7 +1429,7 @@ final class NTLMEngineImpl implements NTLMEngine { // If there's anything left, copy it into the buffer and leave it. // We know there's not enough left to process. if (inputIndex < input.length) { - final int transferAmt = input.length - inputIndex; + int transferAmt = input.length - inputIndex; System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); count += transferAmt; curBufferPos += transferAmt; @@ -1428,9 +1439,9 @@ final class NTLMEngineImpl implements NTLMEngine { byte[] getOutput() { // Feed pad/length data into engine. This must round out the input // to a multiple of 512 bits. - final int bufferIndex = (int) (count & 63L); - final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); - final byte[] postBytes = new byte[padLen + 8]; + int bufferIndex = (int) (count & 63L); + int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); + byte[] postBytes = new byte[padLen + 8]; // Leading 0x80, specified amount of zero padding, then length in // bits. postBytes[0] = (byte) 0x80; @@ -1443,7 +1454,7 @@ final class NTLMEngineImpl implements NTLMEngine { update(postBytes); // Calculate final result - final byte[] result = new byte[16]; + byte[] result = new byte[16]; writeULong(result, A, 0); writeULong(result, B, 4); writeULong(result, C, 8); @@ -1453,7 +1464,7 @@ final class NTLMEngineImpl implements NTLMEngine { protected void processBuffer() { // Convert current buffer to 16 ulongs - final int[] d = new int[16]; + int[] d = new int[16]; for (int i = 0; i < 16; i++) { d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) @@ -1462,10 +1473,10 @@ final class NTLMEngineImpl implements NTLMEngine { } // Do a round of processing - final int AA = A; - final int BB = B; - final int CC = C; - final int DD = D; + int AA = A; + int BB = B; + int CC = C; + int DD = D; round1(d); round2(d); round3(d); @@ -1476,7 +1487,7 @@ final class NTLMEngineImpl implements NTLMEngine { } - protected void round1(final int[] d) { + protected void round1(int[] d) { A = rotintlft((A + F(B, C, D) + d[0]), 3); D = rotintlft((D + F(A, B, C) + d[1]), 7); C = rotintlft((C + F(D, A, B) + d[2]), 11); @@ -1498,7 +1509,7 @@ final class NTLMEngineImpl implements NTLMEngine { B = rotintlft((B + F(C, D, A) + d[15]), 19); } - protected void round2(final int[] d) { + protected void round2(int[] d) { A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); @@ -1521,7 +1532,7 @@ final class NTLMEngineImpl implements NTLMEngine { } - protected void round3(final int[] d) { + protected void round3(int[] d) { A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); @@ -1558,7 +1569,7 @@ final class NTLMEngineImpl implements NTLMEngine { HMACMD5(byte[] key) throws NTLMEngineException { try { md5 = MessageDigest.getInstance("MD5"); - } catch (final Exception ex) { + } catch (Exception ex) { // Umm, the algorithm doesn't exist - throw an // NTLMEngineException! throw new NTLMEngineException( @@ -1596,18 +1607,18 @@ final class NTLMEngineImpl implements NTLMEngine { /** Grab the current digest. This is the "answer". */ byte[] getOutput() { - final byte[] digest = md5.digest(); + byte[] digest = md5.digest(); md5.update(opad); return md5.digest(digest); } /** Update by adding a complete array */ - void update(final byte[] input) { + void update(byte[] input) { md5.update(input); } /** Update the algorithm */ - void update(final byte[] input, final int offset, final int length) { + void update(byte[] input, int offset, int length) { md5.update(input, offset, length); } @@ -1625,7 +1636,7 @@ final class NTLMEngineImpl implements NTLMEngine { final String domain, final String workstation, final String challenge) throws NTLMEngineException { - final Type2Message t2m = new Type2Message(challenge); + Type2Message t2m = new Type2Message(challenge); return getType3Message( username, password, diff --git a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java index e857b13c2..87e5e6865 100644 --- a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java +++ b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java @@ -95,6 +95,8 @@ public class TestNTLMEngineImpl { null, null, null, + null, + null, null); checkArraysMatch(toBytes("c337cd5cbd44fc9782a667af6d427c6de67c20c2d3e77c56"), @@ -111,6 +113,8 @@ public class TestNTLMEngineImpl { null, null, null, + null, + null, null); checkArraysMatch(toBytes("25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6"), @@ -124,8 +128,10 @@ public class TestNTLMEngineImpl { "user", "SecREt01", toBytes("0123456789abcdef"), + "DOMAIN", null, toBytes("ffffff0011223344"), + toBytes("ffffff0011223344"), null, null); @@ -140,8 +146,10 @@ public class TestNTLMEngineImpl { "user", "SecREt01", toBytes("0123456789abcdef"), + "DOMAIN", toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"), toBytes("ffffff0011223344"), + toBytes("ffffff0011223344"), null, toBytes("0090d336b734c301")); @@ -158,8 +166,10 @@ public class TestNTLMEngineImpl { "user", "SecREt01", toBytes("0123456789abcdef"), + "DOMAIN", toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"), toBytes("ffffff0011223344"), + toBytes("ffffff0011223344"), null, toBytes("0090d336b734c301")); @@ -174,8 +184,10 @@ public class TestNTLMEngineImpl { "user", "SecREt01", toBytes("0123456789abcdef"), + "DOMAIN", toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"), toBytes("ffffff0011223344"), + toBytes("ffffff0011223344"), null, toBytes("0090d336b734c301")); @@ -190,8 +202,10 @@ public class TestNTLMEngineImpl { "user", "SecREt01", toBytes("0123456789abcdef"), + "DOMAIN", toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"), toBytes("ffffff0011223344"), + toBytes("ffffff0011223344"), null, toBytes("0090d336b734c301"));