in httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/NTLMEngineImpl.java [1626:1760]
void buildMessage() {
final int ntRespLen = ntResp.length;
final int lmRespLen = lmResp.length;
final int domainLen = domainBytes != null ? domainBytes.length : 0;
final int hostLen = hostBytes != null ? hostBytes.length: 0;
final int userLen = userBytes.length;
final int sessionKeyLen;
if (sessionKey != null) {
sessionKeyLen = sessionKey.length;
} else {
sessionKeyLen = 0;
}
// Calculate the layout within the packet
final int lmRespOffset = 72 + // allocate space for the version
( computeMic ? 16 : 0 ); // and MIC
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;
// Start the response. Length includes signature and type
prepareResponse(finalLength, 3);
// LM Resp Length (twice)
addUShort(lmRespLen);
addUShort(lmRespLen);
// LM Resp Offset
addULong(lmRespOffset);
// NT Resp Length (twice)
addUShort(ntRespLen);
addUShort(ntRespLen);
// NT Resp Offset
addULong(ntRespOffset);
// Domain length (twice)
addUShort(domainLen);
addUShort(domainLen);
// Domain offset.
addULong(domainOffset);
// User Length (twice)
addUShort(userLen);
addUShort(userLen);
// User offset
addULong(userOffset);
// Host length (twice)
addUShort(hostLen);
addUShort(hostLen);
// Host offset
addULong(hostOffset);
// Session key length (twice)
addUShort(sessionKeyLen);
addUShort(sessionKeyLen);
// Session key offset
addULong(sessionKeyOffset);
// Flags.
addULong(
/*
//FLAG_WORKSTATION_PRESENT |
//FLAG_DOMAIN_PRESENT |
// Required flags
(type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) |
(type2Flags & FLAG_REQUEST_NTLMv1) |
(type2Flags & FLAG_REQUEST_NTLM2_SESSION) |
// Protocol version request
FLAG_REQUEST_VERSION |
// Recommended privacy settings
(type2Flags & FLAG_REQUEST_ALWAYS_SIGN) |
(type2Flags & FLAG_REQUEST_SEAL) |
(type2Flags & FLAG_REQUEST_SIGN) |
// These must be set according to documentation, based on use of SEAL above
(type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) |
(type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) |
(type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) |
(type2Flags & FLAG_TARGETINFO_PRESENT) |
(type2Flags & FLAG_REQUEST_UNICODE_ENCODING) |
(type2Flags & FLAG_REQUEST_TARGET)
*/
type2Flags
);
// Version
addUShort(0x0105);
// Build
addULong(2600);
// NTLM revision
addUShort(0x0f00);
int micPosition = -1;
if ( computeMic ) {
micPosition = currentOutputPosition;
currentOutputPosition += 16;
}
// Add the actual data
addBytes(lmResp);
addBytes(ntResp);
addBytes(domainBytes);
addBytes(userBytes);
addBytes(hostBytes);
if (sessionKey != null) {
addBytes(sessionKey);
}
// Write the mic back into its slot in the message
if (computeMic) {
// Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2.
final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey );
hmacMD5.update( type1Message );
hmacMD5.update( type2Message );
hmacMD5.update( messageContents );
final byte[] mic = hmacMD5.getOutput();
System.arraycopy( mic, 0, messageContents, micPosition, mic.length );
}
}