All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.server.auth.ntlm.NTLMMessage Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

The newest version!
/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco 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 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco 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 Alfresco. If not, see .
 */

package org.filesys.server.auth.ntlm;

import java.io.UnsupportedEncodingException;

import org.filesys.debug.Debug;
import org.filesys.util.DataPacker;

/**
 * NTLM Message Types Base Class
 *
 * @author gkspencer
 */
public abstract class NTLMMessage {

    // Message types
    public enum Type {
        Negotiate       (1),
        Challenge       (2),
        Authenticate    (3),

        Invalid         (-1);

        private final int msgType;

        /**
         * Enum constructor
         *
         * @param typ int
         */
        Type(int typ) { msgType = typ; }

        /**
         * Return the message type as an int
         *
         * @return int
         */
        public final int intValue() { return msgType; }

        /**
         * Create a message type from an int
         *
         * @param ival int
         * @return Type
         */
        public static final Type fromInt(int ival) {
            Type msgType = Invalid;

            switch( ival) {
                case 1:
                    msgType = Negotiate;
                    break;
                case 2:
                    msgType = Challenge;
                    break;
                case 3:
                    msgType = Authenticate;
                    break;
            }

            return msgType;
        }
    }

    // Default buffer size to allocate
    private static final int DefaultBlobSize = 512;

    // Field offsets
    public static final int OffsetSignature = 0;
    public static final int OffsetType = 8;

    // Buffer header length
    public static final int BufferHeaderLen = 8;

    // Buffer, offset and length of the NTLM blob
    private byte[] m_buf;
    private int m_offset;
    private int m_len;

    /**
     * Default constructor
     */
    protected NTLMMessage() {

        // Allocate a buffer
        m_buf = new byte[DefaultBlobSize];
        m_len = DefaultBlobSize;
    }

    /**
     * Class constructor
     *
     * @param buf    byte[]
     * @param offset int
     * @param len    int
     */
    protected NTLMMessage(byte[] buf, int offset, int len) {
        m_buf = buf;
        m_offset = offset;

        m_len = len;
    }

    /**
     * Return the message type
     *
     * @return Type
     */
    public final Type isMessageType() {
        return Type.fromInt(DataPacker.getIntelInt(m_buf, m_offset + OffsetType));
    }

    /**
     * Return the message flags
     *
     * @return int
     */
    public abstract int getFlags();

    /**
     * Return the state of the specified flag
     *
     * @param flag int
     * @return boolean
     */
    public final boolean hasFlag(int flag) {
        return (getFlags() & flag) != 0 ? true : false;
    }

    /**
     * Return the buffer
     *
     * @return byte[]
     */
    protected final byte[] getBuffer() {
        return m_buf;
    }

    /**
     * Return the message length
     *
     * @return int
     */
    public final int getLength() {
        return m_len;
    }

    /**
     * Return the buffer offset
     *
     * @return int
     */
    public final int getOffset() {
        return m_offset;
    }

    /**
     * Set the message type
     *
     * @param typ Type
     */
    public final void setMessageType(Type typ) {
        DataPacker.putIntelInt(typ.intValue(), m_buf, m_offset + OffsetType);
    }

    /**
     * Copy the NTLM blob data from the specified buffer
     *
     * @param buf    byte[]
     * @param offset int
     * @param len    int
     */
    public final void copyFrom(byte[] buf, int offset, int len) {

        // Allocate a new buffer, if required
        if (m_buf == null || m_offset != 0 || m_buf.length < len)
            m_buf = new byte[len];

        // Copy the security blob data
        System.arraycopy(buf, offset, m_buf, 0, len);

        m_len = len;
        m_offset = 0;
    }

    /**
     * Return the NTLM message as a byte array
     *
     * @return byte[]
     */
    public final byte[] getBytes() {
        byte[] byts = new byte[getLength()];
        System.arraycopy(m_buf, m_offset, byts, 0, getLength());
        return byts;
    }

    /**
     * Set the message flags
     *
     * @param flags int
     */
    protected abstract void setFlags(int flags);

    /**
     * Initialize the blob
     *
     * @param typ   Type
     * @param flags int
     */
    protected void initializeHeader(Type typ, int flags) {

        // Set the signature
        System.arraycopy(NTLM.Signature, 0, m_buf, m_offset, NTLM.Signature.length);

        setMessageType(typ);
        setFlags(flags);
    }

    /**
     * Return a short/16bit value
     *
     * @param offset int
     * @return int
     */
    protected final int getShortValue(int offset) {
        return DataPacker.getIntelShort(m_buf, m_offset + offset);
    }

    /**
     * Return an int/32bit value
     *
     * @param offset int
     * @return int
     */
    protected final int getIntValue(int offset) {
        return DataPacker.getIntelInt(m_buf, m_offset + offset);
    }

    /**
     * Return a long/64bit value
     *
     * @param offset int
     * @return long
     */
    protected final long getLongValue(int offset) {
        return DataPacker.getIntelLong(m_buf, m_offset + offset);
    }

