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

jcifs.internal.smb1.trans.SmbComTransaction Maven / Gradle / Ivy

/* jcifs smb client library in Java
 * Copyright (C) 2000  "Michael B. Allen" 
 * 
 * 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.internal.smb1.trans;


import java.util.Enumeration;

import jcifs.Configuration;
import jcifs.internal.smb1.ServerMessageBlock;
import jcifs.internal.util.SMBUtil;
import jcifs.util.Hexdump;


/**
 * 
 */
public abstract class SmbComTransaction extends ServerMessageBlock implements Enumeration {

    // relative to headerStart
    private static final int PRIMARY_SETUP_OFFSET = 61;
    private static final int SECONDARY_PARAMETER_OFFSET = 51;

    static final int DISCONNECT_TID = 0x01;
    static final int ONE_WAY_TRANSACTION = 0x02;

    static final int PADDING_SIZE = 4;

    private int tflags = 0x00;
    private int pad1 = 0;
    private int pad2 = 0;
    private boolean hasMore = true;
    private boolean isPrimary = true;
    private int bufParameterOffset;
    private int bufDataOffset;

    static final int TRANSACTION_BUF_SIZE = 0xFFFF;

    /**
     * 
     */
    public static final byte TRANS2_FIND_FIRST2 = (byte) 0x01;
    /**
     * 
     */
    public static final byte TRANS2_FIND_NEXT2 = (byte) 0x02;
    /**
     * 
     */
    public static final byte TRANS2_QUERY_FS_INFORMATION = (byte) 0x03;
    /**
     * 
     */
    public static final byte TRANS2_QUERY_PATH_INFORMATION = (byte) 0x05;
    /**
     * 
     */
    public static final byte TRANS2_GET_DFS_REFERRAL = (byte) 0x10;
    /**
     * 
     */
    public static final byte TRANS2_QUERY_FILE_INFORMATION = (byte) 0x07;
    /**
     * 
     */
    public static final byte TRANS2_SET_FILE_INFORMATION = (byte) 0x08;

    /**
     * 
     */
    public static final byte NET_SHARE_ENUM = (byte) 0x00;
    /**
     * 
     */
    public static final byte NET_SERVER_ENUM2 = (byte) 0x68;
    /**
     * 
     */
    public static final byte NET_SERVER_ENUM3 = (byte) 0xD7;

    /**
     * 
     */
    public static final byte TRANS_PEEK_NAMED_PIPE = (byte) 0x23;
    /**
     * 
     */
    public static final byte TRANS_WAIT_NAMED_PIPE = (byte) 0x53;
    /**
     * 
     */
    public static final byte TRANS_CALL_NAMED_PIPE = (byte) 0x54;
    /**
     * 
     */
    public static final byte TRANS_TRANSACT_NAMED_PIPE = (byte) 0x26;

    protected int primarySetupOffset;
    protected int secondaryParameterOffset;
    protected int parameterCount;
    protected int parameterOffset;
    protected int parameterDisplacement;
    protected int dataCount;
    protected int dataOffset;
    protected int dataDisplacement;

    protected int totalParameterCount;
    protected int totalDataCount;
    protected int maxParameterCount;
    protected int maxDataCount;
    protected byte maxSetupCount;
    protected int timeout = 0;
    protected int setupCount = 1;
    private byte subCommand;
    protected String name = "";
    protected int maxBufferSize; // set in SmbTransport.sendTransaction() before nextElement called

    private byte[] txn_buf;


    protected SmbComTransaction ( Configuration config, byte command, byte subCommand ) {
        super(config, command);
        this.subCommand = subCommand;
        this.maxDataCount = config.getTransactionBufferSize() - 512;
        this.maxParameterCount = 1024;
        this.primarySetupOffset = PRIMARY_SETUP_OFFSET;
        this.secondaryParameterOffset = SECONDARY_PARAMETER_OFFSET;
    }


    /**
     * @param maxBufferSize
     *            the maxBufferSize to set
     */
    public final void setMaxBufferSize ( int maxBufferSize ) {
        this.maxBufferSize = maxBufferSize;
    }


    /**
     * @param maxDataCount
     *            the maxDataCount to set
     */
    public final void setMaxDataCount ( int maxDataCount ) {
        this.maxDataCount = maxDataCount;
    }


    /**
     * @param buffer
     */
    public void setBuffer ( byte[] buffer ) {
        this.txn_buf = buffer;
    }


    /**
     * @return the txn_buf
     */
    public byte[] releaseBuffer () {
        byte[] buf = this.txn_buf;
        this.txn_buf = null;
        return buf;
    }


