Type3Messagepublic class Type3Message extends NtlmMessage Represents an NTLMSSP Type-3 message. |
Fields Summary |
---|
static final long | MILLISECONDS_BETWEEN_1970_AND_1601 | private static final int | DEFAULT_FLAGS | private static final String | DEFAULT_DOMAIN | private static final String | DEFAULT_USER | private static final String | DEFAULT_PASSWORD | private static final String | DEFAULT_WORKSTATION | private static final int | LM_COMPATIBILITY | private static final SecureRandom | RANDOM | private byte[] | lmResponse | private byte[] | ntResponse | private String | domain | private String | user | private String | workstation | private byte[] | masterKey | private byte[] | sessionKey |
Constructors Summary |
---|
public Type3Message()Creates a Type-3 message using default values from the current
environment.
DEFAULT_FLAGS = NTLMSSP_NEGOTIATE_NTLM |
(Config.getBoolean("jcifs.smb.client.useUnicode", true) ?
NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM);
DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", null);
DEFAULT_USER = Config.getProperty("jcifs.smb.client.username", null);
DEFAULT_PASSWORD = Config.getProperty("jcifs.smb.client.password",
null);
String defaultWorkstation = null;
try {
defaultWorkstation = NbtAddress.getLocalHost().getHostName();
} catch (UnknownHostException ex) { }
DEFAULT_WORKSTATION = defaultWorkstation;
LM_COMPATIBILITY = Config.getInt("jcifs.smb.lmCompatibility", 3);
setFlags(getDefaultFlags());
setDomain(getDefaultDomain());
setUser(getDefaultUser());
setWorkstation(getDefaultWorkstation());
| public Type3Message(Type2Message type2)Creates a Type-3 message in response to the given Type-2 message
using default values from the current environment.
setFlags(getDefaultFlags(type2));
setWorkstation(getDefaultWorkstation());
String domain = getDefaultDomain();
setDomain(domain);
String user = getDefaultUser();
setUser(user);
String password = getDefaultPassword();
switch (LM_COMPATIBILITY) {
case 0:
case 1:
setLMResponse(getLMResponse(type2, password));
setNTResponse(getNTResponse(type2, password));
break;
case 2:
byte[] nt = getNTResponse(type2, password);
setLMResponse(nt);
setNTResponse(nt);
break;
case 3:
case 4:
case 5:
byte[] clientChallenge = new byte[8];
RANDOM.nextBytes(clientChallenge);
setLMResponse(getLMv2Response(type2, domain, user, password,
clientChallenge));
/*
setNTResponse(getNTLMv2Response(type2, domain, user, password,
clientChallenge));
*/
break;
default:
setLMResponse(getLMResponse(type2, password));
setNTResponse(getNTResponse(type2, password));
}
| public Type3Message(Type2Message type2, String password, String domain, String user, String workstation, int flags)Creates a Type-3 message in response to the given Type-2 message.
setFlags(flags | getDefaultFlags(type2));
if (workstation == null)
workstation = getDefaultWorkstation();
setWorkstation(workstation);
setDomain(domain);
setUser(user);
switch (LM_COMPATIBILITY) {
case 0:
case 1:
if ((getFlags() & NTLMSSP_NEGOTIATE_NTLM2) == 0) {
setLMResponse(getLMResponse(type2, password));
setNTResponse(getNTResponse(type2, password));
} else {
// NTLM2 Session Response
byte[] clientChallenge = new byte[24];
RANDOM.nextBytes(clientChallenge);
java.util.Arrays.fill(clientChallenge, 8, 24, (byte)0x00);
// NTLMv1 w/ NTLM2 session sec and key exch all been verified with a debug build of smbclient
byte[] responseKeyNT = NtlmPasswordAuthentication.nTOWFv1(password);
byte[] ntlm2Response = NtlmPasswordAuthentication.getNTLM2Response(responseKeyNT,
type2.getChallenge(),
clientChallenge);
setLMResponse(clientChallenge);
setNTResponse(ntlm2Response);
if ((getFlags() & NTLMSSP_NEGOTIATE_SIGN) == NTLMSSP_NEGOTIATE_SIGN) {
byte[] sessionNonce = new byte[16];
System.arraycopy(type2.getChallenge(), 0, sessionNonce, 0, 8);
System.arraycopy(clientChallenge, 0, sessionNonce, 8, 8);
MD4 md4 = new MD4();
md4.update(responseKeyNT);
byte[] userSessionKey = md4.digest();
HMACT64 hmac = new HMACT64(userSessionKey);
hmac.update(sessionNonce);
byte[] ntlm2SessionKey = hmac.digest();
if ((getFlags() & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0) {
masterKey = new byte[16];
RANDOM.nextBytes(masterKey);
byte[] exchangedKey = new byte[16];
RC4 rc4 = new RC4(ntlm2SessionKey);
rc4.update(masterKey, 0, 16, exchangedKey, 0);
/* RC4 was not added to Java until 1.5u7 so let's use our own for a little while longer ...
try {
Cipher rc4 = Cipher.getInstance("RC4");
rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(ntlm2SessionKey, "RC4"));
rc4.update(masterKey, 0, 16, exchangedKey, 0);
} catch (GeneralSecurityException gse) {
throw new RuntimeException("", gse);
}
*/
setSessionKey(exchangedKey);
} else {
masterKey = ntlm2SessionKey;
setSessionKey(masterKey);
}
}
}
break;
case 2:
byte[] nt = getNTResponse(type2, password);
setLMResponse(nt);
setNTResponse(nt);
break;
case 3:
case 4:
case 5:
byte[] responseKeyNT = NtlmPasswordAuthentication.nTOWFv2(domain, user, password);
byte[] clientChallenge = new byte[8];
RANDOM.nextBytes(clientChallenge);
setLMResponse(getLMv2Response(type2, domain, user, password, clientChallenge));
byte[] clientChallenge2 = new byte[8];
RANDOM.nextBytes(clientChallenge2);
setNTResponse(getNTLMv2Response(type2, responseKeyNT, clientChallenge2));
if ((getFlags() & NTLMSSP_NEGOTIATE_SIGN) == NTLMSSP_NEGOTIATE_SIGN) {
HMACT64 hmac = new HMACT64(responseKeyNT);
hmac.update(ntResponse, 0, 16); // only first 16 bytes of ntResponse
byte[] userSessionKey = hmac.digest();
if ((getFlags() & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0) {
masterKey = new byte[16];
RANDOM.nextBytes(masterKey);
byte[] exchangedKey = new byte[16];
RC4 rc4 = new RC4(userSessionKey);
rc4.update(masterKey, 0, 16, exchangedKey, 0);
/* RC4 was not added to Java until 1.5u7 so let's use our own for a little while longer ...
try {
Cipher rc4 = Cipher.getInstance("RC4");
rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(userSessionKey, "RC4"));
rc4.update(masterKey, 0, 16, exchangedKey, 0);
} catch (GeneralSecurityException gse) {
throw new RuntimeException("", gse);
}
*/
setSessionKey(exchangedKey);
} else {
masterKey = userSessionKey;
setSessionKey(masterKey);
}
}
break;
default:
setLMResponse(getLMResponse(type2, password));
setNTResponse(getNTResponse(type2, password));
}
| public Type3Message(int flags, byte[] lmResponse, byte[] ntResponse, String domain, String user, String workstation)Creates a Type-3 message with the specified parameters.
setFlags(flags);
setLMResponse(lmResponse);
setNTResponse(ntResponse);
setDomain(domain);
setUser(user);
setWorkstation(workstation);
| public Type3Message(byte[] material)Creates a Type-3 message using the given raw Type-3 material.
parse(material);
|
Methods Summary |
---|
public static java.lang.String | getDefaultDomain()Returns the default domain from the current environment.
return DEFAULT_DOMAIN;
| public static int | getDefaultFlags()Returns the default flags for a generic Type-3 message in the
current environment.
return DEFAULT_FLAGS;
| public static int | getDefaultFlags(Type2Message type2)Returns the default flags for a Type-3 message created in response
to the given Type-2 message in the current environment.
if (type2 == null) return DEFAULT_FLAGS;
int flags = NTLMSSP_NEGOTIATE_NTLM;
flags |= ((type2.getFlags() & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?
NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM;
return flags;
| public static java.lang.String | getDefaultPassword()Returns the default password from the current environment.
return DEFAULT_PASSWORD;
| public static java.lang.String | getDefaultUser()Returns the default user from the current environment.
return DEFAULT_USER;
| public static java.lang.String | getDefaultWorkstation()Returns the default workstation from the current environment.
return DEFAULT_WORKSTATION;
| public java.lang.String | getDomain()Returns the domain in which the user has an account.
return domain;
| public static byte[] | getLMResponse(Type2Message type2, java.lang.String password)Constructs the LanManager response to the given Type-2 message using
the supplied password.
if (type2 == null || password == null) return null;
return NtlmPasswordAuthentication.getPreNTLMResponse(password,
type2.getChallenge());
| public byte[] | getLMResponse()Returns the LanManager/LMv2 response.
return lmResponse;
| public static byte[] | getLMv2Response(Type2Message type2, java.lang.String domain, java.lang.String user, java.lang.String password, byte[] clientChallenge)
if (type2 == null || domain == null || user == null ||
password == null || clientChallenge == null) {
return null;
}
return NtlmPasswordAuthentication.getLMv2Response(domain, user,
password, type2.getChallenge(), clientChallenge);
| public byte[] | getMasterKey()The real session key if the regular session key is actually
the encrypted version used for key exchange.
return masterKey;
| public static byte[] | getNTLMv2Response(Type2Message type2, byte[] responseKeyNT, byte[] clientChallenge)
if (type2 == null || responseKeyNT == null || clientChallenge == null) {
return null;
}
long nanos1601 = (System.currentTimeMillis() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
return NtlmPasswordAuthentication.getNTLMv2Response(responseKeyNT,
type2.getChallenge(),
clientChallenge,
nanos1601,
type2.getTargetInformation());
| public static byte[] | getNTResponse(Type2Message type2, java.lang.String password)Constructs the NT response to the given Type-2 message using
the supplied password.
if (type2 == null || password == null) return null;
return NtlmPasswordAuthentication.getNTLMResponse(password,
type2.getChallenge());
| public byte[] | getNTResponse()Returns the NT/NTLMv2 response.
return ntResponse;
| public byte[] | getSessionKey()Returns the session key.
return sessionKey;
| public java.lang.String | getUser()Returns the username for the authenticating user.
return user;
| public java.lang.String | getWorkstation()Returns the workstation from which authentication is being performed.
return workstation;
| private void | parse(byte[] material)
for (int i = 0; i < 8; i++) {
if (material[i] != NTLMSSP_SIGNATURE[i]) {
throw new IOException("Not an NTLMSSP message.");
}
}
if (readULong(material, 8) != 3) {
throw new IOException("Not a Type 3 message.");
}
byte[] lmResponse = readSecurityBuffer(material, 12);
int lmResponseOffset = readULong(material, 16);
byte[] ntResponse = readSecurityBuffer(material, 20);
int ntResponseOffset = readULong(material, 24);
byte[] domain = readSecurityBuffer(material, 28);
int domainOffset = readULong(material, 32);
byte[] user = readSecurityBuffer(material, 36);
int userOffset = readULong(material, 40);
byte[] workstation = readSecurityBuffer(material, 44);
int workstationOffset = readULong(material, 48);
int flags;
String charset;
byte[] _sessionKey = null;
if (lmResponseOffset == 52 || ntResponseOffset == 52 ||
domainOffset == 52 || userOffset == 52 ||
workstationOffset == 52) {
flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_OEM;
charset = getOEMEncoding();
} else {
_sessionKey = readSecurityBuffer(material, 52);
flags = readULong(material, 60);
charset = ((flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?
UNI_ENCODING : getOEMEncoding();
}
setSessionKey(_sessionKey);
setFlags(flags);
setLMResponse(lmResponse);
setNTResponse(ntResponse);
setDomain(new String(domain, charset));
setUser(new String(user, charset));
setWorkstation(new String(workstation, charset));
| public void | setDomain(java.lang.String domain)Sets the domain for this message.
this.domain = domain;
| public void | setLMResponse(byte[] lmResponse)Sets the LanManager/LMv2 response for this message.
this.lmResponse = lmResponse;
| public void | setNTResponse(byte[] ntResponse)Sets the NT/NTLMv2 response for this message.
this.ntResponse = ntResponse;
| public void | setSessionKey(byte[] sessionKey)Sets the session key.
this.sessionKey = sessionKey;
| public void | setUser(java.lang.String user)Sets the user for this message.
this.user = user;
| public void | setWorkstation(java.lang.String workstation)Sets the workstation for this message.
this.workstation = workstation;
| public byte[] | toByteArray()
try {
int flags = getFlags();
boolean unicode = (flags & NTLMSSP_NEGOTIATE_UNICODE) != 0;
String oem = unicode ? null : getOEMEncoding();
String domainName = getDomain();
byte[] domain = null;
if (domainName != null && domainName.length() != 0) {
domain = unicode ?
domainName.getBytes(UNI_ENCODING) :
domainName.getBytes(oem);
}
int domainLength = (domain != null) ? domain.length : 0;
String userName = getUser();
byte[] user = null;
if (userName != null && userName.length() != 0) {
user = unicode ? userName.getBytes(UNI_ENCODING) :
userName.toUpperCase().getBytes(oem);
}
int userLength = (user != null) ? user.length : 0;
String workstationName = getWorkstation();
byte[] workstation = null;
if (workstationName != null && workstationName.length() != 0) {
workstation = unicode ?
workstationName.getBytes(UNI_ENCODING) :
workstationName.toUpperCase().getBytes(oem);
}
int workstationLength = (workstation != null) ?
workstation.length : 0;
byte[] lmResponse = getLMResponse();
int lmLength = (lmResponse != null) ? lmResponse.length : 0;
byte[] ntResponse = getNTResponse();
int ntLength = (ntResponse != null) ? ntResponse.length : 0;
byte[] sessionKey = getSessionKey();
int keyLength = (sessionKey != null) ? sessionKey.length : 0;
byte[] type3 = new byte[64 + domainLength + userLength +
workstationLength + lmLength + ntLength + keyLength];
System.arraycopy(NTLMSSP_SIGNATURE, 0, type3, 0, 8);
writeULong(type3, 8, 3);
int offset = 64;
writeSecurityBuffer(type3, 12, offset, lmResponse);
offset += lmLength;
writeSecurityBuffer(type3, 20, offset, ntResponse);
offset += ntLength;
writeSecurityBuffer(type3, 28, offset, domain);
offset += domainLength;
writeSecurityBuffer(type3, 36, offset, user);
offset += userLength;
writeSecurityBuffer(type3, 44, offset, workstation);
offset += workstationLength;
writeSecurityBuffer(type3, 52, offset, sessionKey);
writeULong(type3, 60, flags);
return type3;
} catch (IOException ex) {
throw new IllegalStateException(ex.getMessage());
}
| public java.lang.String | toString()
String user = getUser();
String domain = getDomain();
String workstation = getWorkstation();
byte[] lmResponse = getLMResponse();
byte[] ntResponse = getNTResponse();
byte[] sessionKey = getSessionKey();
return "Type3Message[domain=" + domain +
",user=" + user +
",workstation=" + workstation +
",lmResponse=" + (lmResponse == null ? "null" : "<" + lmResponse.length + " bytes>") +
",ntResponse=" + (ntResponse == null ? "null" : "<" + ntResponse.length + " bytes>") +
",sessionKey=" + (sessionKey == null ? "null" : "<" + sessionKey.length + " bytes>") +
",flags=0x" + jcifs.util.Hexdump.toHexString(getFlags(), 8) + "]";
|
|