/*
* Copyright (c) 2016 Dell EMC Software
* All Rights Reserved
*/
package com.iwave.ext.windows.winrm.ntlm;
import java.util.Arrays;
import org.apache.commons.lang3.CharEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class representing an NTLM Type 1 Message. The format of the message is as follows.
*
* <pre>
* Description Content
* 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000)
* 8 NTLM Message Type long (0x01000000)
* 12 Flags long
* (16) Supplied Domain (Optional) security buffer
* (24) Supplied Workstation (Optional) security buffer
* (32) OS Version Structure (Optional) 8 bytes
* (32) (40) start of data block (if required)
* </pre>
*
* @author Jason Forand
*
*/
public class NTLMType1Message extends NTLMMessage {
/**
* The logger for this class.
*/
private static final Logger LOG = LoggerFactory.getLogger(NTLMType1Message.class);
/** byte array containing the domain. */
private byte[] domain;
/** byte array containing the workstation. */
private byte[] workstation;
/** The type of this NTLM message. */
public static final int TYPE = 1;
/**
*
* @param flags
* the flags
* @param domain
* the domain
* @param workstation
* the workstation
* @param version
* the version
*/
public NTLMType1Message(byte[] flags, byte[] domain, byte[] workstation, byte[] version) {
super(flags, version);
this.domain = domain;
this.workstation = workstation;
}
/**
* @return the domain
*/
public byte[] getDomain() {
return domain;
}
/**
* @param domain
* the domain to set
*/
public void setDomain(byte[] domain) {
this.domain = domain;
}
/**
* @return the workstation
*/
public byte[] getWorkstation() {
return workstation;
}
/**
* @param workstation
* the workstation to set
*/
public void setWorkstation(byte[] workstation) {
this.workstation = workstation;
}
@Override
public int getMessageType() {
return TYPE;
}
/**
* Pretty print for debugging purposes.
*
* @return the pretty string
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("TYPE 1\n");
builder.append(getFlagsAsString());
try {
builder.append("DOMAIN:").append(new String(domain, CharEncoding.UTF_16LE));
builder.append("WORKSTATION:").append(new String(workstation, CharEncoding.UTF_16LE));
} catch (Exception e) {
LOG.error("Impossible encoding exception.", e);
}
builder.append(getVersionAsString());
return builder.toString();
}
@Override
public byte[] toHeaderBytes() {
NTLMByteMessage message = new NTLMByteMessage();
message.putHeader(NTLMSSP_BYTES);
message.putHeader(NTLMUtils.convertInt(1));
message.putHeader(getFlags());
message.putData(domain);
message.putData(workstation);
message.putHeader(getVersion());
return message.getMsg();
}
/**
* Parses a byte header and creates a type 1 message out of it.
*
* @param header
* the byte header
* @return the created message
*/
public static NTLMType1Message parse(byte[] header) {
byte[] flags = Arrays.copyOfRange(header, 12, 16);
byte[] domain = NTLMUtils.getSecurityBuffer(16, header);
byte[] workstation = NTLMUtils.getSecurityBuffer(24, header);
byte[] version = Arrays.copyOfRange(header, 32, 40);
return new NTLMType1Message(flags, domain, workstation, version);
}
}