    /**
     * @return the subCommand
     */
    public final byte getSubCommand () {
        return this.subCommand;
    }


    /**
     * @param subCommand
     *            the subCommand to set
     */
    public final void setSubCommand ( byte subCommand ) {
        this.subCommand = subCommand;
    }


    @Override
    public void reset () {
        super.reset();
        this.isPrimary = this.hasMore = true;
    }


    protected void reset ( int key, String lastName ) {
        reset();
    }


    @Override
    public boolean hasMoreElements () {
        return this.hasMore;
    }


    @Override
    public SmbComTransaction nextElement () {
        if ( this.isPrimary ) {
            this.isPrimary = false;

            // primarySetupOffset
            // SMB_COM_TRANSACTION: 61 = 32 SMB header + 1 (word count) + 28 (fixed words)
            // SMB_COM_NT_TRANSACTION: 69 = 32 SMB header + 1 (word count) + 38 (fixed words)
            this.parameterOffset = this.primarySetupOffset;

            // 2* setupCount
            this.parameterOffset += this.setupCount * 2;
            this.parameterOffset += 2; // ByteCount

            if ( this.getCommand() == SMB_COM_TRANSACTION && isResponse() == false ) {
                this.parameterOffset += stringWireLength(this.name, this.parameterOffset);
            }

            this.pad1 = pad(this.parameterOffset);
            this.parameterOffset += this.pad1;

            this.totalParameterCount = writeParametersWireFormat(this.txn_buf, this.bufParameterOffset);
            this.bufDataOffset = this.totalParameterCount; // data comes right after data

            int available = this.maxBufferSize - this.parameterOffset;
            this.parameterCount = Math.min(this.totalParameterCount, available);
            available -= this.parameterCount;

            this.dataOffset = this.parameterOffset + this.parameterCount;
            this.pad2 = this.pad(this.dataOffset);
            this.dataOffset += this.pad2;

            this.totalDataCount = writeDataWireFormat(this.txn_buf, this.bufDataOffset);

            this.dataCount = Math.min(this.totalDataCount, available);
        }
        else {
            if ( this.getCommand() != SMB_COM_NT_TRANSACT ) {
                this.setCommand(SMB_COM_TRANSACTION_SECONDARY);
            }
            else {
                this.setCommand(SMB_COM_NT_TRANSACT_SECONDARY);
            }
            // totalParameterCount and totalDataCount are set ok from primary

            this.parameterOffset = SECONDARY_PARAMETER_OFFSET;
            if ( ( this.totalParameterCount - this.parameterDisplacement ) > 0 ) {
                this.pad1 = this.pad(this.parameterOffset);
                this.parameterOffset += this.pad1;
            }

            // caclulate parameterDisplacement before calculating new parameterCount
            this.parameterDisplacement += this.parameterCount;

            int available = this.maxBufferSize - this.parameterOffset - this.pad1;
            this.parameterCount = Math.min(this.totalParameterCount - this.parameterDisplacement, available);
            available -= this.parameterCount;

            this.dataOffset = this.parameterOffset + this.parameterCount;
            this.pad2 = this.pad(this.dataOffset);
            this.dataOffset += this.pad2;

            this.dataDisplacement += this.dataCount;

            available -= this.pad2;
            this.dataCount = Math.min(this.totalDataCount - this.dataDisplacement, available);
        }
        if ( ( this.parameterDisplacement + this.parameterCount ) >= this.totalParameterCount
                && ( this.dataDisplacement + this.dataCount ) >= this.totalDataCount ) {
            this.hasMore = false;
        }
        return this;
    }


    /**
     * @return
     */
    protected int pad ( int offset ) {
        int p = offset % getPadding();
        if ( p == 0 ) {
            return 0;
        }
        return getPadding() - p;
    }


    /**
     * 
     * @return padding size
     */
    public int getPadding () {
        return PADDING_SIZE;
    }


    @Override
    protected int writeParameterWordsWireFormat ( byte[] dst, int dstIndex ) {
        int start = dstIndex;

        SMBUtil.writeInt2(this.totalParameterCount, dst, dstIndex);
        dstIndex += 2;
        SMBUtil.writeInt2(this.totalDataCount, dst, dstIndex);
        dstIndex += 2;
        if ( this.getCommand() != SMB_COM_TRANSACTION_SECONDARY ) {
            SMBUtil.writeInt2(this.maxParameterCount, dst, dstIndex);
            dstIndex += 2;
            SMBUtil.writeInt2(this.maxDataCount, dst, dstIndex);
            dstIndex += 2;
            dst[ dstIndex++ ] = this.maxSetupCount;
            dst[ dstIndex++ ] = (byte) 0x00; // Reserved1
            SMBUtil.writeInt2(this.tflags, dst, dstIndex);
            dstIndex += 2;
            SMBUtil.writeInt4(this.timeout, dst, dstIndex);
            dstIndex += 4;
            dst[ dstIndex++ ] = (byte) 0x00; // Reserved2
            dst[ dstIndex++ ] = (byte) 0x00;
        }
        SMBUtil.writeInt2(this.parameterCount, dst, dstIndex);
        dstIndex += 2;
        // writeInt2(( parameterCount == 0 ? 0 : parameterOffset ), dst, dstIndex );
        SMBUtil.writeInt2(this.parameterOffset, dst, dstIndex);
        dstIndex += 2;
        if ( this.getCommand() == SMB_COM_TRANSACTION_SECONDARY ) {
            SMBUtil.writeInt2(this.parameterDisplacement, dst, dstIndex);
            dstIndex += 2;
        }
        SMBUtil.writeInt2(this.dataCount, dst, dstIndex);
        dstIndex += 2;
        SMBUtil.writeInt2( ( this.dataCount == 0 ? 0 : this.dataOffset ), dst, dstIndex);
        dstIndex += 2;
        if ( this.getCommand() == SMB_COM_TRANSACTION_SECONDARY ) {
            SMBUtil.writeInt2(this.dataDisplacement, dst, dstIndex);
            dstIndex += 2;
        }
        else {
            dst[ dstIndex++ ] = (byte) this.setupCount;
            dst[ dstIndex++ ] = (byte) 0x00; // Reserved3
            dstIndex += writeSetupWireFormat(dst, dstIndex);
        }

        return dstIndex - start;
    }


    @Override
    protected int writeBytesWireFormat ( byte[] dst, int dstIndex ) {
        int start = dstIndex;

        if ( this.getCommand() == SMB_COM_TRANSACTION && isResponse() == false ) {
            dstIndex += writeString(this.name, dst, dstIndex);
        }

        int end = dstIndex + this.pad1;

        if ( this.parameterCount > 0 ) {
            System.arraycopy(this.txn_buf, this.bufParameterOffset, dst, this.headerStart + this.parameterOffset, this.parameterCount);
            end = Math.max(end, this.headerStart + this.parameterOffset + this.parameterCount + this.pad2);
        }

        if ( this.dataCount > 0 ) {
            System.arraycopy(this.txn_buf, this.bufDataOffset, dst, this.headerStart + this.dataOffset, this.dataCount);
            this.bufDataOffset += this.dataCount;
            end = Math.max(end, this.headerStart + this.dataOffset + this.dataCount);
        }

        return end - start;
    }


    @Override
    protected int readParameterWordsWireFormat ( byte[] buffer, int bufferIndex ) {
        return 0;
    }


    @Override
    protected int readBytesWireFormat ( byte[] buffer, int bufferIndex ) {
        return 0;
    }


    protected abstract int writeSetupWireFormat ( byte[] dst, int dstIndex );


    protected abstract int writeParametersWireFormat ( byte[] dst, int dstIndex );


    protected abstract int writeDataWireFormat ( byte[] dst, int dstIndex );


    protected abstract int readSetupWireFormat ( byte[] buffer, int bufferIndex, int len );


    protected abstract int readParametersWireFormat ( byte[] buffer, int bufferIndex, int len );


    protected abstract int readDataWireFormat ( byte[] buffer, int bufferIndex, int len );


    @Override
    public String toString () {
        return new String(
            super.toString() + ",totalParameterCount=" + this.totalParameterCount + ",totalDataCount=" + this.totalDataCount + ",maxParameterCount="
                    + this.maxParameterCount + ",maxDataCount=" + this.maxDataCount + ",maxSetupCount=" + (int) this.maxSetupCount + ",flags=0x"
                    + Hexdump.toHexString(this.tflags, 2) + ",timeout=" + this.timeout + ",parameterCount=" + this.parameterCount
                    + ",parameterOffset=" + this.parameterOffset + ",parameterDisplacement=" + this.parameterDisplacement + ",dataCount="
                    + this.dataCount + ",dataOffset=" + this.dataOffset + ",dataDisplacement=" + this.dataDisplacement + ",setupCount="
                    + this.setupCount + ",pad=" + this.pad1 + ",pad1=" + this.pad2);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy