Improved Transaction2Subcommands implementation

This commit is contained in:
Tal Aloni 2017-01-07 23:56:26 +02:00
parent 2f4a6e1538
commit 8864c4f335
10 changed files with 106 additions and 86 deletions

View file

@ -24,7 +24,7 @@ namespace SMBLibrary.SMB1
} }
public Transaction2CreateDirectoryResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base() public Transaction2CreateDirectoryResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0); EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
} }

View file

@ -24,7 +24,7 @@ namespace SMBLibrary.SMB1
public SearchStorageType SearchStorageType; public SearchStorageType SearchStorageType;
public string FileName; // SMB_STRING public string FileName; // SMB_STRING
// Data: // Data:
FullExtendedAttributeList GetExtendedAttributeList; // Used with FindInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST public FullExtendedAttributeList GetExtendedAttributeList; // Used with FindInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST
public Transaction2FindFirst2Request() : base() public Transaction2FindFirst2Request() : base()
{ {

View file

@ -19,19 +19,18 @@ namespace SMBLibrary.SMB1
public const int ParametersLength = 10; public const int ParametersLength = 10;
// Parameters: // Parameters:
public ushort SID; // Search handle public ushort SID; // Search handle
public ushort SearchCount; private ushort SearchCount;
public bool EndOfSearch; public bool EndOfSearch;
public ushort EaErrorOffset; public ushort EaErrorOffset;
public ushort LastNameOffset; public ushort LastNameOffset;
// Data: // Data:
public FindInformationList FindInfoList; private byte[] FindInformationListBytes = new byte[0];
public Transaction2FindFirst2Response() : base() public Transaction2FindFirst2Response() : base()
{ {
FindInfoList = new FindInformationList();
} }
public Transaction2FindFirst2Response(byte[] parameters, byte[] data, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys) : base() public Transaction2FindFirst2Response(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
SID = LittleEndianConverter.ToUInt16(parameters, 0); SID = LittleEndianConverter.ToUInt16(parameters, 0);
SearchCount = LittleEndianConverter.ToUInt16(parameters, 2); SearchCount = LittleEndianConverter.ToUInt16(parameters, 2);
@ -39,13 +38,11 @@ namespace SMBLibrary.SMB1
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 6); EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 6);
LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 8); LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 8);
FindInfoList = new FindInformationList(data, informationLevel, isUnicode, returnResumeKeys); FindInformationListBytes = data;
} }
public override byte[] GetParameters(bool isUnicode) public override byte[] GetParameters(bool isUnicode)
{ {
SearchCount = (ushort)FindInfoList.Count;
byte[] parameters = new byte[ParametersLength]; byte[] parameters = new byte[ParametersLength];
LittleEndianWriter.WriteUInt16(parameters, 0, SID); LittleEndianWriter.WriteUInt16(parameters, 0, SID);
LittleEndianWriter.WriteUInt16(parameters, 2, SearchCount); LittleEndianWriter.WriteUInt16(parameters, 2, SearchCount);
@ -57,7 +54,18 @@ namespace SMBLibrary.SMB1
public override byte[] GetData(bool isUnicode) public override byte[] GetData(bool isUnicode)
{ {
return FindInfoList.GetBytes(isUnicode); return FindInformationListBytes;
}
public FindInformationList GetFindInformationList(FindInformationLevel findInformationLevel, bool isUnicode, bool returnResumeKeys)
{
return new FindInformationList(FindInformationListBytes, findInformationLevel, isUnicode, returnResumeKeys);
}
public void SetFindInformationList(FindInformationList findInformationList, bool isUnicode)
{
SearchCount = (ushort)findInformationList.Count;
FindInformationListBytes = findInformationList.GetBytes(isUnicode);
} }
public override Transaction2SubcommandName SubcommandName public override Transaction2SubcommandName SubcommandName

View file

@ -18,26 +18,25 @@ namespace SMBLibrary.SMB1
{ {
public const int ParametersLength = 8; public const int ParametersLength = 8;
// Parameters: // Parameters:
public ushort SearchCount; private ushort SearchCount;
public bool EndOfSearch; public bool EndOfSearch;
public ushort EaErrorOffset; public ushort EaErrorOffset;
public ushort LastNameOffset; public ushort LastNameOffset;
// Data: // Data:
public FindInformationList FindInfoList; private byte[] FindInformationListBytes = new byte[0];
public Transaction2FindNext2Response() : base() public Transaction2FindNext2Response() : base()
{ {
FindInfoList = new FindInformationList();
} }
public Transaction2FindNext2Response(byte[] parameters, byte[] data, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys) : base() public Transaction2FindNext2Response(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
SearchCount = LittleEndianConverter.ToUInt16(parameters, 0); SearchCount = LittleEndianConverter.ToUInt16(parameters, 0);
EndOfSearch = LittleEndianConverter.ToUInt16(parameters, 2) != 0; EndOfSearch = LittleEndianConverter.ToUInt16(parameters, 2) != 0;
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 4); EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 4);
LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 6); LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 6);
FindInfoList = new FindInformationList(data, informationLevel, isUnicode, returnResumeKeys); FindInformationListBytes = data;
} }
public override byte[] GetParameters(bool isUnicode) public override byte[] GetParameters(bool isUnicode)
@ -52,7 +51,18 @@ namespace SMBLibrary.SMB1
public override byte[] GetData(bool isUnicode) public override byte[] GetData(bool isUnicode)
{ {
return FindInfoList.GetBytes(isUnicode); return FindInformationListBytes;
}
public FindInformationList GetFindInformationList(FindInformationLevel findInformationLevel, bool isUnicode, bool returnResumeKeys)
{
return new FindInformationList(FindInformationListBytes, findInformationLevel, isUnicode, returnResumeKeys);
}
public void SetFindInformationList(FindInformationList findInformationList, bool isUnicode)
{
SearchCount = (ushort)findInformationList.Count;
FindInformationListBytes = findInformationList.GetBytes(isUnicode);
} }
public override Transaction2SubcommandName SubcommandName public override Transaction2SubcommandName SubcommandName

View file

@ -17,21 +17,31 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryFSInformationResponse : Transaction2Subcommand public class Transaction2QueryFSInformationResponse : Transaction2Subcommand
{ {
// Data: // Data:
public QueryFSInformation QueryFSInfo; private byte[] QueryFSInformationBytes;
public Transaction2QueryFSInformationResponse() : base() public Transaction2QueryFSInformationResponse() : base()
{ {
} }
public Transaction2QueryFSInformationResponse(byte[] parameters, byte[] data, QueryFSInformationLevel informationLevel, bool isUnicode) : base() public Transaction2QueryFSInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
QueryFSInfo = QueryFSInformation.GetQueryFSInformation(data, informationLevel, isUnicode); QueryFSInformationBytes = data;
} }
public override byte[] GetData(bool isUnicode) public override byte[] GetData(bool isUnicode)
{ {
return QueryFSInfo.GetBytes(isUnicode); return QueryFSInformationBytes;
}
public QueryFSInformation GetQueryFSInformation(QueryFSInformationLevel informationLevel, bool isUnicode)
{
return QueryFSInformation.GetQueryFSInformation(QueryFSInformationBytes, informationLevel, isUnicode);
}
public void SetQueryFSInformation(QueryFSInformation queryFSInformation, bool isUnicode)
{
QueryFSInformationBytes = queryFSInformation.GetBytes(isUnicode);
} }
public override Transaction2SubcommandName SubcommandName public override Transaction2SubcommandName SubcommandName

View file

@ -17,46 +17,39 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryFileInformationResponse : Transaction2Subcommand public class Transaction2QueryFileInformationResponse : Transaction2Subcommand
{ {
// Parameters: // Parameters:
public ushort EaErrorOffset; public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST
// Data: // Data:
public QueryInformation QueryInfo; private byte[] QueryInformationBytes = new byte[0];
public Transaction2QueryFileInformationResponse() : base() public Transaction2QueryFileInformationResponse() : base()
{ {
} }
public Transaction2QueryFileInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base() public Transaction2QueryFileInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
if ((ushort)informationLevel > 0x0100) EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
{ QueryInformationBytes = data;
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}
QueryInfo = QueryInformation.GetQueryInformation(data, informationLevel);
} }
public override byte[] GetParameters(bool isUnicode) public override byte[] GetParameters(bool isUnicode)
{ {
if ((ushort)QueryInfo.InformationLevel > 0x0100) return LittleEndianConverter.GetBytes(EaErrorOffset);
{
byte[] parameters = new byte[2];
LittleEndianWriter.WriteUInt16(parameters, 0, EaErrorOffset);
return parameters;
}
return new byte[0];
} }
public override byte[] GetData(bool isUnicode) public override byte[] GetData(bool isUnicode)
{ {
if (QueryInfo == null) return QueryInformationBytes;
{ }
// SMB_INFO_IS_NAME_VALID
return new byte[0]; public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel)
} {
else return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel);
{ }
return QueryInfo.GetBytes();
} public void SetQueryInformation(QueryInformation queryInformation)
{
QueryInformationBytes = queryInformation.GetBytes();
} }
public override Transaction2SubcommandName SubcommandName public override Transaction2SubcommandName SubcommandName

View file

@ -17,46 +17,39 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryPathInformationResponse : Transaction2Subcommand public class Transaction2QueryPathInformationResponse : Transaction2Subcommand
{ {
// Parameters: // Parameters:
public ushort EaErrorOffset; public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST
// Data: // Data:
public QueryInformation QueryInfo; private byte[] QueryInformationBytes;
public Transaction2QueryPathInformationResponse() : base() public Transaction2QueryPathInformationResponse() : base()
{ {
} }
public Transaction2QueryPathInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base() public Transaction2QueryPathInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
if ((ushort)informationLevel > 0x0100) EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
{ QueryInformationBytes = data;
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}
QueryInfo = QueryInformation.GetQueryInformation(data, informationLevel);
} }
public override byte[] GetParameters(bool isUnicode) public override byte[] GetParameters(bool isUnicode)
{ {
if ((ushort)QueryInfo.InformationLevel > 0x0100) return LittleEndianConverter.GetBytes(EaErrorOffset);
{
byte[] parameters = new byte[2];
LittleEndianWriter.WriteUInt16(parameters, 0, EaErrorOffset);
return parameters;
}
return new byte[0];
} }
public override byte[] GetData(bool isUnicode) public override byte[] GetData(bool isUnicode)
{ {
if (QueryInfo == null) return QueryInformationBytes;
{ }
// SMB_INFO_IS_NAME_VALID
return new byte[0]; public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel)
} {
else return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel);
{ }
return QueryInfo.GetBytes();
} public void SetQueryInformation(QueryInformation queryInformation)
{
QueryInformationBytes = queryInformation.GetBytes();
} }
public override Transaction2SubcommandName SubcommandName public override Transaction2SubcommandName SubcommandName

View file

@ -17,14 +17,14 @@ namespace SMBLibrary.SMB1
public class Transaction2SetFileInformationResponse : Transaction2Subcommand public class Transaction2SetFileInformationResponse : Transaction2Subcommand
{ {
// Parameters: // Parameters:
public ushort EaErrorOffset; public ushort EaErrorOffset; // Meaningful only when the request's InformationLevel is set to SMB_INFO_SET_EAS
public Transaction2SetFileInformationResponse() : base() public Transaction2SetFileInformationResponse() : base()
{ {
} }
public Transaction2SetFileInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base() public Transaction2SetFileInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0); EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
} }

View file

@ -17,14 +17,14 @@ namespace SMBLibrary.SMB1
public class Transaction2SetPathInformationResponse : Transaction2Subcommand public class Transaction2SetPathInformationResponse : Transaction2Subcommand
{ {
// Parameters: // Parameters:
public ushort EaErrorOffset; public ushort EaErrorOffset; // Meaningful only when the request's InformationLevel is set to SMB_INFO_SET_EAS
public Transaction2SetPathInformationResponse() : base() public Transaction2SetPathInformationResponse() : base()
{ {
} }
public Transaction2SetPathInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base() public Transaction2SetPathInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{ {
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0); EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
} }

View file

@ -101,18 +101,20 @@ namespace SMBLibrary.Server
bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0;
int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count);
// We ignore SearchAttributes // We ignore SearchAttributes
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response(); FindInformationList findInformationList = new FindInformationList();
for (int index = 0; index < entriesToReturn; index++) for (int index = 0; index < entriesToReturn; index++)
{ {
FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys); FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys);
response.FindInfoList.Add(infoEntry); findInformationList.Add(infoEntry);
if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID)) if (findInformationList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
{ {
response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1); findInformationList.RemoveAt(findInformationList.Count - 1);
break; break;
} }
} }
int returnCount = response.FindInfoList.Count; int returnCount = findInformationList.Count;
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount); response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount);
bool closeAtEndOfSearch = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AT_EOS) > 0; bool closeAtEndOfSearch = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AT_EOS) > 0;
bool closeAfterRequest = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AFTER_REQUEST) > 0; bool closeAfterRequest = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AFTER_REQUEST) > 0;
@ -193,7 +195,6 @@ namespace SMBLibrary.Server
internal static Transaction2FindNext2Response GetSubcommandResponse(SMBHeader header, Transaction2FindNext2Request subcommand, FileSystemShare share, StateObject state) internal static Transaction2FindNext2Response GetSubcommandResponse(SMBHeader header, Transaction2FindNext2Request subcommand, FileSystemShare share, StateObject state)
{ {
Transaction2FindNext2Response response = new Transaction2FindNext2Response();
if (!state.OpenSearches.ContainsKey(subcommand.SID)) if (!state.OpenSearches.ContainsKey(subcommand.SID))
{ {
header.Status = NTStatus.STATUS_INVALID_HANDLE; header.Status = NTStatus.STATUS_INVALID_HANDLE;
@ -202,20 +203,22 @@ namespace SMBLibrary.Server
bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0;
List<FileSystemEntry> entries = state.OpenSearches[subcommand.SID]; List<FileSystemEntry> entries = state.OpenSearches[subcommand.SID];
FindInformationList findInformationList = new FindInformationList();
for (int index = 0; index < entries.Count; index++) for (int index = 0; index < entries.Count; index++)
{ {
FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys); FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys);
response.FindInfoList.Add(infoEntry); findInformationList.Add(infoEntry);
if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID)) if (findInformationList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
{ {
response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1); findInformationList.RemoveAt(findInformationList.Count - 1);
break; break;
} }
} }
int returnCount = response.FindInfoList.Count; int returnCount = findInformationList.Count;
Transaction2FindNext2Response response = new Transaction2FindNext2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
entries.RemoveRange(0, returnCount); entries.RemoveRange(0, returnCount);
state.OpenSearches[subcommand.SID] = entries; state.OpenSearches[subcommand.SID] = entries;
response.SearchCount = (ushort)returnCount;
response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount); response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount);
if (response.EndOfSearch) if (response.EndOfSearch)
{ {
@ -227,7 +230,8 @@ namespace SMBLibrary.Server
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share) internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share)
{ {
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse(); Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
response.QueryFSInfo = InfoHelper.GetFSInformation(subcommand.InformationLevel, share.FileSystem); QueryFSInformation queryFSInformation = InfoHelper.GetFSInformation(subcommand.InformationLevel, share.FileSystem);
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
return response; return response;
} }
@ -245,7 +249,8 @@ namespace SMBLibrary.Server
return null; return null;
} }
Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse(); Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse();
response.QueryInfo = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel); QueryInformation queryInformation = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
response.SetQueryInformation(queryInformation);
return response; return response;
} }
@ -267,7 +272,8 @@ namespace SMBLibrary.Server
return null; return null;
} }
Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse(); Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse();
response.QueryInfo = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel); QueryInformation queryInformation = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
response.SetQueryInformation(queryInformation);
return response; return response;
} }