mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-02 17:35:18 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
800 lines
24 KiB
Java
800 lines
24 KiB
Java
/*
|
|
* Copyright (C) 2005 Alfresco, Inc.
|
|
*
|
|
* Licensed under the Mozilla Public License version 1.1
|
|
* with a permitted attribution clause. You may obtain a
|
|
* copy of the License at
|
|
*
|
|
* http://www.alfresco.org/legal/license.txt
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
* either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the
|
|
* License.
|
|
*/
|
|
package org.alfresco.filesys.smb.server;
|
|
|
|
import java.io.IOException;
|
|
|
|
import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
|
|
import org.alfresco.filesys.server.filesys.TreeConnection;
|
|
import org.alfresco.filesys.smb.DataType;
|
|
import org.alfresco.filesys.smb.PacketType;
|
|
import org.alfresco.filesys.smb.SMBStatus;
|
|
import org.alfresco.filesys.smb.TransactBuffer;
|
|
import org.alfresco.filesys.smb.dcerpc.DCEBuffer;
|
|
import org.alfresco.filesys.smb.dcerpc.DCEBufferException;
|
|
import org.alfresco.filesys.smb.dcerpc.DCECommand;
|
|
import org.alfresco.filesys.smb.dcerpc.DCEDataPacker;
|
|
import org.alfresco.filesys.smb.dcerpc.DCEPipeType;
|
|
import org.alfresco.filesys.smb.dcerpc.UUID;
|
|
import org.alfresco.filesys.smb.dcerpc.server.DCEPipeFile;
|
|
import org.alfresco.filesys.smb.dcerpc.server.DCESrvPacket;
|
|
import org.alfresco.filesys.util.DataBuffer;
|
|
import org.alfresco.filesys.util.DataPacker;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* DCE/RPC Protocol Handler Class
|
|
*/
|
|
public class DCERPCHandler
|
|
{
|
|
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
|
|
|
|
/**
|
|
* Process a DCE/RPC request
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param srvTrans SMBSrvTransPacket
|
|
* @param outPkt SMBSrvPacket
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void processDCERPCRequest(SMBSrvSession sess, SMBSrvTransPacket srvTrans, SMBSrvPacket outPkt)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Get the tree id from the received packet and validate that it is a valid
|
|
// connection id.
|
|
|
|
int treeId = srvTrans.getTreeId();
|
|
TreeConnection conn = sess.findConnection(treeId);
|
|
|
|
if (conn == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Get the file id and validate
|
|
|
|
int fid = srvTrans.getSetupParameter(1);
|
|
int maxData = srvTrans.getParameter(3) - DCEBuffer.OPERATIONDATA;
|
|
|
|
// Get the IPC pipe file for the specified file id
|
|
|
|
DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid);
|
|
if (pipeFile == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Create a DCE/RPC buffer from the received data
|
|
|
|
DCEBuffer dceBuf = new DCEBuffer(srvTrans.getBuffer(), srvTrans.getParameter(10)
|
|
+ RFCNetBIOSProtocol.HEADER_LEN);
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("TransactNmPipe pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x"
|
|
+ Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE)));
|
|
|
|
// Process the received DCE buffer
|
|
|
|
processDCEBuffer(sess, dceBuf, pipeFile);
|
|
|
|
// Check if there is a reply buffer to return to the caller
|
|
|
|
if (pipeFile.hasBufferedData() == false)
|
|
return;
|
|
|
|
DCEBuffer txBuf = pipeFile.getBufferedData();
|
|
|
|
// Initialize the reply
|
|
|
|
DCESrvPacket dcePkt = new DCESrvPacket(outPkt.getBuffer());
|
|
|
|
// Always only one fragment as the data either fits into the first reply fragment or the
|
|
// client will read the remaining data by issuing read requests on the pipe
|
|
|
|
int flags = DCESrvPacket.FLG_ONLYFRAG;
|
|
|
|
dcePkt.initializeDCEReply();
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, flags);
|
|
|
|
// Build the reply data
|
|
|
|
byte[] buf = dcePkt.getBuffer();
|
|
int pos = DCEDataPacker.longwordAlign(dcePkt.getByteOffset());
|
|
|
|
// Set the DCE fragment size and send the reply DCE/RPC SMB
|
|
|
|
int dataLen = txBuf.getLength();
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, dataLen);
|
|
|
|
// Copy the data from the DCE output buffer to the reply SMB packet
|
|
|
|
int len = txBuf.getLength();
|
|
int sts = SMBStatus.NTSuccess;
|
|
|
|
if (len > maxData)
|
|
{
|
|
|
|
// Write the maximum transmit fragment to the reply
|
|
|
|
len = maxData + DCEBuffer.OPERATIONDATA;
|
|
dataLen = maxData + DCEBuffer.OPERATIONDATA;
|
|
|
|
// Indicate a buffer overflow status
|
|
|
|
sts = SMBStatus.NTBufferOverflow;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Clear the DCE/RPC pipe buffered data, the reply will fit into a single response
|
|
// packet
|
|
|
|
pipeFile.setBufferedData(null);
|
|
}
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("Reply DCEbuf flags=0x" + Integer.toHexString(flags) + ", len=" + len + ", status=0x"
|
|
+ Integer.toHexString(sts));
|
|
|
|
// Copy the reply data to the reply packet
|
|
|
|
try
|
|
{
|
|
pos += txBuf.copyData(buf, pos, len);
|
|
}
|
|
catch (DCEBufferException ex)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv);
|
|
return;
|
|
}
|
|
|
|
// Set the SMB transaction data length
|
|
|
|
int byteLen = pos - dcePkt.getByteOffset();
|
|
dcePkt.setParameter(1, dataLen);
|
|
dcePkt.setParameter(6, dataLen);
|
|
dcePkt.setByteCount(byteLen);
|
|
dcePkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE);
|
|
dcePkt.setLongErrorCode(sts);
|
|
|
|
sess.sendResponseSMB(dcePkt);
|
|
}
|
|
|
|
/**
|
|
* Process a DCE/RPC request
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param tbuf TransactBuffer
|
|
* @param outPkt SMBSrvPacket
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void processDCERPCRequest(SMBSrvSession sess, TransactBuffer tbuf, SMBSrvPacket outPkt)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Check if the transaction buffer has setup and data buffers
|
|
|
|
if (tbuf.hasSetupBuffer() == false || tbuf.hasDataBuffer() == false)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
|
|
return;
|
|
}
|
|
|
|
// Get the tree id from the received packet and validate that it is a valid
|
|
// connection id.
|
|
|
|
int treeId = tbuf.getTreeId();
|
|
TreeConnection conn = sess.findConnection(treeId);
|
|
|
|
if (conn == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Get the file id and validate
|
|
|
|
DataBuffer setupBuf = tbuf.getSetupBuffer();
|
|
|
|
setupBuf.skipBytes(2);
|
|
int fid = setupBuf.getShort();
|
|
int maxData = tbuf.getReturnDataLimit() - DCEBuffer.OPERATIONDATA;
|
|
|
|
// Get the IPC pipe file for the specified file id
|
|
|
|
DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid);
|
|
if (pipeFile == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Create a DCE/RPC buffer from the received transaction data
|
|
|
|
DCEBuffer dceBuf = new DCEBuffer(tbuf);
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("TransactNmPipe pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x"
|
|
+ Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE)));
|
|
|
|
// Process the received DCE buffer
|
|
|
|
processDCEBuffer(sess, dceBuf, pipeFile);
|
|
|
|
// Check if there is a reply buffer to return to the caller
|
|
|
|
if (pipeFile.hasBufferedData() == false)
|
|
return;
|
|
|
|
DCEBuffer txBuf = pipeFile.getBufferedData();
|
|
|
|
// Initialize the reply
|
|
|
|
DCESrvPacket dcePkt = new DCESrvPacket(outPkt.getBuffer());
|
|
|
|
// Always only one fragment as the data either fits into the first reply fragment or the
|
|
// client will read the remaining data by issuing read requests on the pipe
|
|
|
|
int flags = DCESrvPacket.FLG_ONLYFRAG;
|
|
|
|
dcePkt.initializeDCEReply();
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, flags);
|
|
|
|
// Build the reply data
|
|
|
|
byte[] buf = dcePkt.getBuffer();
|
|
int pos = DCEDataPacker.longwordAlign(dcePkt.getByteOffset());
|
|
|
|
// Set the DCE fragment size and send the reply DCE/RPC SMB
|
|
|
|
int dataLen = txBuf.getLength();
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, dataLen);
|
|
|
|
// Copy the data from the DCE output buffer to the reply SMB packet
|
|
|
|
int len = txBuf.getLength();
|
|
int sts = SMBStatus.NTSuccess;
|
|
|
|
if (len > maxData)
|
|
{
|
|
|
|
// Write the maximum transmit fragment to the reply
|
|
|
|
len = maxData + DCEBuffer.OPERATIONDATA;
|
|
dataLen = maxData + DCEBuffer.OPERATIONDATA;
|
|
|
|
// Indicate a buffer overflow status
|
|
|
|
sts = SMBStatus.NTBufferOverflow;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Clear the DCE/RPC pipe buffered data, the reply will fit into a single response
|
|
// packet
|
|
|
|
pipeFile.setBufferedData(null);
|
|
}
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("Reply DCEbuf flags=0x" + Integer.toHexString(flags) + ", len=" + len + ", status=0x"
|
|
+ Integer.toHexString(sts));
|
|
|
|
// Copy the reply data to the reply packet
|
|
|
|
try
|
|
{
|
|
pos += txBuf.copyData(buf, pos, len);
|
|
}
|
|
catch (DCEBufferException ex)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv);
|
|
return;
|
|
}
|
|
|
|
// Set the SMB transaction data length
|
|
|
|
int byteLen = pos - dcePkt.getByteOffset();
|
|
dcePkt.setParameter(1, dataLen);
|
|
dcePkt.setParameter(6, dataLen);
|
|
dcePkt.setByteCount(byteLen);
|
|
dcePkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE);
|
|
dcePkt.setLongErrorCode(sts);
|
|
|
|
sess.sendResponseSMB(dcePkt);
|
|
}
|
|
|
|
/**
|
|
* Process a DCE/RPC write request to the named pipe file
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param inPkt SMBSrvPacket
|
|
* @param outPkt SMBSrvPacket
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void processDCERPCRequest(SMBSrvSession sess, SMBSrvPacket inPkt, SMBSrvPacket outPkt)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Get the tree id from the received packet and validate that it is a valid
|
|
// connection id.
|
|
|
|
int treeId = inPkt.getTreeId();
|
|
TreeConnection conn = sess.findConnection(treeId);
|
|
|
|
if (conn == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Determine if this is a write or write andX request
|
|
|
|
int cmd = inPkt.getCommand();
|
|
|
|
// Get the file id and validate
|
|
|
|
int fid = -1;
|
|
if (cmd == PacketType.WriteFile)
|
|
fid = inPkt.getParameter(0);
|
|
else
|
|
fid = inPkt.getParameter(2);
|
|
|
|
// Get the IPC pipe file for the specified file id
|
|
|
|
DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid);
|
|
if (pipeFile == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Create a DCE buffer for the received data
|
|
|
|
DCEBuffer dceBuf = null;
|
|
byte[] buf = inPkt.getBuffer();
|
|
int pos = 0;
|
|
int len = 0;
|
|
|
|
if (cmd == PacketType.WriteFile)
|
|
{
|
|
|
|
// Get the data offset
|
|
|
|
pos = inPkt.getByteOffset();
|
|
|
|
// Check that the received data is valid
|
|
|
|
if (buf[pos++] != DataType.DataBlock)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidData, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
len = DataPacker.getIntelShort(buf, pos);
|
|
pos += 2;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// Get the data offset and length
|
|
|
|
len = inPkt.getParameter(10);
|
|
pos = inPkt.getParameter(11) + RFCNetBIOSProtocol.HEADER_LEN;
|
|
}
|
|
|
|
// Create a DCE buffer mapped to the received packet
|
|
|
|
dceBuf = new DCEBuffer(buf, pos);
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
|
|
logger.debug("Write pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x"
|
|
+ Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE)));
|
|
|
|
// Process the DCE buffer
|
|
|
|
processDCEBuffer(sess, dceBuf, pipeFile);
|
|
|
|
// Check if there is a valid reply buffered
|
|
|
|
int bufLen = 0;
|
|
if (pipeFile.hasBufferedData())
|
|
bufLen = pipeFile.getBufferedData().getLength();
|
|
|
|
// Send the write/write andX reply
|
|
|
|
if (cmd == PacketType.WriteFile)
|
|
{
|
|
|
|
// Build the write file reply
|
|
|
|
outPkt.setParameterCount(1);
|
|
outPkt.setParameter(0, len);
|
|
outPkt.setByteCount(0);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Build the write andX reply
|
|
|
|
outPkt.setParameterCount(6);
|
|
|
|
outPkt.setAndXCommand(0xFF);
|
|
outPkt.setParameter(1, 0);
|
|
outPkt.setParameter(2, len);
|
|
outPkt.setParameter(3, bufLen);
|
|
outPkt.setParameter(4, 0);
|
|
outPkt.setParameter(5, 0);
|
|
outPkt.setByteCount(0);
|
|
}
|
|
|
|
// Send the write reply
|
|
|
|
outPkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE);
|
|
sess.sendResponseSMB(outPkt);
|
|
}
|
|
|
|
/**
|
|
* Process a DCE/RPC pipe read request
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param inPkt SMBSrvPacket
|
|
* @param outPkt SMBSrvPacket
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void processDCERPCRead(SMBSrvSession sess, SMBSrvPacket inPkt, SMBSrvPacket outPkt)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Get the tree id from the received packet and validate that it is a valid
|
|
// connection id.
|
|
|
|
int treeId = inPkt.getTreeId();
|
|
TreeConnection conn = sess.findConnection(treeId);
|
|
|
|
if (conn == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Determine if this is a read or read andX request
|
|
|
|
int cmd = inPkt.getCommand();
|
|
|
|
// Get the file id and read length, and validate
|
|
|
|
int fid = -1;
|
|
int rdLen = -1;
|
|
|
|
if (cmd == PacketType.ReadFile)
|
|
{
|
|
fid = inPkt.getParameter(0);
|
|
rdLen = inPkt.getParameter(1);
|
|
}
|
|
else
|
|
{
|
|
fid = inPkt.getParameter(2);
|
|
rdLen = inPkt.getParameter(5);
|
|
}
|
|
|
|
// Get the IPC pipe file for the specified file id
|
|
|
|
DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid);
|
|
if (pipeFile == null)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
|
|
return;
|
|
}
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
|
|
logger.debug("Read pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", rdLen=" + rdLen);
|
|
|
|
// Check if there is a valid reply buffered
|
|
|
|
if (pipeFile.hasBufferedData())
|
|
{
|
|
|
|
// Get the buffered data
|
|
|
|
DCEBuffer bufData = pipeFile.getBufferedData();
|
|
int bufLen = bufData.getAvailableLength();
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
|
|
logger.debug(" Buffered data available=" + bufLen);
|
|
|
|
// Check if there is less data than the read size
|
|
|
|
if (rdLen > bufLen)
|
|
rdLen = bufLen;
|
|
|
|
// Build the read response
|
|
|
|
if (cmd == PacketType.ReadFile)
|
|
{
|
|
|
|
// Build the read response
|
|
|
|
outPkt.setParameterCount(5);
|
|
outPkt.setParameter(0, rdLen);
|
|
for (int i = 1; i < 5; i++)
|
|
outPkt.setParameter(i, 0);
|
|
outPkt.setByteCount(rdLen + 3);
|
|
|
|
// Copy the data to the response
|
|
|
|
byte[] buf = outPkt.getBuffer();
|
|
int pos = outPkt.getByteOffset();
|
|
|
|
buf[pos++] = (byte) DataType.DataBlock;
|
|
DataPacker.putIntelShort(rdLen, buf, pos);
|
|
pos += 2;
|
|
|
|
try
|
|
{
|
|
bufData.copyData(buf, pos, rdLen);
|
|
}
|
|
catch (DCEBufferException ex)
|
|
{
|
|
logger.error("DCR/RPC read", ex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Build the read andX response
|
|
|
|
outPkt.setParameterCount(12);
|
|
outPkt.setAndXCommand(0xFF);
|
|
for (int i = 1; i < 12; i++)
|
|
outPkt.setParameter(i, 0);
|
|
|
|
// Copy the data to the response
|
|
|
|
byte[] buf = outPkt.getBuffer();
|
|
int pos = DCEDataPacker.longwordAlign(outPkt.getByteOffset());
|
|
|
|
outPkt.setParameter(5, rdLen);
|
|
outPkt.setParameter(6, pos - RFCNetBIOSProtocol.HEADER_LEN);
|
|
outPkt.setByteCount((pos + rdLen) - outPkt.getByteOffset());
|
|
|
|
try
|
|
{
|
|
bufData.copyData(buf, pos, rdLen);
|
|
}
|
|
catch (DCEBufferException ex)
|
|
{
|
|
logger.error("DCE/RPC error", ex);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
|
|
logger.debug(" No buffered data available");
|
|
|
|
// Return a zero length read response
|
|
|
|
if (cmd == PacketType.ReadFile)
|
|
{
|
|
|
|
// Initialize the read response
|
|
|
|
outPkt.setParameterCount(5);
|
|
for (int i = 0; i < 5; i++)
|
|
outPkt.setParameter(i, 0);
|
|
outPkt.setByteCount(0);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Return a zero length read andX response
|
|
|
|
outPkt.setParameterCount(12);
|
|
|
|
outPkt.setAndXCommand(0xFF);
|
|
for (int i = 1; i < 12; i++)
|
|
outPkt.setParameter(i, 0);
|
|
outPkt.setByteCount(0);
|
|
}
|
|
}
|
|
|
|
// Clear the status code
|
|
|
|
outPkt.setLongErrorCode(SMBStatus.NTSuccess);
|
|
|
|
// Send the read reply
|
|
|
|
outPkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE);
|
|
sess.sendResponseSMB(outPkt);
|
|
}
|
|
|
|
/**
|
|
* Process the DCE/RPC request buffer
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param buf DCEBuffer
|
|
* @param pipeFile DCEPipeFile
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void processDCEBuffer(SMBSrvSession sess, DCEBuffer dceBuf, DCEPipeFile pipeFile)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Process the DCE/RPC request
|
|
|
|
switch (dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE))
|
|
{
|
|
|
|
// DCE Bind
|
|
|
|
case DCECommand.BIND:
|
|
procDCEBind(sess, dceBuf, pipeFile);
|
|
break;
|
|
|
|
// DCE Request
|
|
|
|
case DCECommand.REQUEST:
|
|
procDCERequest(sess, dceBuf, pipeFile);
|
|
break;
|
|
|
|
default:
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVNoAccessRights, SMBStatus.ErrSrv);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process a DCE bind request
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param dceBuf DCEBuffer
|
|
* @param pipeFile DCEPipeFile
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void procDCEBind(SMBSrvSession sess, DCEBuffer dceBuf, DCEPipeFile pipeFile)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
// DEBUG
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("DCE Bind");
|
|
|
|
// Get the call id and skip the DCE header
|
|
|
|
int callId = dceBuf.getHeaderValue(DCEBuffer.HDR_CALLID);
|
|
dceBuf.skipBytes(DCEBuffer.DCEDATA);
|
|
|
|
// Unpack the bind request
|
|
|
|
int maxTxSize = dceBuf.getShort();
|
|
int maxRxSize = dceBuf.getShort();
|
|
int groupId = dceBuf.getInt();
|
|
int ctxElems = dceBuf.getByte(DCEBuffer.ALIGN_INT);
|
|
int presCtxId = dceBuf.getByte(DCEBuffer.ALIGN_SHORT);
|
|
int trfSyntax = dceBuf.getByte(DCEBuffer.ALIGN_SHORT);
|
|
|
|
UUID uuid1 = dceBuf.getUUID(true);
|
|
UUID uuid2 = dceBuf.getUUID(true);
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
{
|
|
logger.debug("Bind: maxTx=" + maxTxSize + ", maxRx=" + maxRxSize + ", groupId=" + groupId
|
|
+ ", ctxElems=" + ctxElems + ", presCtxId=" + presCtxId + ", trfSyntax=" + trfSyntax);
|
|
logger.debug(" uuid1=" + uuid1.toString());
|
|
logger.debug(" uuid2=" + uuid2.toString());
|
|
}
|
|
|
|
// Update the IPC pipe file
|
|
|
|
pipeFile.setMaxTransmitFragmentSize(maxTxSize);
|
|
pipeFile.setMaxReceiveFragmentSize(maxRxSize);
|
|
|
|
// Create an output DCE buffer for the reply and add the bind acknowledge header
|
|
|
|
DCEBuffer txBuf = new DCEBuffer();
|
|
txBuf.putBindAckHeader(dceBuf.getHeaderValue(DCEBuffer.HDR_CALLID));
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, DCEBuffer.FLG_ONLYFRAG);
|
|
|
|
// Pack the bind acknowledge DCE reply
|
|
|
|
txBuf.putShort(maxTxSize);
|
|
txBuf.putShort(maxRxSize);
|
|
txBuf.putInt(0x53F0);
|
|
|
|
String srvPipeName = DCEPipeType.getServerPipeName(pipeFile.getPipeId());
|
|
txBuf.putShort(srvPipeName.length() + 1);
|
|
txBuf.putASCIIString(srvPipeName, true, DCEBuffer.ALIGN_INT);
|
|
txBuf.putInt(1);
|
|
txBuf.putShort(0);
|
|
txBuf.putShort(0);
|
|
txBuf.putUUID(uuid2, true);
|
|
|
|
txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, txBuf.getLength());
|
|
|
|
// Attach the reply buffer to the pipe file
|
|
|
|
pipeFile.setBufferedData(txBuf);
|
|
}
|
|
catch (DCEBufferException ex)
|
|
{
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process a DCE request
|
|
*
|
|
* @param sess SMBSrvSession
|
|
* @param dceBuf DCEBuffer
|
|
* @param pipeFile DCEPipeFile
|
|
* @exception IOException
|
|
* @exception SMBSrvException
|
|
*/
|
|
public static final void procDCERequest(SMBSrvSession sess, DCEBuffer inBuf, DCEPipeFile pipeFile)
|
|
throws IOException, SMBSrvException
|
|
{
|
|
|
|
// Debug
|
|
|
|
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC))
|
|
logger.debug("DCE Request opNum=0x" + Integer.toHexString(inBuf.getHeaderValue(DCEBuffer.HDR_OPCODE)));
|
|
|
|
// Pass the request to the DCE pipe request handler
|
|
|
|
if (pipeFile.hasRequestHandler())
|
|
pipeFile.getRequestHandler().processRequest(sess, inBuf, pipeFile);
|
|
else
|
|
sess.sendErrorResponseSMB(SMBStatus.SRVNoAccessRights, SMBStatus.ErrSrv);
|
|
}
|
|
}
|