123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- */
- package org.alfresco.jlan.client;
- import java.io.*;
- import org.alfresco.jlan.debug.Debug;
- import org.alfresco.jlan.netbios.NetworkSession;
- import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
- import org.alfresco.jlan.smb.PacketType;
- import org.alfresco.jlan.smb.SMBErrorText;
- import org.alfresco.jlan.smb.SMBException;
- import org.alfresco.jlan.smb.SMBStatus;
- import org.alfresco.jlan.util.DataPacker;
- import org.alfresco.jlan.util.HexDump;
- /**
- * SMB packet type class
- *
- * <p>Contains the details of an SMB/CIFS request or response. The SMB packet class has methods for packing
- * and unpacking the various fields of the SMB header and requests.
- *
- * <p>Contains SMB/CIFS constants for SMB packet field offsets and header flag values.
- *
- * @author gkspencer
- */
- public class SMBPacket {
- // SMB packet offsets, assuming an RFC NetBIOS transport
- public static final int SMBHEADER = RFCNetBIOSProtocol.HEADER_LEN;
- public static final int COMMAND = 4 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int ERRORCODE = 5 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int ERRORCLASS = 5 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int ERROR = 7 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int FLAGS = 9 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int FLAGS2 = 10 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int PIDHIGH = 12 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int SIGNATURE = 14 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int SID = 18 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int SEQNO = 20 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int TID = 24 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int PID = 26 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int UID = 28 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int MID = 30 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int WORDCNT = 32 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int ANDXCOMMAND = 33 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int ANDXRESERVED = 34 + RFCNetBIOSProtocol.HEADER_LEN;
- public static final int PARAMWORDS = 33 + RFCNetBIOSProtocol.HEADER_LEN;
- // SMB packet header length for a transaction type request
- public static final int TRANS_HEADERLEN = 66 + RFCNetBIOSProtocol.HEADER_LEN;
- // Minimum receive length for a valid SMB packet
- public static final int MIN_RXLEN = 32;
- // Default buffer size to allocate for SMB packets
- public static final int DEFAULT_BUFSIZE = 4096;
- // Flag bits
- public static final int FLG_SUBDIALECT = 0x01;
- public static final int FLG_CASELESS = 0x08;
- public static final int FLG_CANONICAL = 0x10;
- public static final int FLG_OPLOCK = 0x20;
- public static final int FLG_NOTIFY = 0x40;
- public static final int FLG_RESPONSE = 0x80;
- // Flag2 bits
- public static final int FLG2_LONGFILENAMES = 0x0001;
- public static final int FLG2_EXTENDEDATTRIB = 0x0002;
- public static final int FLG2_SECURITYSIG = 0x0004;
- public static final int FLG2_EXTENDEDSETUP = 0x0800;
- public static final int FLG2_READIFEXE = 0x2000;
- public static final int FLG2_LONGERRORCODE = 0x4000;
- public static final int FLG2_UNICODE = 0x8000;
- // Security mode bits
- public static final int SEC_USER = 0x0001;
- public static final int SEC_ENCRYPT = 0x0002;
- // Raw mode bits
- public static final int RAW_READ = 0x0001;
- public static final int RAW_WRITE = 0x0002;
- // SMB packet buffer
- private byte[] m_smbbuf;
- // Packet type
- private int m_pkttype;
- // Current byte area pack/unpack position
-
- protected int m_pos;
- protected int m_endpos;
- // Time of last packet send
-
- protected long m_lastTxTime;
-
- /**
- * Default constructor
- */
- public SMBPacket() {
- m_smbbuf = new byte[DEFAULT_BUFSIZE];
- InitializeBuffer();
- }
- /**
- * Construct an SMB packet using the specified packet buffer.
- *
- * @param buf SMB packet buffer.
- */
- public SMBPacket(byte[] buf) {
- m_smbbuf = buf;
- }
- /**
- * Construct an SMB packet of the specified size.
- *
- * @param siz Size of SMB packet buffer to allocate.
- */
- public SMBPacket(int siz) {
- m_smbbuf = new byte[siz];
- InitializeBuffer();
- }
- /**
- * Check if a received SMB is valid, if not then throw an exception
- *
- * @exception SMBException
- */
- public final void checkForError()
- throws SMBException {
- // Check if a valid SMB response has been received
- if ( isValidResponse() == false) {
- // Check for NT error codes
- if ( isLongErrorCode())
- throw new SMBException(SMBStatus.NTErr, getLongErrorCode());
- else
- throw new SMBException(getErrorClass(), getErrorCode());
- }
- }
- /**
- * Clear the data byte count
- */
- public final void clearBytes() {
- int offset = getByteOffset() - 2;
- DataPacker.putIntelShort(0, m_smbbuf, offset);
- }
- /**
- * Dump the SMB packet to the debug stream
- */
- public void DumpPacket() {
- // Dump the command type
- int pCount = getParameterCount();
- Debug.println("** SMB Packet Type: " + PacketType.getCommandName(getCommand()) + (isResponse() ? " [Response]" : ""));
- // Dump flags/secondary flags
- if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket)) {
- // Dump the packet length
- Debug.println("** SMB Packet Dump");
- Debug.println("Packet Length : " + getLength());
- Debug.println("Byte Offset: " + getByteOffset() + ", Byte Count: " + getByteCount());
- // Dump the flags
- Debug.println("Flags: " + getFlagsAsString());
- Debug.println("Flags2: " + getFlags2AsString());
- // Dump the security signature is signing is enabled
- if ( hasSecuritySignature())
- Debug.println("Signature: " + Long.toHexString(getSignature()));
- // Dump various ids
- Debug.print("TID=" + getTreeId());
- Debug.print(", PID=" + getProcessId());
- Debug.print(", UID=" + getUserId());
- Debug.println(", MID=" + getMultiplexId());
- // Dump parameter words/count
- Debug.println("Parameter Words: " + pCount);
- if ( pCount > 0) {
- StringBuffer str = new StringBuffer(128);
- int colCnt = (pCount + 3) & 0xFFFC;
- int curCol = 1;
- for (int i = 0; i < colCnt; i++) {
- // Check if there is a parameter to output
- if ( i < pCount) {
- str.append("P");
- str.append(Integer.toString(i + 1));
- if ( i < 9)
- str.append(" ");
- str.append("=");
- str.append(Integer.toString(getParameter(i)));
- str.append("/0x");
- str.append(Integer.toHexString(getParameter(i)));
- }
- // Pad the column
- while (str.length() < (curCol * 20))
- str.append(" ");
- if ( curCol == 4) {
- curCol = 1;
- Debug.println(str.toString());
- str.setLength(0);
- }
- else
- curCol++;
- }
- }
- // Response packet fields
- if ( isResponse()) {
- // Dump the error code
- if ( isLongErrorCode())
- Debug.println("Long error: 0x" + Integer.toHexString(getLongErrorCode()));
- else {
- Debug.print("Error text: ");
- Debug.println(SMBErrorText.ErrorString(getErrorClass(), getErrorCode()));
- }
- }
- }
- // Dump the raw data
- if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGHexDump)) {
- Debug.println("********** Raw SMB Data Dump **********");
- HexDump.Dump(m_smbbuf, getLength(), 4);
- }
- Debug.println("");
- }
- /**
- * Check if the error class/code match the specified error/class
- *
- * @param errClass int
- * @param errCode int
- * @return boolean
- */
- public final boolean equalsError(int errClass, int errCode) {
- if ( getErrorClass() == errClass && getErrorCode() == errCode)
- return true;
- return false;
- }
- /**
- * Send the SMB packet and receive the response packet
- *
- * @param sess Network session to send/receive the packet over.
- * @param rxPkt SMB packet to receive the response into.
- * @param throwerr If true then throw an I/O error if an invalid response is received.
- * @exception java.io.IOException If a network error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- protected final synchronized void ExchangeLowLevelSMB(NetworkSession sess, SMBPacket rxPkt, boolean throwerr)
- throws java.io.IOException, SMBException {
- // Set multiplex id
- if ( getMultiplexId() == 0)
- setMultiplexId(1);
- // DEBUG
- if ( Session.hasDebug())
- DumpPacket();
- // Send the SMB request
- sess.Send(m_smbbuf, getLength());
- // Receive a response
- if ( sess.Receive(rxPkt.getBuffer()) >= MIN_RXLEN) {
- // Check if the response is for the current request
- if ( rxPkt.getCommand() == m_pkttype) {
- // DEBUG
- if ( Session.hasDebug())
- rxPkt.DumpPacket();
- // Check if a valid SMB response has been received
- if ( throwerr == true)
- checkForError();
- // Valid packet received, return to caller
- return;
- }
- }
- // Invalid receive packet
- throw new java.io.IOException("Invalid SMB Receive Packet");
- }
- /**
- * Send/receive an SMB protocol packet to the remote server.
- *
- * @param sess SMB session to send/receive data on.
- * @param rxPkt SMB packet to receive the response into.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs.
- */
- public synchronized final void ExchangeSMB(Session sess, SMBPacket rxPkt)
- throws SMBException, IOException {
- // Call the main SMB exhchange method
- ExchangeSMB(sess, rxPkt, false);
- }
- /**
- * Send the SMB packet and receive the response packet
- *
- * @param sess SMB session to send/receive the packet over.
- * @param rxPkt SMB packet to receive the response into.
- * @param throwerr If true then throw an I/O error if an invalid response is received.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs.
- */
- public synchronized final void ExchangeSMB(Session sess, SMBPacket rxPkt, boolean throwerr)
- throws SMBException, IOException {
- // Set the process id, user id and multiplex id
- setProcessId(sess.getProcessId());
- setUserId(sess.getUserId());
- if ( getMultiplexId() == 0)
- setMultiplexId(1);
- // DEBUG
- if ( Session.hasDebug())
- DumpPacket();
- // Get the network session
- NetworkSession netSess = sess.getSession();
- // Check if SMB signing is enabled, if so then set the SMB signature for the request
- if ( sess.hasSMBSigning())
- sess.signTxPacket(this);
- // Send the SMB request
- netSess.Send(m_smbbuf, getLength());
- // Receive the response, other asynchronous responses may be received before the response
- // for this request
- boolean rxValid = false;
- while (rxValid == false) {
- // Receive a response
- if ( netSess.Receive(rxPkt.getBuffer()) >= MIN_RXLEN) {
- // Check if the response is for the current request
- if ( rxPkt.getCommand() == m_pkttype) {
- // Check if SMB signing is enabled and received packet signatures should be
- // checked
- if ( sess.hasSMBSigning() && SessionFactory.isReceivedSMBSigningEnabled())
- sess.verifyRxPacket(this);
- // DEBUG
- if ( Session.hasDebug())
- rxPkt.DumpPacket();
- // Check if a valid SMB response has been received, done before checking SMB
- // signatures
- if ( throwerr == true)
- checkForError();
- // Valid packet received, return to caller
- return;
- }
- // Asynchronous response received, pass the packet to the session for processing
- sess.processAsynchResponse(rxPkt);
- }
- }
- // Invalid receive packet
- throw new java.io.IOException("Invalid SMB Receive Packet");
- }
- /**
- * Get the secondary command code
- *
- * @return Secondary command code
- */
- public final int getAndXCommand() {
- return (int) (m_smbbuf[ANDXCOMMAND] & 0xFF);
- }
- /**
- * Return the byte array used for the SMB packet
- *
- * @return Byte array used for the SMB packet.
- */
- public final byte[] getBuffer() {
- return m_smbbuf;
- }
- /**
- * Return the total buffer size available to the SMB request
- *
- * @return Total SMB buffer length available.
- */
- public final int getBufferLength() {
- return m_smbbuf.length - RFCNetBIOSProtocol.HEADER_LEN;
- }
- /**
- * Return the available buffer space for data bytes
- *
- * @return int
- */
- public final int getAvailableLength() {
- return m_smbbuf.length - DataPacker.longwordAlign(getByteOffset());
- }
- /**
- * Get the data byte count for the SMB packet
- *
- * @return Data byte count
- */
- public final int getByteCount() {
- // Calculate the offset of the byte count
- int pos = PARAMWORDS + (2 * getParameterCount());
- return (int) DataPacker.getIntelShort(m_smbbuf, pos);
- }
- /**
- * Get the data byte area offset within the SMB packet
- *
- * @return Data byte offset within the SMB packet.
- */
- public final int getByteOffset() {
- // Calculate the offset of the byte buffer
- int pCnt = getParameterCount();
- int pos = WORDCNT + (2 * pCnt) + 3;
- return pos;
- }
- /**
- * Get the SMB command
- *
- * @return SMB command code.
- */
- public final int getCommand() {
- return (int) (m_smbbuf[COMMAND] & 0xFF);
- }
- /**
- * Determine if normal or long error codes have been returned
- *
- * @return boolean
- */
- public final boolean hasLongErrorCode() {
- if ( (getFlags2() & FLG2_LONGERRORCODE) == 0)
- return false;
- return true;
- }
- /**
- * Determine if security signatures are being used
- *
- * @return boolean
- */
- public final boolean hasSecuritySignature() {
- if ( (getFlags2() & FLG2_SECURITYSIG) == 0)
- return false;
- return true;
- }
- /**
- * Determine if extended session setup is being used
- *
- * @return boolean
- */
- public final boolean hasExtendedSetup() {
- if ( (getFlags2() & FLG2_EXTENDEDSETUP) == 0)
- return false;
- return true;
- }
- /**
- * Return the saved packet type
- *
- * @return int
- */
- public final int isType() {
- return m_pkttype;
- }
- /**
- * Check if the packet contains ASCII or Unicode strings
- *
- * @return boolean
- */
- public final boolean isUnicode() {
- return (getFlags2() & FLG2_UNICODE) != 0 ? true : false;
- }
- /**
- * Check if the packet is using caseless filenames
- *
- * @return boolean
- */
- public final boolean isCaseless() {
- return (getFlags() & FLG_CASELESS) != 0 ? true : false;
- }
- /**
- * Check if long file names are being used
- *
- * @return boolean
- */
- public final boolean isLongFileNames() {
- return (getFlags2() & FLG2_LONGFILENAMES) != 0 ? true : false;
- }
- /**
- * Check if long error codes are being used
- *
- * @return boolean
- */
- public final boolean isLongErrorCode() {
- return (getFlags2() & FLG2_LONGERRORCODE) != 0 ? true : false;
- }
- /**
- * Get the SMB error class
- *
- * @return SMB error class.
- */
- public final int getErrorClass() {
- return (int) m_smbbuf[ERRORCLASS] & 0xFF;
- }
- /**
- * Get the SMB error code
- *
- * @return SMB error code.
- */
- public final int getErrorCode() {
- return (int) m_smbbuf[ERROR] & 0xFF;
- }
- /**
- * Get the SMB flags value.
- *
- * @return SMB flags value.
- */
- public final int getFlags() {
- return (int) m_smbbuf[FLAGS] & 0xFF;
- }
- /**
- * Get the SMB flags2 value.
- *
- * @return SMB flags2 value.
- */
- public final int getFlags2() {
- return (int) DataPacker.getIntelShort(m_smbbuf, FLAGS2);
- }
- /**
- * Calculate the total used packet length.
- *
- * @return Total used packet length.
- */
- public final int getLength() {
- return (getByteOffset() + getByteCount()) - RFCNetBIOSProtocol.HEADER_LEN;
- }
- /**
- * Get the long SMB error code
- *
- * @return Long SMB error code.
- */
- public final int getLongErrorCode() {
- return DataPacker.getIntelInt(m_smbbuf, ERRORCODE);
- }
- /**
- * Get the multiplex identifier.
- *
- * @return Multiplex identifier.
- */
- public final int getMultiplexId() {
- return DataPacker.getIntelShort(m_smbbuf, MID);
- }
- /**
- * Get a parameter word from the SMB packet.
- *
- * @param idx Parameter index (zero based).
- * @return Parameter word value.
- * @exception java.lang.IndexOutOfBoundsException If the parameter index is out of range.
- */
- public final int getParameter(int idx)
- throws java.lang.IndexOutOfBoundsException {
- // Range check the parameter index
- if ( idx > getParameterCount())
- throw new java.lang.IndexOutOfBoundsException();
- // Calculate the parameter word offset
- int pos = WORDCNT + (2 * idx) + 1;
- return (int) (DataPacker.getIntelShort(m_smbbuf, pos) & 0xFFFF);
- }
- /**
- * Get the specified parameter words, as an int value.
- *
- * @param idx Parameter index (zero based).
- * @return int
- */
- public final int getParameterLong(int idx) {
- int pos = WORDCNT + (2 * idx) + 1;
- return DataPacker.getIntelInt(m_smbbuf, pos);
- }
- /**
- * Get the parameter count
- *
- * @return Parameter word count.
- */
- public final int getParameterCount() {
- return (int) m_smbbuf[WORDCNT];
- }
- /**
- * Get the process indentifier (PID)
- *
- * @return Process identifier value.
- */
- public final int getProcessId() {
- return DataPacker.getIntelShort(m_smbbuf, PID);
- }
- /**
- * Get the SMB signing value, as a long value
- *
- * @return long
- */
- public final long getSignature() {
- return DataPacker.getIntelLong(m_smbbuf, SIGNATURE);
- }
- /**
- * Get the tree identifier (TID)
- *
- * @return Tree identifier (TID)
- */
- public final int getTreeId() {
- return DataPacker.getIntelShort(m_smbbuf, TID);
- }
- /**
- * Get the user identifier (UID)
- *
- * @return User identifier (UID)
- */
- public final int getUserId() {
- return DataPacker.getIntelShort(m_smbbuf, UID);
- }
- /**
- * Return the last sent packet time
- *
- * @return long
- */
- public final long getLastPacketSendTime() {
- return m_lastTxTime;
- }
- /**
- * Initialize the SMB packet buffer.
- */
- private final void InitializeBuffer() {
- // Set the packet signature
- m_smbbuf[SMBHEADER] = (byte) 0xFF;
- m_smbbuf[SMBHEADER + 1] = (byte) 'S';
- m_smbbuf[SMBHEADER + 2] = (byte) 'M';
- m_smbbuf[SMBHEADER + 3] = (byte) 'B';
- }
- /**
- * Determine if this packet is an SMB response, or command packet
- *
- * @return true if this SMB packet is a response, else false
- */
- public final boolean isResponse() {
- int resp = getFlags();
- if ( (resp & FLG_RESPONSE) != 0)
- return true;
- return false;
- }
- /**
- * Check if this is an SMB request packet
- *
- * @return boolean
- */
- public final boolean isRequest() {
- return ( getFlags() & FLG_RESPONSE) == 0 ? true : false;
- }
-
- /**
- * Check if the response packet is valid, ie. type and flags
- *
- * @return true if the SMB packet is a response packet and the response is valid, else false.
- */
- public final boolean isValidResponse() {
- // Check if this is a response packet, and the correct type of packet
- if ( isResponse() && getCommand() == m_pkttype) {
- // Check if standard error codes or NT 32-bit error codes are being used
- if ( (getFlags2() & FLG2_LONGERRORCODE) == 0) {
- if ( getErrorCode() == SMBStatus.Success)
- return true;
- }
- else if ( getLongErrorCode() == SMBStatus.NTSuccess)
- return true;
- }
- return false;
- }
- /**
- * Pack a byte (8 bit) value into the byte area
- *
- * @param val byte
- */
- public final void packByte(byte val) {
- m_smbbuf[m_pos++] = val;
- }
- /**
- * Pack a byte (8 bit) value into the byte area
- *
- * @param val int
- */
- public final void packByte(int val) {
- m_smbbuf[m_pos++] = (byte) val;
- }
- /**
- * Pack the specified bytes into the byte area
- *
- * @param byts byte[]
- * @param len int
- */
- public final void packBytes(byte[] byts, int len) {
- System.arraycopy(byts, 0, m_smbbuf, m_pos, len);
- m_pos += len;
- }
- /**
- * Pack a string using either ASCII or Unicode into the byte area
- *
- * @param str String
- * @param uni boolean
- */
- public final void packString(String str, boolean uni) {
- // Check for Unicode or ASCII
- if ( uni) {
- // Word align the buffer position, pack the Unicode string
- m_pos = DataPacker.wordAlign(m_pos);
- DataPacker.putUnicodeString(str, m_smbbuf, m_pos, true);
- m_pos += (str.length() * 2) + 2;
- }
- else {
- // Pack the ASCII string
- DataPacker.putString(str, m_smbbuf, m_pos, true);
- m_pos += str.length() + 1;
- }
- }
- /**
- * Pack a word (16 bit) value into the byte area
- *
- * @param val int
- */
- public final void packWord(int val) {
- DataPacker.putIntelShort(val, m_smbbuf, m_pos);
- m_pos += 2;
- }
- /**
- * Pack a 32 bit integer value into the byte area
- *
- * @param val int
- */
- public final void packInt(int val) {
- DataPacker.putIntelInt(val, m_smbbuf, m_pos);
- m_pos += 4;
- }
- /**
- * Pack a long integer (64 bit) value into the byte area
- *
- * @param val long
- */
- public final void packLong(long val) {
- DataPacker.putIntelLong(val, m_smbbuf, m_pos);
- m_pos += 8;
- }
- /**
- * Return the current byte area buffer position
- *
- * @return int
- */
- public final int getPosition() {
- return m_pos;
- }
- /**
- * Set the byte area buffer position
- *
- * @param pos int
- */
- public final void setPosition(int pos) {
- m_pos = pos;
- }
- /**
- * Unpack a byte value from the byte area
- *
- * @return int
- */
- public final int unpackByte() {
- return (int) m_smbbuf[m_pos++];
- }
- /**
- * Unpack a block of bytes from the byte area
- *
- * @param len int
- * @return byte[]
- */
- public final byte[] unpackBytes(int len) {
- if ( len <= 0)
- return null;
- byte[] buf = new byte[len];
- System.arraycopy(m_smbbuf, m_pos, buf, 0, len);
- m_pos += len;
- return buf;
- }
- /**
- * Unpack a word (16 bit) value from the byte area
- *
- * @return int
- */
- public final int unpackWord() {
- int val = DataPacker.getIntelShort(m_smbbuf, m_pos);
- m_pos += 2;
- return val;
- }
- /**
- * Unpack an integer (32 bit) value from the byte/parameter area
- *
- * @return int
- */
- public final int unpackInt() {
- int val = DataPacker.getIntelInt(m_smbbuf, m_pos);
- m_pos += 4;
- return val;
- }
- /**
- * Unpack a long integer (64 bit) value from the byte area
- *
- * @return long
- */
- public final long unpackLong() {
- long val = DataPacker.getIntelLong(m_smbbuf, m_pos);
- m_pos += 8;
- return val;
- }
- /**
- * Unpack a string from the byte area
- *
- * @param uni boolean
- * @return String
- */
- public final String unpackString(boolean uni) {
- // Check for Unicode or ASCII
- String ret = null;
- if ( uni) {
- // Word align the current buffer position
- m_pos = DataPacker.wordAlign(m_pos);
- ret = DataPacker.getUnicodeString(m_smbbuf, m_pos, 255);
- if ( ret != null)
- m_pos += (ret.length() * 2) + 2;
- }
- else {
- // Unpack the ASCII string
- ret = DataPacker.getString(m_smbbuf, m_pos, 255);
- if ( ret != null)
- m_pos += ret.length() + 1;
- }
- // Return the string
- return ret;
- }
- /**
- * Unpack a string from the byte area
- *
- * @param len int
- * @param uni boolean
- * @return String
- */
- public final String unpackString(int len, boolean uni) {
- // Check for Unicode or ASCII
- String ret = null;
- if ( uni) {
- // Word align the current buffer position
- m_pos = DataPacker.wordAlign(m_pos);
- ret = DataPacker.getUnicodeString(m_smbbuf, m_pos, len);
- if ( ret != null)
- m_pos += (ret.length() * 2);
- }
- else {
- // Unpack the ASCII string
- ret = DataPacker.getString(m_smbbuf, m_pos, len);
- if ( ret != null)
- m_pos += ret.length();
- }
- // Return the string
- return ret;
- }
- /**
- * Check if there is more data in the byte area
- *
- * @return boolean
- */
- public final boolean hasMoreData() {
- if ( m_pos < m_endpos)
- return true;
- return false;
- }
- /**
- * Receive an SMB packet on the spceified SMB session.
- *
- * @param sess SMB session to receive the packet on.
- * @exception java.io.IOException If a network error occurs
- * @exception SMBException If an SMB level error occurs
- */
- protected final void ReceiveSMB(Session sess)
- throws java.io.IOException, SMBException {
- // Call the main receive method
- ReceiveSMB(sess, true);
- }
- /**
- * Receive an SMB packet on the spceified SMB session.
- *
- * @param sess SMB session to receive the packet on.
- * @param throwErr Flag to indicate if an error is thrown if an error response is received
- * @exception java.io.IOException If a network error occurs
- * @exception SMBException If an SMB level error occurs
- */
- protected final void ReceiveSMB(Session sess, boolean throwErr)
- throws java.io.IOException, SMBException {
- // Get the network session
- NetworkSession netSess = sess.getSession();
- // Receive the response, other asynchronous responses may be received before the response
- // for this request
- boolean rxValid = false;
- while (rxValid == false) {
- // Receive a response
- if ( netSess.Receive(getBuffer()) >= MIN_RXLEN) {
- // Check if the response is for the current request
- if ( getCommand() == m_pkttype) {
- // DEBUG
- if ( Session.hasDebug())
- DumpPacket();
- // Check if SMB signing is enabled and received packet signatures should be
- // checked
- if ( sess.hasSMBSigning() && SessionFactory.isReceivedSMBSigningEnabled())
- sess.verifyRxPacket(this);
- // Check if a valid SMB response has been received
- if ( throwErr == true)
- checkForError();
- // Valid packet received, return to caller
- return;
- }
- // Asynchronous response received, pass the packet to the session for processing
- sess.processAsynchResponse(this);
- }
- else {
- // Not enough data received for an SMB header
- throw new java.io.IOException("Short NetBIOS receive");
- }
- }
- }
- /**
- * Receive an asynchronous SMB response from the server
- *
- * @param sess Session
- * @param waitTime Receive timeout in milliseconds, or zero for no timeout
- * @throws java.io.IOException
- * @throws SMBException
- */
- protected final void ReceiveAsynchSMB(Session sess, int waitTime)
- throws java.io.IOException, SMBException {
- // Get the network session
- NetworkSession netSess = sess.getSession();
- netSess.setTimeout(waitTime);
- // Receive, or wait for, a response
- if ( netSess.Receive(getBuffer()) >= MIN_RXLEN) {
- // Asynchronous response received, pass the packet to the session for processing
- sess.processAsynchResponse(this);
- }
- else {
- // Not enough data received for an SMB header
- throw new java.io.IOException("Short NetBIOS receive");
- }
- }
- /**
- * Send the SMB packet on the specified SMB session.
- *
- * @param sess SMB session to send this packet over.
- * @exception java.io.IOException If an I/O error occurs.
- */
- protected final void SendSMB(Session sess)
- throws java.io.IOException {
- // DEBUG
- if ( Session.hasDebug())
- DumpPacket();
- // Update the last send time
- m_lastTxTime = System.currentTimeMillis();
- // Check if SMB signing is enabled, if so then set the SMB signature for the request
- if ( sess.hasSMBSigning())
- sess.signTxPacket(this);
- // Send the SMB request
- sess.getSession().Send(m_smbbuf, getLength());
- }
- /**
- * Set the secondary SMB command
- *
- * @param cmd Secondary SMB command code.
- */
- public final void setAndXCommand(int cmd) {
- // Set the chained command packet type
- m_smbbuf[ANDXCOMMAND] = (byte) cmd;
- m_smbbuf[ANDXRESERVED] = (byte) 0;
- // If the AndX command is disabled clear the offset to the chained packet
- if ( cmd == PacketType.NoChainedCommand)
- setParameter(1, 0);
- }
- /**
- * Set the data byte count for this SMB packet
- *
- * @param cnt Data byte count.
- */
- public final void setByteCount(int cnt) {
- int offset = getByteOffset() - 2;
- DataPacker.putIntelShort(cnt, m_smbbuf, offset);
- }
- /**
- * Set the data byte count for this SMB packet
- */
- public final void setByteCount() {
- int offset = getByteOffset() - 2;
- int len = m_pos - getByteOffset();
- DataPacker.putIntelShort(len, m_smbbuf, offset);
- }
- /**
- * Set the data byte area in the SMB packet
- *
- * @param byts Byte array containing the data to be copied to the SMB packet.
- */
- public final void setBytes(byte[] byts) {
- int offset = getByteOffset() - 2;
- DataPacker.putIntelShort(byts.length, m_smbbuf, offset);
- offset += 2;
- for (int idx = 0; idx < byts.length; m_smbbuf[offset + idx] = byts[idx++])
- ;
- }
- /**
- * Set the SMB command
- *
- * @param cmd SMB command code
- */
- public final void setCommand(int cmd) {
- m_pkttype = cmd;
- m_smbbuf[COMMAND] = (byte) cmd;
- }
- /**
- * Set the SMB error class.
- *
- * @param cl SMB error class.
- */
- public final void setErrorClass(int cl) {
- m_smbbuf[ERRORCLASS] = (byte) (cl & 0xFF);
- }
- /**
- * Set the SMB error code
- *
- * @param sts SMB error code.
- */
- public final void setErrorCode(int sts) {
- m_smbbuf[ERROR] = (byte) (sts & 0xFF);
- }
- /**
- * Set a long error code (NT status code)
- *
- * @param lsts int
- */
- public final void setLongErrorCode(int lsts) {
- DataPacker.putIntelInt(lsts, m_smbbuf, ERRORCODE);
- }
- /**
- * Set the SMB flags value.
- *
- * @param flg SMB flags value.
- */
- public final void setFlags(int flg) {
- m_smbbuf[FLAGS] = (byte) flg;
- }
- /**
- * Set the SMB flags2 value.
- *
- * @param flg SMB flags2 value.
- */
- public final void setFlags2(int flg) {
- DataPacker.putIntelShort(flg, m_smbbuf, FLAGS2);
- }
- /**
- * Set the multiplex identifier.
- *
- * @param mid Multiplex identifier
- */
- public final void setMultiplexId(int mid) {
- DataPacker.putIntelShort(mid, m_smbbuf, MID);
- }
- /**
- * Set the specified parameter word.
- *
- * @param idx Parameter index (zero based).
- * @param val Parameter value.
- */
- public final void setParameter(int idx, int val) {
- int pos = WORDCNT + (2 * idx) + 1;
- DataPacker.putIntelShort(val, m_smbbuf, pos);
- }
- /**
- * Set the specified parameter words.
- *
- * @param idx Parameter index (zero based).
- * @param val Parameter value.
- */
- public final void setParameterLong(int idx, int val) {
- int pos = WORDCNT + (2 * idx) + 1;
- DataPacker.putIntelInt(val, m_smbbuf, pos);
- }
- /**
- * Set the parameter count
- *
- * @param cnt Parameter word count.
- */
- public final void setParameterCount(int cnt) {
- m_smbbuf[WORDCNT] = (byte) cnt;
- }
- /**
- * Set the process identifier value (PID).
- *
- * @param pid Process identifier value.
- */
- public final void setProcessId(int pid) {
- DataPacker.putIntelShort(pid, m_smbbuf, PID);
- }
- /**
- * Set the packet sequence number, for connectionless commands.
- *
- * @param seq Sequence number.
- */
- public final void setSeqNo(int seq) {
- DataPacker.putIntelShort(seq, m_smbbuf, SEQNO);
- }
- /**
- * Set the session id.
- *
- * @param sid Session id.
- */
- public final void setSID(int sid) {
- DataPacker.putIntelShort(sid, m_smbbuf, SID);
- }
- /**
- * Set the SMB signing signature
- *
- * @param ival int
- */
- public final void setSignature(int ival) {
- DataPacker.putIntelInt(ival, m_smbbuf, SIGNATURE);
- DataPacker.putZeros(m_smbbuf, SIGNATURE + 4, 4);
- }
- /**
- * Set the SMB signing signature
- *
- * @param lval long
- */
- public final void setSignature(long lval) {
- DataPacker.putIntelLong(lval, m_smbbuf, SIGNATURE);
- }
- /**
- * Set the SMB signing signature
- *
- * @param byts byte[]
- * @param offset int
- */
- public final void setSignature(byte[] byts, int offset) {
- System.arraycopy(byts, offset, m_smbbuf, SIGNATURE, 8);
- }
- /**
- * Set the tree identifier (TID)
- *
- * @param tid Tree identifier value.
- */
- public final void setTreeId(int tid) {
- DataPacker.putIntelShort(tid, m_smbbuf, TID);
- }
- /**
- * Set the user identifier (UID)
- *
- * @param uid User identifier value.
- */
- public final void setUserId(int uid) {
- DataPacker.putIntelShort(uid, m_smbbuf, UID);
- }
- /**
- * Align the byte area pointer on an int (32bit) boundary
- */
- public final void alignBytePointer() {
- m_pos = DataPacker.longwordAlign(m_pos);
- }
- /**
- * Reset the byte/parameter pointer area for packing/unpacking data items from the packet
- */
- public final void resetBytePointer() {
- m_pos = getByteOffset();
- m_endpos = m_pos + getByteCount();
- }
- /**
- * Reset the byte/parameter pointer area for packing/unpacking data items from the packet, and
- * align the buffer on an int (32bit) boundary
- */
- public final void resetBytePointerAlign() {
- m_pos = DataPacker.longwordAlign(getByteOffset());
- m_endpos = m_pos + getByteCount();
- }
- /**
- * Reset the byte/parameter pointer area for packing/unpacking paramaters from the packet
- */
- public final void resetParameterPointer() {
- m_pos = PARAMWORDS;
- }
- /**
- * Set the unpack pointer to the specified offset, for AndX processing
- *
- * @param off int
- * @param len int
- */
- public final void setBytePointer(int off, int len) {
- m_pos = off;
- m_endpos = m_pos + len;
- }
- /**
- * Skip a number of bytes in the parameter/byte area
- *
- * @param cnt int
- */
- public final void skipBytes(int cnt) {
- m_pos += cnt;
- }
- /**
- * Return the flags value as a string
- *
- * @return String
- */
- protected final String getFlagsAsString() {
- // Get the flags value
- int flags = getFlags();
- if ( flags == 0)
- return "<None>";
- StringBuffer str = new StringBuffer();
- if ( (flags & FLG_SUBDIALECT) != 0)
- str.append("SubDialect,");
- if ( (flags & FLG_CASELESS) != 0)
- str.append("Caseless,");
- if ( (flags & FLG_CANONICAL) != 0)
- str.append("Canonical,");
- if ( (flags & FLG_OPLOCK) != 0)
- str.append("Oplock,");
- if ( (flags & FLG_NOTIFY) != 0)
- str.append("Notify,");
- if ( (flags & FLG_RESPONSE) != 0)
- str.append("Response,");
- str.setLength(str.length() - 1);
- return str.toString();
- }
- /**
- * Return the flags2 value as a string
- *
- * @return String
- */
- protected final String getFlags2AsString() {
- // Get the flags2 value
- int flags2 = getFlags2();
- if ( flags2 == 0)
- return "<None>";
- StringBuffer str = new StringBuffer();
- if ( (flags2 & FLG2_LONGFILENAMES) != 0)
- str.append("LongFilenames,");
- if ( (flags2 & FLG2_EXTENDEDATTRIB) != 0)
- str.append("ExtAttributes,");
- if ( (flags2 & FLG2_SECURITYSIG) != 0)
- str.append("SecuritySignatures,");
- if ( (flags2 & FLG2_EXTENDEDSETUP) != 0)
- str.append("ExtendedSetup,");
- if ( (flags2 & FLG2_READIFEXE) != 0)
- str.append("ReadIfEXE,");
- if ( (flags2 & FLG2_LONGERRORCODE) != 0)
- str.append("LongErrorCode,");
- if ( (flags2 & FLG2_UNICODE) != 0)
- str.append("Unicode,");
- str.setLength(str.length() - 1);
- return str.toString();
- }
- }
|