![JAR search and dependency download from the Maven repository](/logo.png)
jcifs.ntlmssp.Type2Message Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs-krb5-jdk7 Show documentation
Show all versions of jcifs-krb5-jdk7 Show documentation
JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java
/* jcifs smb client library in Java
* Copyright (C) 2002 "Michael B. Allen"
* "Eric Glass"
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.ntlmssp;
import java.io.IOException;
import java.net.UnknownHostException;
import jcifs.Config;
import jcifs.netbios.NbtAddress;
/**
* Represents an NTLMSSP Type-2 message.
*/
public class Type2Message extends NtlmMessage {
private static final int DEFAULT_FLAGS;
private static final String DEFAULT_DOMAIN;
private static final byte[] DEFAULT_TARGET_INFORMATION;
private byte[] challenge;
private String target;
private byte[] context;
private byte[] targetInformation;
static {
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);
byte[] domain = new byte[0];
if (DEFAULT_DOMAIN != null) {
try {
domain = DEFAULT_DOMAIN.getBytes(UNI_ENCODING);
} catch (IOException ex) { }
}
int domainLength = domain.length;
byte[] server = new byte[0];
try {
String host = NbtAddress.getLocalHost().getHostName();
if (host != null) {
try {
server = host.getBytes(UNI_ENCODING);
} catch (IOException ex) { }
}
} catch (UnknownHostException ex) { }
int serverLength = server.length;
byte[] targetInfo = new byte[(domainLength > 0 ? domainLength + 4 : 0) +
(serverLength > 0 ? serverLength + 4 : 0) + 4];
int offset = 0;
if (domainLength > 0) {
writeUShort(targetInfo, offset, 2);
offset += 2;
writeUShort(targetInfo, offset, domainLength);
offset += 2;
System.arraycopy(domain, 0, targetInfo, offset, domainLength);
offset += domainLength;
}
if (serverLength > 0) {
writeUShort(targetInfo, offset, 1);
offset += 2;
writeUShort(targetInfo, offset, serverLength);
offset += 2;
System.arraycopy(server, 0, targetInfo, offset, serverLength);
}
DEFAULT_TARGET_INFORMATION = targetInfo;
}
/**
* Creates a Type-2 message using default values from the current
* environment.
*/
public Type2Message() {
this(getDefaultFlags(), null, null);
}
/**
* Creates a Type-2 message in response to the given Type-1 message
* using default values from the current environment.
*
* @param type1 The Type-1 message which this represents a response to.
*/
public Type2Message(Type1Message type1) {
this(type1, null, null);
}
/**
* Creates a Type-2 message in response to the given Type-1 message.
*
* @param type1 The Type-1 message which this represents a response to.
* @param challenge The challenge from the domain controller/server.
* @param target The authentication target.
*/
public Type2Message(Type1Message type1, byte[] challenge, String target) {
this(getDefaultFlags(type1), challenge, (type1 != null &&
target == null && type1.getFlag(NTLMSSP_REQUEST_TARGET)) ?
getDefaultDomain() : target);
}
/**
* Creates a Type-2 message with the specified parameters.
*
* @param flags The flags to apply to this message.
* @param challenge The challenge from the domain controller/server.
* @param target The authentication target.
*/
public Type2Message(int flags, byte[] challenge, String target) {
setFlags(flags);
setChallenge(challenge);
setTarget(target);
if (target != null) setTargetInformation(getDefaultTargetInformation());
}
/**
* Creates a Type-2 message using the given raw Type-2 material.
*
* @param material The raw Type-2 material used to construct this message.
* @throws IOException If an error occurs while parsing the material.
*/
public Type2Message(byte[] material) throws IOException {
parse(material);
}
/**
* Returns the challenge for this message.
*
* @return A byte[]
containing the challenge.
*/
public byte[] getChallenge() {
return challenge;
}
/**
* Sets the challenge for this message.
*
* @param challenge The challenge from the domain controller/server.
*/
public void setChallenge(byte[] challenge) {
this.challenge = challenge;
}
/**
* Returns the authentication target.
*
* @return A String
containing the authentication target.
*/
public String getTarget() {
return target;
}
/**
* Sets the authentication target.
*
* @param target The authentication target.
*/
public void setTarget(String target) {
this.target = target;
}
/**
* Returns the target information block.
*
* @return A byte[]
containing the target information block.
* The target information block is used by the client to create an
* NTLMv2 response.
*/
public byte[] getTargetInformation() {
return targetInformation;
}
/**
* Sets the target information block.
* The target information block is used by the client to create
* an NTLMv2 response.
*
* @param targetInformation The target information block.
*/
public void setTargetInformation(byte[] targetInformation) {
this.targetInformation = targetInformation;
}
/**
* Returns the local security context.
*
* @return A byte[]
containing the local security
* context. This is used by the client to negotiate local
* authentication.
*/
public byte[] getContext() {
return context;
}
/**
* Sets the local security context. This is used by the client
* to negotiate local authentication.
*
* @param context The local security context.
*/
public void setContext(byte[] context) {
this.context = context;
}
public byte[] toByteArray() {
try {
String targetName = getTarget();
byte[] challenge = getChallenge();
byte[] context = getContext();
byte[] targetInformation = getTargetInformation();
int flags = getFlags();
byte[] target = new byte[0];
if ((flags & NTLMSSP_REQUEST_TARGET) != 0) {
if (targetName != null && targetName.length() != 0) {
target = (flags & NTLMSSP_NEGOTIATE_UNICODE) != 0 ?
targetName.getBytes(UNI_ENCODING) :
targetName.toUpperCase().getBytes(getOEMEncoding());
} else {
flags &= (0xffffffff ^ NTLMSSP_REQUEST_TARGET);
}
}
if (targetInformation != null) {
flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
// empty context is needed for padding when t.i. is supplied.
if (context == null) context = new byte[8];
}
int data = 32;
if (context != null) data += 8;
if (targetInformation != null) data += 8;
byte[] type2 = new byte[data + target.length +
(targetInformation != null ? targetInformation.length : 0)];
System.arraycopy(NTLMSSP_SIGNATURE, 0, type2, 0, 8);
writeULong(type2, 8, 2);
writeSecurityBuffer(type2, 12, data, target);
writeULong(type2, 20, flags);
System.arraycopy(challenge != null ? challenge : new byte[8], 0,
type2, 24, 8);
if (context != null) System.arraycopy(context, 0, type2, 32, 8);
if (targetInformation != null) {
writeSecurityBuffer(type2, 40, data + target.length,
targetInformation);
}
return type2;
} catch (IOException ex) {
throw new IllegalStateException(ex.getMessage());
}
}
public String toString() {
String target = getTarget();
byte[] challenge = getChallenge();
byte[] context = getContext();
byte[] targetInformation = getTargetInformation();
return "Type2Message[target=" + target +
",challenge=" + (challenge == null ? "null" : "<" + challenge.length + " bytes>") +
",context=" + (context == null ? "null" : "<" + context.length + " bytes>") +
",targetInformation=" + (targetInformation == null ? "null" : "<" + targetInformation.length + " bytes>") +
",flags=0x" + jcifs.util.Hexdump.toHexString(getFlags(), 8) + "]";
}
/**
* Returns the default flags for a generic Type-2 message in the
* current environment.
*
* @return An int
containing the default flags.
*/
public static int getDefaultFlags() {
return DEFAULT_FLAGS;
}
/**
* Returns the default flags for a Type-2 message created in response
* to the given Type-1 message in the current environment.
*
* @return An int
containing the default flags.
*/
public static int getDefaultFlags(Type1Message type1) {
if (type1 == null) return DEFAULT_FLAGS;
int flags = NTLMSSP_NEGOTIATE_NTLM;
int type1Flags = type1.getFlags();
flags |= ((type1Flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?
NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM;
if ((type1Flags & NTLMSSP_REQUEST_TARGET) != 0) {
String domain = getDefaultDomain();
if (domain != null) {
flags |= NTLMSSP_REQUEST_TARGET | NTLMSSP_TARGET_TYPE_DOMAIN;
}
}
return flags;
}
/**
* Returns the default domain from the current environment.
*
* @return A String
containing the domain.
*/
public static String getDefaultDomain() {
return DEFAULT_DOMAIN;
}
public static byte[] getDefaultTargetInformation() {
return DEFAULT_TARGET_INFORMATION;
}
private void parse(byte[] material) throws IOException {
for (int i = 0; i < 8; i++) {
if (material[i] != NTLMSSP_SIGNATURE[i]) {
throw new IOException("Not an NTLMSSP message.");
}
}
if (readULong(material, 8) != 2) {
throw new IOException("Not a Type 2 message.");
}
int flags = readULong(material, 20);
setFlags(flags);
String target = null;
byte[] bytes = readSecurityBuffer(material, 12);
if (bytes.length != 0) {
target = new String(bytes,
((flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?
UNI_ENCODING : getOEMEncoding());
}
setTarget(target);
for (int i = 24; i < 32; i++) {
if (material[i] != 0) {
byte[] challenge = new byte[8];
System.arraycopy(material, 24, challenge, 0, 8);
setChallenge(challenge);
break;
}
}
int offset = readULong(material, 16); // offset of targetname start
if (offset == 32 || material.length == 32) return;
for (int i = 32; i < 40; i++) {
if (material[i] != 0) {
byte[] context = new byte[8];
System.arraycopy(material, 32, context, 0, 8);
setContext(context);
break;
}
}
if (offset == 40 || material.length == 40) return;
bytes = readSecurityBuffer(material, 40);
if (bytes.length != 0) setTargetInformation(bytes);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy