Added DeviceIOControl to the INTFileStore interface, relevant functionality moved to the object store layer

This commit is contained in:
Tal Aloni 2017-02-11 15:31:08 +02:00
parent 0d5898bb60
commit 3e158fb855
9 changed files with 90 additions and 59 deletions

View file

@ -370,6 +370,12 @@ namespace SMBLibrary
return NTStatus.STATUS_SUCCESS;
}
public NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength)
{
output = null;
return NTStatus.STATUS_NOT_SUPPORTED;
}
public void Log(Severity severity, string message)
{
// To be thread-safe we must capture the delegate reference first

View file

@ -0,0 +1,22 @@
namespace SMBLibrary
{
public enum IoControlCode : uint
{
FSCTL_DFS_GET_REFERRALS = 0x00060194, // SMB2-specific processing
FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0, // SMB2-specific processing
FSCTL_SET_REPARSE_POINT = 0x000900A4, // SMB2-specific processing
FSCTL_FILE_LEVEL_TRIM = 0x00098208, // SMB2-specific processing
FSCTL_PIPE_WAIT = 0x00110018, // SMB2-specific processing
FSCTL_PIPE_PEEK = 0x0011400C, // SMB2-specific processing
FSCTL_PIPE_TRANSCEIVE = 0x0011C017, // SMB2-specific processing
FSCTL_SRV_REQUEST_RESUME_KEY = 0x00140078, // SMB2-specific processing
FSCTL_VALIDATE_NEGOTIATE_INFO = 0x00140204, // SMB2-specific processing
FSCTL_LMR_REQUEST_RESILIENCY = 0x001401D4, // SMB2-specific processing
FSCTL_QUERY_NETWORK_INTERFACE_INFO = 0x001401FC, // SMB2-specific processing
FSCTL_SRV_ENUMERATE_SNAPSHOTS = 0x00144064, // SMB2-specific processing
FSCTL_SRV_COPYCHUNK = 0x001440F2, // SMB2-specific processing
FSCTL_SRV_READ_HASH = 0x001441BB, // SMB2-specific processing
FSCTL_SRV_COPYCHUNK_WRITE = 0x001480F2, // SMB2-specific processing
}
}

View file

@ -33,5 +33,7 @@ namespace SMBLibrary
NTStatus SetFileInformation(object handle, FileInformation information);
NTStatus GetFileSystemInformation(out FileSystemInformation result, FileSystemInformationClass informationClass);
NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength);
}
}

View file

@ -99,6 +99,28 @@ namespace SMBLibrary
return NTStatus.STATUS_SUCCESS;
}
public NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength)
{
output = null;
if (ctlCode == (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE)
{
int numberOfBytesWritten;
NTStatus writeStatus = WriteFile(out numberOfBytesWritten, handle, 0, input);
if (writeStatus != NTStatus.STATUS_SUCCESS)
{
return writeStatus;
}
NTStatus readStatus = ReadFile(out output, handle, 0, maxOutputLength);
if (readStatus != NTStatus.STATUS_SUCCESS)
{
return readStatus;
}
return NTStatus.STATUS_SUCCESS;
}
return NTStatus.STATUS_NOT_SUPPORTED;
}
public NTStatus QueryDirectory(out List<QueryDirectoryFileInformation> result, object directoryHandle, string fileName, FileInformationClass informationClass)
{
result = null;

View file

@ -93,6 +93,7 @@
<Compile Include="NTFileStore\Enums\FileSystemInformation\FileSystemControlFlags.cs" />
<Compile Include="NTFileStore\Enums\FileSystemInformation\FileSystemInformationClass.cs" />
<Compile Include="NTFileStore\Enums\FileSystemInformation\SectorSizeInformationFlags.cs" />
<Compile Include="NTFileStore\Enums\IoControlCode.cs" />
<Compile Include="NTFileStore\Enums\NtCreateFile\CreateDisposition.cs" />
<Compile Include="NTFileStore\Enums\NtCreateFile\CreateOptions.cs" />
<Compile Include="NTFileStore\Enums\NtCreateFile\FileStatus.cs" />

View file

@ -80,7 +80,7 @@ namespace SMBLibrary.Server.SMB1
}
else if (subcommand is NTTransactIOCTLRequest)
{
subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand);
subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand, share, state);
}
else if (subcommand is NTTransactSetSecurityDescriptor)
{
@ -112,25 +112,28 @@ namespace SMBLibrary.Server.SMB1
return response;
}
private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand)
private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state)
{
const uint FSCTL_CREATE_OR_GET_OBJECT_ID = 0x900C0;
SMB1Session session = state.GetSession(header.UID);
NTTransactIOCTLResponse response = new NTTransactIOCTLResponse();
if (subcommand.IsFsctl)
{
if (subcommand.FunctionCode == FSCTL_CREATE_OR_GET_OBJECT_ID)
OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID);
if (openFile == null)
{
ObjectIDBufferType1 objectID = new ObjectIDBufferType1();
objectID.ObjectId = Guid.NewGuid();
response.Data = objectID.GetBytes();
return response;
}
else
{
header.Status = NTStatus.STATUS_NOT_IMPLEMENTED;
header.Status = NTStatus.STATUS_INVALID_HANDLE;
return null;
}
int maxOutputLength = UInt16.MaxValue;
byte[] output;
header.Status = share.FileStore.DeviceIOControl(openFile.Handle, subcommand.FunctionCode, subcommand.Data, out output, maxOutputLength);
if (header.Status != NTStatus.STATUS_SUCCESS)
{
return null;
}
response.Data = output;
return response;
}
else
{

View file

@ -134,14 +134,7 @@ namespace SMBLibrary.Server.SMB1
}
else if (subcommand is TransactionTransactNamedPipeRequest)
{
if (!(share is NamedPipeShare))
{
// [MS-CIFS] If the pipe is not a message mode pipe, the Trans subsystem MUST fail the request with STATUS_INVALID_PARAMETER
header.Status = NTStatus.STATUS_INVALID_PARAMETER;
return new ErrorResponse(CommandName.SMB_COM_TRANSACTION);
}
subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, (TransactionTransactNamedPipeRequest)subcommand, (NamedPipeShare)share, state);
subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, (TransactionTransactNamedPipeRequest)subcommand, share, state);
}
else if (subcommand is TransactionRawWriteNamedPipeRequest)
{

View file

@ -16,7 +16,7 @@ namespace SMBLibrary.Server.SMB1
{
public class TransactionSubcommandHelper
{
internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, TransactionTransactNamedPipeRequest subcommand, NamedPipeShare share, SMB1ConnectionState state)
internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, TransactionTransactNamedPipeRequest subcommand, ISMBShare share, SMB1ConnectionState state)
{
SMB1Session session = state.GetSession(header.UID);
OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID);
@ -26,19 +26,15 @@ namespace SMBLibrary.Server.SMB1
return null;
}
int maxOutputLength = UInt16.MaxValue;
byte[] output;
header.Status = share.FileStore.DeviceIOControl(openFile.Handle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, subcommand.WriteData, out output, maxOutputLength);
if (header.Status != NTStatus.STATUS_SUCCESS)
{
return null;
}
TransactionTransactNamedPipeResponse response = new TransactionTransactNamedPipeResponse();
int numberOfBytesWritten;
header.Status = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, 0, subcommand.WriteData);
if (header.Status != NTStatus.STATUS_SUCCESS)
{
return null;
}
int maxCount = UInt16.MaxValue;
header.Status = share.FileStore.ReadFile(out response.ReadData, openFile.Handle, 0, maxCount);
if (header.Status != NTStatus.STATUS_SUCCESS)
{
return null;
}
response.ReadData = output;
return response;
}
}

View file

@ -14,14 +14,11 @@ namespace SMBLibrary.Server.SMB2
{
public class IOCtlHelper
{
private const uint FSCTL_DFS_GET_REFERRALS = 0x00060194;
private const uint FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0;
private const uint FSCTL_PIPE_TRANSCEIVE = 0x0011C017;
internal static SMB2Command GetIOCtlResponse(IOCtlRequest request, ISMBShare share, SMB2ConnectionState state)
{
SMB2Session session = state.GetSession(request.Header.SessionID);
if (request.CtlCode == FSCTL_DFS_GET_REFERRALS || request.CtlCode == FSCTL_DFS_GET_REFERRALS_EX)
if (request.CtlCode == (uint)IoControlCode.FSCTL_DFS_GET_REFERRALS ||
request.CtlCode == (uint)IoControlCode.FSCTL_DFS_GET_REFERRALS_EX)
{
// [MS-SMB2] 3.3.5.15.2 Handling a DFS Referral Information Request
return new ErrorResponse(request.CommandName, NTStatus.STATUS_FS_DRIVER_REQUIRED);
@ -33,29 +30,18 @@ namespace SMBLibrary.Server.SMB2
return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED);
}
if (share is NamedPipeShare)
int maxOutputLength = (int)request.MaxOutputResponse;
byte[] output;
NTStatus status = share.FileStore.DeviceIOControl(openFile.Handle, request.CtlCode, request.Input, out output, maxOutputLength);
if (status != NTStatus.STATUS_SUCCESS)
{
if (request.CtlCode == FSCTL_PIPE_TRANSCEIVE)
{
IOCtlResponse response = new IOCtlResponse();
response.CtlCode = request.CtlCode;
int numberOfBytesWritten;
NTStatus writeStatus = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, 0, request.Input);
if (writeStatus != NTStatus.STATUS_SUCCESS)
{
return new ErrorResponse(request.CommandName, writeStatus);
}
int maxCount = (int)request.MaxOutputResponse;
NTStatus readStatus = share.FileStore.ReadFile(out response.Output, openFile.Handle, 0, maxCount);
if (readStatus != NTStatus.STATUS_SUCCESS)
{
return new ErrorResponse(request.CommandName, readStatus);
}
return response;
}
return new ErrorResponse(request.CommandName, status);
}
return new ErrorResponse(request.CommandName, NTStatus.STATUS_NOT_SUPPORTED);
IOCtlResponse response = new IOCtlResponse();
response.CtlCode = request.CtlCode;
response.Output = output;
return response;
}
}
}