2005-12-08 07:13:07 +00:00

636 lines
21 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 java.util.Enumeration;
import org.alfresco.filesys.server.core.ShareType;
import org.alfresco.filesys.server.core.SharedDevice;
import org.alfresco.filesys.server.core.SharedDeviceList;
import org.alfresco.filesys.smb.PacketType;
import org.alfresco.filesys.smb.SMBStatus;
import org.alfresco.filesys.smb.TransactBuffer;
import org.alfresco.filesys.util.DataBuffer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* IPC$ Transaction handler for \PIPE\LANMAN requests.
*/
class PipeLanmanHandler
{
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
// Server capability flags
public static final int WorkStation = 0x00000001;
public static final int Server = 0x00000002;
public static final int SQLServer = 0x00000004;
public static final int DomainCtrl = 0x00000008;
public static final int DomainBakCtrl = 0x00000010;
public static final int TimeSource = 0x00000020;
public static final int AFPServer = 0x00000040;
public static final int NovellServer = 0x00000080;
public static final int DomainMember = 0x00000100;
public static final int PrintServer = 0x00000200;
public static final int DialinServer = 0x00000400;
public static final int UnixServer = 0x00000800;
public static final int NTServer = 0x00001000;
public static final int WfwServer = 0x00002000;
public static final int MFPNServer = 0x00004000;
public static final int NTNonDCServer = 0x00008000;
public static final int PotentialBrowse = 0x00010000;
public static final int BackupBrowser = 0x00020000;
public static final int MasterBrowser = 0x00040000;
public static final int DomainMaster = 0x00080000;
public static final int OSFServer = 0x00100000;
public static final int VMSServer = 0x00200000;
public static final int Win95Plus = 0x00400000;
public static final int DFSRoot = 0x00800000;
public static final int NTCluster = 0x01000000;
public static final int TerminalServer = 0x02000000;
public static final int DCEServer = 0x10000000;
public static final int AlternateXport = 0x20000000;
public static final int LocalListOnly = 0x40000000;
public static final int DomainEnum = 0x80000000;
/**
* Process a \PIPE\LANMAN transaction request.
*
* @param tbuf Transaction setup, parameter and data buffers
* @param sess SMB server session that received the transaction.
* @param trans Packet to use for reply
* @return true if the transaction has been handled, else false.
* @exception java.io.IOException If an I/O error occurs
* @exception SMBSrvException If an SMB protocol error occurs
*/
public final static boolean processRequest(TransactBuffer tbuf, SMBSrvSession sess, SMBSrvPacket trans)
throws IOException, SMBSrvException
{
// Create a transaction packet
SMBSrvTransPacket tpkt = new SMBSrvTransPacket(trans.getBuffer());
// Get the transaction command code, parameter descriptor and data descriptor strings from
// the parameter block.
DataBuffer paramBuf = tbuf.getParameterBuffer();
int cmd = paramBuf.getShort();
String prmDesc = paramBuf.getString(false);
String dataDesc = paramBuf.getString(false);
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("\\PIPE\\LANMAN\\ transact request, cmd=" + cmd + ", prm=" + prmDesc + ", data=" + dataDesc);
// Call the required transaction handler
boolean processed = false;
switch (cmd)
{
// Share
case PacketType.RAPShareEnum:
processed = procNetShareEnum(sess, tbuf, prmDesc, dataDesc, tpkt);
break;
// Get share information
case PacketType.RAPShareGetInfo:
processed = procNetShareGetInfo(sess, tbuf, prmDesc, dataDesc, tpkt);
break;
// Workstation information
case PacketType.RAPWkstaGetInfo:
processed = procNetWkstaGetInfo(sess, tbuf, prmDesc, dataDesc, tpkt);
break;
// Server information
case PacketType.RAPServerGetInfo:
processed = procNetServerGetInfo(sess, tbuf, prmDesc, dataDesc, tpkt);
break;
// Print queue information
case PacketType.NetPrintQGetInfo:
processed = procNetPrintQGetInfo(sess, tbuf, prmDesc, dataDesc, tpkt);
break;
// No handler
default:
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("No handler for \\PIPE\\LANMAN\\ request, cmd=" + cmd + ", prm=" + prmDesc + ", data="
+ dataDesc);
break;
}
// Return the transaction processed status
return processed;
}
/**
* Process a NetServerGetInfo transaction request.
*
* @param sess Server session that received the request.
* @param tbuf Transaction buffer
* @param prmDesc Parameter descriptor string.
* @param dataDesc Data descriptor string.
* @param tpkt Transaction reply packet
* @return true if the transaction has been processed, else false.
*/
protected final static boolean procNetServerGetInfo(SMBSrvSession sess, TransactBuffer tbuf, String prmDesc,
String dataDesc, SMBSrvTransPacket tpkt) throws IOException, SMBSrvException
{
// Validate the parameter string
if (prmDesc.compareTo("WrLh") != 0)
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// Unpack the server get information specific parameters
DataBuffer paramBuf = tbuf.getParameterBuffer();
int infoLevel = paramBuf.getShort();
int bufSize = paramBuf.getShort();
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetServerGetInfo infoLevel=" + infoLevel);
// Check if the information level requested and data descriptor string match
if (infoLevel == 1 && dataDesc.compareTo("B16BBDz") == 0)
{
// Create the transaction reply data buffer
TransactBuffer replyBuf = new TransactBuffer(tbuf.isType(), 0, 6, 1024);
// Pack the parameter block
paramBuf = replyBuf.getParameterBuffer();
paramBuf.putShort(0); // status code
paramBuf.putShort(0); // converter for strings
paramBuf.putShort(1); // number of entries
// Pack the data block, calculate the size of the fixed data block
DataBuffer dataBuf = replyBuf.getDataBuffer();
int strPos = SMBSrvTransPacket.CalculateDataItemSize("B16BBDz");
// Pack the server name pointer and string
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putFixedStringAt(sess.getServerName(), 16, strPos);
// Pack the major/minor version
dataBuf.putByte(1);
dataBuf.putByte(0);
// Pack the server capability flags
dataBuf.putInt(sess.getSMBServer().getServerType());
// Pack the server comment string
String srvComment = sess.getSMBServer().getComment();
if (srvComment == null)
srvComment = "";
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putStringAt(srvComment, strPos, false, true);
// Set the data block length
dataBuf.setLength(strPos);
// Send the transaction response
tpkt.doTransactionResponse(sess, replyBuf);
}
else
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// We processed the request
return true;
}
/**
* Process a NetShareEnum transaction request.
*
* @param sess Server session that received the request.
* @param tbuf Transaction buffer
* @param prmDesc Parameter descriptor string.
* @param dataDesc Data descriptor string.
* @param tpkt Transaction reply packet
* @return true if the transaction has been processed, else false.
*/
protected final static boolean procNetShareEnum(SMBSrvSession sess, TransactBuffer tbuf, String prmDesc,
String dataDesc, SMBSrvTransPacket tpkt) throws IOException, SMBSrvException
{
// Validate the parameter string
if (prmDesc.compareTo("WrLeh") != 0)
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// Unpack the server get information specific parameters
DataBuffer paramBuf = tbuf.getParameterBuffer();
int infoLevel = paramBuf.getShort();
int bufSize = paramBuf.getShort();
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetShareEnum infoLevel=" + infoLevel);
// Check if the information level requested and data descriptor string match
if (infoLevel == 1 && dataDesc.compareTo("B13BWz") == 0)
{
// Get the share list from the server
SharedDeviceList shrList = sess.getSMBServer().getShareList(null, sess);
int shrCount = 0;
int strPos = 0;
if (shrList != null)
{
// Calculate the fixed data length
shrCount = shrList.numberOfShares();
strPos = SMBSrvTransPacket.CalculateDataItemSize("B13BWz") * shrCount;
}
// Create the transaction reply data buffer
TransactBuffer replyBuf = new TransactBuffer(tbuf.isType(), 0, 6, bufSize);
// Pack the parameter block
paramBuf = replyBuf.getParameterBuffer();
paramBuf.putShort(0); // status code
paramBuf.putShort(0); // converter for strings
paramBuf.putShort(shrCount); // number of entries
paramBuf.putShort(shrCount); // total number of entries
// Pack the data block
DataBuffer dataBuf = replyBuf.getDataBuffer();
Enumeration<SharedDevice> enm = shrList.enumerateShares();
while (enm.hasMoreElements())
{
// Get the current share
SharedDevice shrDev = enm.nextElement();
// Pack the share name, share type and comment pointer
dataBuf.putFixedString(shrDev.getName(), 13);
dataBuf.putByte(0);
dataBuf.putShort(ShareType.asShareInfoType(shrDev.getType()));
dataBuf.putStringPointer(strPos);
if (shrDev.getComment() != null)
strPos = dataBuf.putStringAt(shrDev.getComment(), strPos, false, true);
else
strPos = dataBuf.putStringAt("", strPos, false, true);
}
// Set the data block length
dataBuf.setLength(strPos);
// Send the transaction response
tpkt.doTransactionResponse(sess, replyBuf);
}
else
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// We processed the request
return true;
}
/**
* Process a NetShareGetInfo transaction request.
*
* @param sess Server session that received the request.
* @param tbuf Transaction buffer
* @param prmDesc Parameter descriptor string.
* @param dataDesc Data descriptor string.
* @param tpkt Transaction reply packet
* @return true if the transaction has been processed, else false.
*/
protected final static boolean procNetShareGetInfo(SMBSrvSession sess, TransactBuffer tbuf, String prmDesc,
String dataDesc, SMBSrvTransPacket tpkt) throws IOException, SMBSrvException
{
// Validate the parameter string
if (prmDesc.compareTo("zWrLh") != 0)
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// Unpack the share get information specific parameters
DataBuffer paramBuf = tbuf.getParameterBuffer();
String shareName = paramBuf.getString(32, false);
int infoLevel = paramBuf.getShort();
int bufSize = paramBuf.getShort();
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetShareGetInfo - " + shareName + ", infoLevel=" + infoLevel);
// Check if the information level requested and data descriptor string match
if (infoLevel == 1 && dataDesc.compareTo("B13BWz") == 0)
{
// Find the required share information
SharedDevice share = null;
try
{
// Get the shared device details
share = sess.getSMBServer().findShare(null, shareName, ShareType.UNKNOWN, sess, false);
}
catch (Exception ex)
{
}
if (share == null)
{
sess.sendErrorResponseSMB(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
return true;
}
// Create the transaction reply data buffer
TransactBuffer replyBuf = new TransactBuffer(tbuf.isType(), 0, 6, 1024);
// Pack the parameter block
paramBuf = replyBuf.getParameterBuffer();
paramBuf.putShort(0); // status code
paramBuf.putShort(0); // converter for strings
paramBuf.putShort(1); // number of entries
// Pack the data block, calculate the size of the fixed data block
DataBuffer dataBuf = replyBuf.getDataBuffer();
int strPos = SMBSrvTransPacket.CalculateDataItemSize("B13BWz");
// Pack the share name
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putFixedStringAt(share.getName(), 13, strPos);
// Pack unknown byte, alignment ?
dataBuf.putByte(0);
// Pack the share type flags
dataBuf.putShort(share.getType());
// Pack the share comment
dataBuf.putStringPointer(strPos);
if (share.getComment() != null)
strPos = dataBuf.putStringAt(share.getComment(), strPos, false, true);
else
strPos = dataBuf.putStringAt("", strPos, false, true);
// Set the data block length
dataBuf.setLength(strPos);
// Send the transaction response
tpkt.doTransactionResponse(sess, replyBuf);
}
else
{
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetShareGetInfo - UNSUPPORTED " + shareName + ", infoLevel=" + infoLevel + ", dataDesc="
+ dataDesc);
// Server error
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
}
// We processed the request
return true;
}
/**
* Process a NetWkstaGetInfo transaction request.
*
* @param sess Server session that received the request.
* @param tbuf Transaction buffer
* @param prmDesc Parameter descriptor string.
* @param dataDesc Data descriptor string.
* @param tpkt Transaction reply packet
* @return true if the transaction has been processed, else false.
*/
protected final static boolean procNetWkstaGetInfo(SMBSrvSession sess, TransactBuffer tbuf, String prmDesc,
String dataDesc, SMBSrvTransPacket tpkt) throws IOException, SMBSrvException
{
// Validate the parameter string
if (prmDesc.compareTo("WrLh") != 0)
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// Unpack the share get information specific parameters
DataBuffer paramBuf = tbuf.getParameterBuffer();
int infoLevel = paramBuf.getShort();
int bufSize = paramBuf.getShort();
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetWkstaGetInfo infoLevel=" + infoLevel);
// Check if the information level requested and data descriptor string match
if ((infoLevel == 1 && dataDesc.compareTo("zzzBBzzz") == 0)
|| (infoLevel == 10 && dataDesc.compareTo("zzzBBzz") == 0))
{
// Create the transaction reply data buffer
TransactBuffer replyBuf = new TransactBuffer(tbuf.isType(), 0, 6, 1024);
// Pack the data block, calculate the size of the fixed data block
DataBuffer dataBuf = replyBuf.getDataBuffer();
int strPos = SMBSrvTransPacket.CalculateDataItemSize(dataDesc);
// Pack the server name
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putStringAt(sess.getServerName(), strPos, false, true);
// Pack the user name
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putStringAt("", strPos, false, true);
// Pack the domain name
dataBuf.putStringPointer(strPos);
String domain = sess.getServer().getConfiguration().getDomainName();
if (domain == null)
domain = "";
strPos = dataBuf.putStringAt(domain, strPos, false, true);
// Pack the major/minor version number
dataBuf.putByte(4);
dataBuf.putByte(2);
// Pack the logon domain
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putStringAt("", strPos, false, true);
// Check if the other domains should be packed
if (infoLevel == 1 && dataDesc.compareTo("zzzBBzzz") == 0)
{
// Pack the other domains
dataBuf.putStringPointer(strPos);
strPos = dataBuf.putStringAt("", strPos, false, true);
}
// Set the data block length
dataBuf.setLength(strPos);
// Pack the parameter block
paramBuf = replyBuf.getParameterBuffer();
paramBuf.putShort(0); // status code
paramBuf.putShort(0); // converter for strings
paramBuf.putShort(dataBuf.getLength());
paramBuf.putShort(0); // number of entries
// Send the transaction response
tpkt.doTransactionResponse(sess, replyBuf);
}
else
{
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetWkstaGetInfo UNSUPPORTED infoLevel=" + infoLevel + ", dataDesc=" + dataDesc);
// Unsupported request
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
}
// We processed the request
return true;
}
/**
* Process a NetPrintQGetInfo transaction request.
*
* @param sess Server session that received the request.
* @param tbuf Transaction buffer
* @param prmDesc Parameter descriptor string.
* @param dataDesc Data descriptor string.
* @param tpkt Transaction reply packet
* @return true if the transaction has been processed, else false.
*/
protected final static boolean procNetPrintQGetInfo(SMBSrvSession sess, TransactBuffer tbuf, String prmDesc,
String dataDesc, SMBSrvTransPacket tpkt) throws IOException, SMBSrvException
{
// Validate the parameter string
if (prmDesc.compareTo("zWrLh") != 0)
throw new SMBSrvException(SMBStatus.SRVInternalServerError, SMBStatus.ErrSrv);
// Unpack the share get information specific parameters
DataBuffer paramBuf = tbuf.getParameterBuffer();
String shareName = paramBuf.getString(32, false);
int infoLevel = paramBuf.getShort();
int bufSize = paramBuf.getShort();
// Debug
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
logger.debug("NetPrintQGetInfo - " + shareName + ", infoLevel=" + infoLevel);
// We did not process the request
return false;
}
}