SMB1: Improved FindInformation implementation and corrected reading of FindInformation entries from buffer

This commit is contained in:
Tal Aloni 2017-09-16 00:00:28 +03:00
parent 0b320ad33e
commit 6a1c68faf7
8 changed files with 36 additions and 57 deletions

View file

@ -18,7 +18,7 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 94;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
public DateTime? CreationTime;
public DateTime? LastAccessTime;
@ -38,11 +38,11 @@ namespace SMBLibrary.SMB1
// Will, in some rare but repeatable cases, cause issues with Windows XP SP3 as a client
// (the client will display an error message that the folder "refers to a location that is unavailable"...)
public FindFileBothDirectoryInfo() : base(false)
public FindFileBothDirectoryInfo() : base()
{
}
public FindFileBothDirectoryInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileBothDirectoryInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -18,7 +18,7 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 64;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
public DateTime? CreationTime;
public DateTime? LastAccessTime;
@ -30,11 +30,11 @@ namespace SMBLibrary.SMB1
//uint FileNameLength; // In bytes, MUST exclude the null termination.
public string FileName; // OEM / Unicode character array. MUST be written as SMB_STRING, and read as fixed length string.
public FindFileDirectoryInfo() : base(false)
public FindFileDirectoryInfo() : base()
{
}
public FindFileDirectoryInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileDirectoryInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -18,7 +18,7 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 68;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
public DateTime? CreationTime;
public DateTime? LastAccessTime;
@ -31,11 +31,11 @@ namespace SMBLibrary.SMB1
public uint EASize;
public string FileName; // OEM / Unicode character array. MUST be written as SMB_STRING, and read as fixed length string.
public FindFileFullDirectoryInfo() : base(false)
public FindFileFullDirectoryInfo() : base()
{
}
public FindFileFullDirectoryInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileFullDirectoryInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -18,7 +18,7 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 104;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
public DateTime? CreationTime;
public DateTime? LastAccessTime;
@ -40,11 +40,11 @@ namespace SMBLibrary.SMB1
// Will, in some rare but repeatable cases, cause issues with Windows XP SP3 as a client
// (the client will display an error message that the folder "refers to a location that is unavailable"...)
public FindFileIDBothDirectoryInfo() : base(false)
public FindFileIDBothDirectoryInfo() : base()
{
}
public FindFileIDBothDirectoryInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileIDBothDirectoryInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -18,7 +18,7 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 80;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
public DateTime? CreationTime;
public DateTime? LastAccessTime;
@ -33,11 +33,11 @@ namespace SMBLibrary.SMB1
public ulong FileID;
public string FileName; // OEM / Unicode character array. MUST be written as SMB_STRING, and read as fixed length string.
public FindFileIDFullDirectoryInfo() : base(false)
public FindFileIDFullDirectoryInfo() : base()
{
}
public FindFileIDFullDirectoryInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileIDFullDirectoryInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -18,16 +18,16 @@ namespace SMBLibrary.SMB1
{
public const int FixedLength = 12;
public uint NextEntryOffset;
// uint NextEntryOffset;
public uint FileIndex; // SHOULD be set to zero when sent in a response and SHOULD be ignored when received by the client
//uint FileNameLength; // In bytes, MUST exclude the null termination.
public string FileName; // OEM / Unicode character array. MUST be written as SMB_STRING, and read as fixed length string.
public FindFileNamesInfo() : base(false)
public FindFileNamesInfo() : base()
{
}
public FindFileNamesInfo(byte[] buffer, ref int offset, bool isUnicode) : base(false)
public FindFileNamesInfo(byte[] buffer, int offset, bool isUnicode) : base()
{
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
FileIndex = LittleEndianReader.ReadUInt32(buffer, ref offset);

View file

@ -12,42 +12,37 @@ namespace SMBLibrary.SMB1
{
public abstract class FindInformation
{
private bool m_returnResumeKeys;
public uint NextEntryOffset;
public FindInformation(bool returnResumeKeys)
public FindInformation()
{
m_returnResumeKeys = returnResumeKeys;
}
public abstract void WriteBytes(byte[] buffer, ref int offset, bool isUnicode);
public abstract int GetLength(bool isUnicode);
public bool ReturnResumeKeys
{
get
{
return m_returnResumeKeys;
}
}
public abstract FindInformationLevel InformationLevel
{
get;
}
public static FindInformation ReadEntry(byte[] buffer, ref int offset, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys)
public static FindInformation ReadEntry(byte[] buffer, int offset, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys)
{
switch (informationLevel)
{
case FindInformationLevel.SMB_FIND_FILE_DIRECTORY_INFO:
return new FindFileDirectoryInfo(buffer, ref offset, isUnicode);
return new FindFileDirectoryInfo(buffer, offset, isUnicode);
case FindInformationLevel.SMB_FIND_FILE_FULL_DIRECTORY_INFO:
return new FindFileFullDirectoryInfo(buffer, ref offset, isUnicode);
return new FindFileFullDirectoryInfo(buffer, offset, isUnicode);
case FindInformationLevel.SMB_FIND_FILE_NAMES_INFO:
return new FindFileNamesInfo(buffer, ref offset, isUnicode);
return new FindFileNamesInfo(buffer, offset, isUnicode);
case FindInformationLevel.SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
return new FindFileBothDirectoryInfo(buffer, ref offset, isUnicode);
return new FindFileBothDirectoryInfo(buffer, offset, isUnicode);
case FindInformationLevel.SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO:
return new FindFileIDFullDirectoryInfo(buffer, offset, isUnicode);
case FindInformationLevel.SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO:
return new FindFileIDBothDirectoryInfo(buffer, offset, isUnicode);
default:
throw new UnsupportedInformationLevelException();
}

View file

@ -22,36 +22,20 @@ namespace SMBLibrary.SMB1
int offset = 0;
while (offset < buffer.Length)
{
FindInformation entry = FindInformation.ReadEntry(buffer, ref offset, informationLevel, isUnicode, returnResumeKeys);
FindInformation entry = FindInformation.ReadEntry(buffer, offset, informationLevel, isUnicode, returnResumeKeys);
this.Add(entry);
offset += (int)entry.NextEntryOffset;
}
}
public byte[] GetBytes(bool isUnicode)
{
for(int index = 0; index < this.Count; index++)
for(int index = 0; index < this.Count - 1; index++)
{
if (index < this.Count - 1)
{
FindInformation entry = this[index];
int entryLength = entry.GetLength(isUnicode);
if (entry is FindFileBothDirectoryInfo)
{
((FindFileBothDirectoryInfo)entry).NextEntryOffset = (uint)entryLength;
}
else if (entry is FindFileDirectoryInfo)
{
((FindFileDirectoryInfo)entry).NextEntryOffset = (uint)entryLength;
}
else if (entry is FindFileFullDirectoryInfo)
{
((FindFileFullDirectoryInfo)entry).NextEntryOffset = (uint)entryLength;
}
else if (entry is FindFileNamesInfo)
{
((FindFileNamesInfo)entry).NextEntryOffset = (uint)entryLength;
}
}
FindInformation entry = this[index];
int entryLength = entry.GetLength(isUnicode);
entry.NextEntryOffset = (uint)entryLength;
}
int length = GetLength(isUnicode);
byte[] buffer = new byte[length];