/* * 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 2 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 (0x02000000) * 12 Target Name security buffer * 20 Flags long * 24 Challenge 8 bytes * (32) Context (optional) 8 bytes (two consecutive longs) * (40) Target Information (optional) security buffer * (48) OS Version Structure (Optional) 8 bytes * 32 (48) (56) start of data block * </pre> * * @author Jason Forand * */ public class NTLMType2Message extends NTLMMessage { /** * The logger for this class. */ private static final Logger LOG = LoggerFactory.getLogger(NTLMType2Message.class); /** Target byte array. */ private byte[] target; /** Server challenge byte array. */ private byte[] challenge; /** Context byte array. */ private byte[] context; /** Target Information byte array. */ private TargetInformation targetInformation; /** The type of this NTLM message. */ public static final int TYPE = 2; /** * * @param target * the target * @param flags * the flags * @param challenge * the challenge * @param context * the context * @param targetInformation * the target information * @param version * the version */ public NTLMType2Message(byte[] target, byte[] flags, byte[] challenge, byte[] context, TargetInformation targetInformation, byte[] version) { super(flags, version); this.target = target; this.challenge = challenge; this.context = context; this.targetInformation = targetInformation; } /** * @return the target */ public byte[] getTarget() { return target; } /** * @param target * the target to set */ public void setTarget(byte[] target) { this.target = target; } /** * @return the challenge */ public byte[] getChallenge() { return challenge; } /** * @param challenge * the challenge to set */ public void setChallenge(byte[] challenge) { this.challenge = challenge; } /** * @return the context */ public byte[] getContext() { return context; } /** * @param context * the context to set */ public void setContext(byte[] context) { this.context = context; } /** * @return the targetInformation */ public TargetInformation getTargetInformation() { return targetInformation; } /** * @param targetInformation * the targetInformation to set */ public void setTargetInformation(TargetInformation targetInformation) { this.targetInformation = targetInformation; } @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 2\n"); try { builder.append("TARGET: ").append(new String(target, CharEncoding.UTF_16LE)).append("\n"); } catch (Exception e) { LOG.error("Impossible encoding exception.", e); } builder.append(getFlagsAsString()); builder.append(getVersionAsString()); return builder.toString(); } @Override public byte[] toHeaderBytes() { NTLMByteMessage message = new NTLMByteMessage(); // This is the stuff that goes into the body message.putHeader(NTLMSSP_BYTES); message.putHeader(NTLMUtils.convertInt(2)); message.putData(target); message.putHeader(getFlags()); message.putHeader(challenge); message.putHeader(context); message.putData(targetInformation.build()); message.putHeader(getVersion()); return message.getMsg(); } /** * Parses a byte header and creates a type 2 message out of it. * * @param header * the byte header * @return the created message */ public static NTLMType2Message parse(byte[] header) { byte[] target = NTLMUtils.getSecurityBuffer(12, header); byte[] flags = Arrays.copyOfRange(header, 20, 24); byte[] challenge = Arrays.copyOfRange(header, 24, 32); byte[] context = Arrays.copyOfRange(header, 32, 40); TargetInformation targetInformation = new TargetInformation(NTLMUtils.getSecurityBuffer(40, header)); byte[] version = Arrays.copyOfRange(header, 48, 56); return new NTLMType2Message(target, flags, challenge, context, targetInformation, version); } }