    /**
     * Return the offset for a byte value
     *
     * @param offset int
     * @return int
     */
    protected final int getByteOffset(int offset) {
        return getIntValue(offset + 4);
    }

    /**
     * Return a byte value that has a header
     *
     * @param offset int
     * @return byte[]
     */
    protected final byte[] getByteValue(int offset) {

        // Get the byte block length
        int bLen = getShortValue(offset);
        if (bLen == 0)
            return null;

        int bOff = getIntValue(offset + 4);
        return getRawBytes(bOff, bLen);
    }

    /**
     * Return a block of byte data
     *
     * @param offset int
     * @param len    int
     * @return byte[]
     */
    protected final byte[] getRawBytes(int offset, int len) {

        byte[] byts = new byte[len];
        System.arraycopy(m_buf, m_offset + offset, byts, 0, len);

        return byts;
    }

    /**
     * Return the length of a string
     *
     * @param offset int
     * @return int
     */
    protected final int getStringLength(int offset) {

        int bufpos = m_offset + offset;

        if (bufpos + 2 > m_len)
            return -1;
        return DataPacker.getIntelShort(m_buf, bufpos);
    }

    /**
     * Return the allocated length of a string
     *
     * @param offset int
     * @return int
     */
    protected final int getStringAllocatedLength(int offset) {

        int bufpos = m_offset + offset;

        if (bufpos + 8 > m_len)
            return -1;
        return DataPacker.getIntelShort(m_buf, bufpos + 2);
    }

    /**
     * Return the string data offset
     *
     * @param offset int
     * @return int
     */
    protected final int getStringOffset(int offset) {

        int bufpos = m_offset + offset;

        if (bufpos + 8 > m_len)
            return -1;
        return DataPacker.getIntelInt(m_buf, bufpos + 4);
    }

    /**
     * Return a string value
     *
     * @param offset int
     * @param isuni  boolean
     * @return String
     */
    protected final String getStringValue(int offset, boolean isuni) {

        int bufpos = m_offset + offset;

        if (offset + 8 > m_len)
            return null;

        // Get the offset to the string
        int len = DataPacker.getIntelShort(m_buf, bufpos);
        int pos = DataPacker.getIntelInt(m_buf, bufpos + 4);

        // Get the string value
        if (pos + len > m_len)
            return null;

        // Unpack the string
        String str = null;
        try {
            str = new String(m_buf, m_offset + pos, len, isuni ? "UnicodeLittle" : "US-ASCII");
        }
        catch (UnsupportedEncodingException ex) {
            Debug.println(ex);
        }

        return str;
    }

    /**
     * Return a raw string
     *
     * @param offset int
     * @param len    int
     * @param isuni  boolean
     * @return String
     */
    protected final String getRawString(int offset, int len, boolean isuni) {
        return DataPacker.getString(m_buf, m_offset + offset, len, isuni);
    }

    /**
     * Set a byte/8bit value
     *
     * @param offset int
     * @param bval int
     */
    protected final void setByteValue(int offset, int bval) {
        m_buf[m_offset + offset] = (byte) (bval & 0xFF);
    }

    /**
     * Set a short/16bit value
     *
     * @param offset int
     * @param sval   int
     */
    protected final void setShortValue(int offset, int sval) {
        DataPacker.putIntelShort(sval, m_buf, m_offset + offset);
    }

    /**
     * Set an int/32bit value
     *
     * @param offset int
     * @param val    int
     */
    protected final void setIntValue(int offset, int val) {
        DataPacker.putIntelInt(val, m_buf, m_offset + offset);
    }

    /**
     * Set a long/64bit value
     *
     * @param offset int
     * @param lval long
     */
    protected final void setLongValue( int offset, long lval) {
        DataPacker.putIntelLong(lval, m_buf, m_offset + offset);
    }

    /**
     * Set a raw byte value
     *
     * @param offset int
     * @param byts   byte[]
     */
    protected final void setRawBytes(int offset, byte[] byts) {
        System.arraycopy(byts, 0, m_buf, m_offset + offset, byts.length);
    }

    /**
     * Set raw int values
     *
     * @param offset int
     * @param ints   int[]
     */
    protected final void setRawInts(int offset, int[] ints) {
        int bufpos = m_offset + offset;

        for (int i = 0; i < ints.length; i++) {
            DataPacker.putIntelInt(ints[i], m_buf, bufpos);
            bufpos += 4;
        }
    }

    /**
     * Pack a raw string
     *
     * @param offset int
     * @param str    String
     * @param isuni  boolean
     * @return int
     */
    protected final int setRawString(int offset, String str, boolean isuni) {
        return DataPacker.putString(str, m_buf, m_offset + offset, false, isuni);
    }

    /**
     * Zero out an area of bytes
     *
     * @param offset int
     * @param len    int
     */
    protected final void zeroBytes(int offset, int len) {
        int bufpos = m_offset + offset;
        for (int i = 0; i < len; i++)
            m_buf[bufpos++] = (byte) 0;
    }

    /**
     * Set a byte array value
     *
     * @param offset     int
     * @param byts       byte[]
     * @param dataOffset int
     * @return int
     */
    protected final int setByteValue(int offset, byte[] byts, int dataOffset) {

        int bytsLen = byts != null ? byts.length : 0;

        if (m_offset + offset + 12 > m_buf.length || m_offset + dataOffset + bytsLen > m_buf.length)
            throw new ArrayIndexOutOfBoundsException();

        // Pack the byte pointer block
        DataPacker.putIntelShort(bytsLen, m_buf, m_offset + offset);
        DataPacker.putIntelShort(bytsLen, m_buf, m_offset + offset + 2);
        DataPacker.putIntelInt(dataOffset, m_buf, m_offset + offset + 4);

        // Pack the bytes
        if (bytsLen > 0)
            System.arraycopy(byts, 0, m_buf, m_offset + dataOffset, bytsLen);

        // Return the new data buffer offset
        return dataOffset + DataPacker.wordAlign(bytsLen);
    }

    /**
     * Set a string value
     *
     * @param offset    int
     * @param val       String
     * @param strOffset int
     * @param isuni     boolean
     * @return int
     */
    protected final int setStringValue(int offset, String val, int strOffset, boolean isuni) {

        // Get the length in bytes
        int len = val.length();
        if (isuni)
            len *= 2;

        if (m_offset + offset + 8 > m_buf.length || m_offset + strOffset + len > m_buf.length)
            throw new ArrayIndexOutOfBoundsException();

        // Pack the string pointer block
        DataPacker.putIntelShort(len, m_buf, m_offset + offset);
        DataPacker.putIntelShort(len, m_buf, m_offset + offset + 2);
        DataPacker.putIntelInt(strOffset, m_buf, m_offset + offset + 4);

        // Pack the string
        return DataPacker.putString(val, m_buf, m_offset + strOffset, false, isuni) - m_offset;
    }

    /**
     * Set the message length
     *
     * @param len int
     */
    protected final void setLength(int len) {
        m_len = len;
    }

    /**
     * Validate and determine the NTLM message type
     *
     * @param buf byte[]
     * @return Type
     */
    public static Type isNTLMType(byte[] buf) {
        return isNTLMType(buf, 0);
    }

    /**
     * Validate and determine the NTLM message type
     *
     * @param buf    byte[]
     * @param offset int
     * @return Type
     */
    public static Type isNTLMType(byte[] buf, int offset) {

        // Validate the buffer
        if (buf == null || buf.length < BufferHeaderLen)
            return Type.Invalid;

        for (int i = 0; i < NTLM.Signature.length; i++) {
            if (buf[offset + i] != NTLM.Signature[i])
                return Type.Invalid;
        }

        // Get the NTLM message type
        return Type.fromInt(DataPacker.getIntelInt(buf, offset + OffsetType));
    }

    /**
     * Return the NTLM flags as a string
     *
     * @return String
     */
    public final String getFlagsAsString() {
        StringBuilder str = new StringBuilder();
        str.append("[Flags=");

        int flags = getFlags();

        if ( hasFlag( NTLM.FlagNegotiateUnicode))
            str.append("Unicode,");
        if ( hasFlag( NTLM.FlagNegotiateOEM))
            str.append("OEM,");
        if ( hasFlag( NTLM.FlagRequestTarget))
            str.append("ReqTarg,");
        if ( hasFlag( NTLM.FlagNegotiateSign))
            str.append("NegSign,");
        if ( hasFlag( NTLM.FlagNegotiateSeal))
            str.append("NegSeal,");
        if ( hasFlag( NTLM.FlagDatagramStyle))
            str.append("DGram,");
        if ( hasFlag( NTLM.FlagNegotiateNetware))
            str.append("Netware,");
        if ( hasFlag( NTLM.FlagNegotiateNTLM))
            str.append("NegNTLM,");
        if ( hasFlag( NTLM.FlagDomainSupplied))
            str.append("DomSup,");
        if ( hasFlag( NTLM.FlagWorkstationSupplied))
            str.append("WorkSup,");
        if ( hasFlag( NTLM.FlagLocalCall))
            str.append("Local,");
        if ( hasFlag( NTLM.FlagAlwaysSign))
            str.append("AlwaysSign,");
        if ( hasFlag( NTLM.FlagChallengeInit))
            str.append("ChInit,");
        if ( hasFlag( NTLM.FlagChallengeAccept))
            str.append("ChAccept,");
        if ( hasFlag( NTLM.FlagChallengeNonNT))
            str.append("ChNonNT,");
        if ( hasFlag( NTLM.FlagNegotiateExtSecurity))
            str.append("NegExtSec,");
        if ( hasFlag( NTLM.FlagTargetInfo))
            str.append("TargInfo,");
        if ( hasFlag( NTLM.FlagRequestVersion))
            str.append("ReqVer,");
        if ( hasFlag( NTLM.Flag128Bit))
            str.append("128Bit,");
        if ( hasFlag( NTLM.FlagKeyExchange))
            str.append("KeyExch,");
        if ( hasFlag( NTLM.Flag56Bit))
            str.append("56Bit,");
        str.append("]");

        return str.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy