GetFileInformation and GetFileSystemInformation now return NTStatus. STATUS_OS2_INVALID_LEVEL will now be returned when applicable.

This commit is contained in:
Tal Aloni 2017-01-19 23:02:38 +02:00
parent 859e939cff
commit 7eb4c1ab2b
4 changed files with 164 additions and 108 deletions

View file

@ -32,10 +32,11 @@ namespace SMBLibrary
STATUS_USER_SESSION_DELETED = 0xC0000203, STATUS_USER_SESSION_DELETED = 0xC0000203,
STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205, STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,
STATUS_INVALID_SMB = 0x00010002, // CIFS/SMB1: A corrupt or invalid SMB request was received STATUS_INVALID_SMB = 0x00010002, // SMB1/CIFS: A corrupt or invalid SMB request was received
STATUS_SMB_BAD_COMMAND = 0x00160002, // CIFS/SMB1: An unknown SMB command code was received by the server STATUS_SMB_BAD_COMMAND = 0x00160002, // SMB1/CIFS: An unknown SMB command code was received by the server
STATUS_SMB_BAD_FID = 0x00060001, // CIFS/SMB1 STATUS_SMB_BAD_FID = 0x00060001, // SMB1/CIFS
STATUS_SMB_BAD_TID = 0x00050002, // CIFS/SMB1 STATUS_SMB_BAD_TID = 0x00050002, // SMB1/CIFS
STATUS_OS2_NO_MORE_SIDS = 0x00710001, // CIFS/SMB1 STATUS_OS2_NO_MORE_SIDS = 0x00710001, // SMB1/CIFS
STATUS_OS2_INVALID_LEVEL = 0x007C0001, // SMB1/CIFS
} }
} }

View file

@ -14,114 +14,128 @@ namespace SMBLibrary.Server.SMB1
{ {
public partial class SMB1FileSystemHelper public partial class SMB1FileSystemHelper
{ {
public static QueryInformation GetFileInformation(FileSystemEntry entry, bool deletePending, QueryInformationLevel informationLevel) public static NTStatus GetFileInformation(out QueryInformation result, FileSystemEntry entry, bool deletePending, QueryInformationLevel informationLevel)
{ {
switch (informationLevel) switch (informationLevel)
{ {
case QueryInformationLevel.SMB_INFO_STANDARD: case QueryInformationLevel.SMB_INFO_STANDARD:
{ {
QueryInfoStandard result = new QueryInfoStandard(); QueryInfoStandard information = new QueryInfoStandard();
result.CreationDateTime = entry.CreationTime; information.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime; information.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime; information.LastWriteDateTime = entry.LastWriteTime;
result.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue); information.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
result.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue); information.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_INFO_QUERY_EA_SIZE: case QueryInformationLevel.SMB_INFO_QUERY_EA_SIZE:
{ {
QueryEASize result = new QueryEASize(); QueryEASize information = new QueryEASize();
result.CreationDateTime = entry.CreationTime; information.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime; information.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime; information.LastWriteDateTime = entry.LastWriteTime;
result.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue); information.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
result.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue); information.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
result.Attributes = GetFileAttributes(entry); information.Attributes = GetFileAttributes(entry);
result.EASize = 0; information.EASize = 0;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST: case QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST:
{ {
throw new NotImplementedException(); result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
} }
case QueryInformationLevel.SMB_INFO_QUERY_ALL_EAS: case QueryInformationLevel.SMB_INFO_QUERY_ALL_EAS:
{ {
throw new NotImplementedException(); result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
} }
case QueryInformationLevel.SMB_INFO_IS_NAME_VALID: case QueryInformationLevel.SMB_INFO_IS_NAME_VALID:
{ {
throw new NotImplementedException(); result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
} }
case QueryInformationLevel.SMB_QUERY_FILE_BASIC_INFO: case QueryInformationLevel.SMB_QUERY_FILE_BASIC_INFO:
{ {
QueryFileBasicInfo result = new QueryFileBasicInfo(); QueryFileBasicInfo information = new QueryFileBasicInfo();
result.CreationDateTime = entry.CreationTime; information.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime; information.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime; information.LastWriteDateTime = entry.LastWriteTime;
result.LastChangeTime = entry.LastWriteTime; information.LastChangeTime = entry.LastWriteTime;
result.ExtFileAttributes = GetExtendedFileAttributes(entry); information.ExtFileAttributes = GetExtendedFileAttributes(entry);
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_STANDARD_INFO: case QueryInformationLevel.SMB_QUERY_FILE_STANDARD_INFO:
{ {
QueryFileStandardInfo result = new QueryFileStandardInfo(); QueryFileStandardInfo information = new QueryFileStandardInfo();
result.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size); information.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.EndOfFile = entry.Size; information.EndOfFile = entry.Size;
result.DeletePending = deletePending; information.DeletePending = deletePending;
result.Directory = entry.IsDirectory; information.Directory = entry.IsDirectory;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_EA_INFO: case QueryInformationLevel.SMB_QUERY_FILE_EA_INFO:
{ {
QueryFileExtendedAttributeInfo result = new QueryFileExtendedAttributeInfo(); QueryFileExtendedAttributeInfo information = new QueryFileExtendedAttributeInfo();
result.EASize = 0; information.EASize = 0;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_NAME_INFO: case QueryInformationLevel.SMB_QUERY_FILE_NAME_INFO:
{ {
QueryFileNameInfo result = new QueryFileNameInfo(); QueryFileNameInfo information = new QueryFileNameInfo();
result.FileName = entry.Name; information.FileName = entry.Name;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO: case QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO:
{ {
QueryFileAllInfo result = new QueryFileAllInfo(); QueryFileAllInfo information = new QueryFileAllInfo();
result.CreationDateTime = entry.CreationTime; information.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime; information.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime; information.LastWriteDateTime = entry.LastWriteTime;
result.ExtFileAttributes = GetExtendedFileAttributes(entry); information.ExtFileAttributes = GetExtendedFileAttributes(entry);
result.LastChangeTime = entry.LastWriteTime; information.LastChangeTime = entry.LastWriteTime;
result.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size); information.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.EndOfFile = entry.Size; information.EndOfFile = entry.Size;
result.DeletePending = deletePending; information.DeletePending = deletePending;
result.Directory = entry.IsDirectory; information.Directory = entry.IsDirectory;
result.EASize = 0; information.EASize = 0;
result.FileName = entry.Name; information.FileName = entry.Name;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_ALT_NAME_INFO: case QueryInformationLevel.SMB_QUERY_FILE_ALT_NAME_INFO:
{ {
QueryFileAltNameInfo result = new QueryFileAltNameInfo(); QueryFileAltNameInfo information = new QueryFileAltNameInfo();
result.FileName = NTFileSystemHelper.GetShortName(entry.Name); information.FileName = NTFileSystemHelper.GetShortName(entry.Name);
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_STREAM_INFO: case QueryInformationLevel.SMB_QUERY_FILE_STREAM_INFO:
{ {
QueryFileStreamInfo result = new QueryFileStreamInfo(); QueryFileStreamInfo information = new QueryFileStreamInfo();
result.StreamSize = entry.Size; information.StreamSize = entry.Size;
result.StreamAllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size); information.StreamAllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.StreamName = "::$DATA"; information.StreamName = "::$DATA";
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryInformationLevel.SMB_QUERY_FILE_COMPRESSION_INFO: case QueryInformationLevel.SMB_QUERY_FILE_COMPRESSION_INFO:
{ {
QueryFileCompressionInfo result = new QueryFileCompressionInfo(); QueryFileCompressionInfo information = new QueryFileCompressionInfo();
result.CompressionFormat = CompressionFormat.COMPRESSION_FORMAT_NONE; information.CompressionFormat = CompressionFormat.COMPRESSION_FORMAT_NONE;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
default: default:
{ {
throw new UnsupportedInformationLevelException(); result = null;
return NTStatus.STATUS_OS2_INVALID_LEVEL;
} }
} }
} }

View file

@ -14,60 +14,67 @@ namespace SMBLibrary.Server.SMB1
{ {
public partial class SMB1FileSystemHelper public partial class SMB1FileSystemHelper
{ {
public static QueryFSInformation GetFileSystemInformation(QueryFSInformationLevel informationLevel, IFileSystem fileSystem) public static NTStatus GetFileSystemInformation(out QueryFSInformation result, QueryFSInformationLevel informationLevel, IFileSystem fileSystem)
{ {
switch (informationLevel) switch (informationLevel)
{ {
case QueryFSInformationLevel.SMB_INFO_ALLOCATION: case QueryFSInformationLevel.SMB_INFO_ALLOCATION:
{ {
QueryFSInfoAllocation result = new QueryFSInfoAllocation(); QueryFSInfoAllocation information = new QueryFSInfoAllocation();
result.FileSystemID = 0; information.FileSystemID = 0;
result.SectorUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector; information.SectorUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
result.UnitsTotal = (uint)Math.Min(fileSystem.Size / NTFileSystemHelper.ClusterSize, UInt32.MaxValue); information.UnitsTotal = (uint)Math.Min(fileSystem.Size / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
result.UnitsAvailable = (uint)Math.Min(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize, UInt32.MaxValue); information.UnitsAvailable = (uint)Math.Min(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
result.Sector = NTFileSystemHelper.BytesPerSector; information.Sector = NTFileSystemHelper.BytesPerSector;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryFSInformationLevel.SMB_INFO_VOLUME: case QueryFSInformationLevel.SMB_INFO_VOLUME:
{ {
QueryFSInfoVolume result = new QueryFSInfoVolume(); QueryFSInfoVolume information = new QueryFSInfoVolume();
result.VolumeLabel = String.Empty; information.VolumeLabel = String.Empty;
result.VolumeSerialNumber = 0; information.VolumeSerialNumber = 0;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryFSInformationLevel.SMB_QUERY_FS_VOLUME_INFO: case QueryFSInformationLevel.SMB_QUERY_FS_VOLUME_INFO:
{ {
QueryFSVolumeInfo result = new QueryFSVolumeInfo(); QueryFSVolumeInfo information = new QueryFSVolumeInfo();
result.VolumeCreationTime = DateTime.Now; information.VolumeCreationTime = DateTime.Now;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryFSInformationLevel.SMB_QUERY_FS_SIZE_INFO: case QueryFSInformationLevel.SMB_QUERY_FS_SIZE_INFO:
{ {
QueryFSSizeInfo result = new QueryFSSizeInfo(); QueryFSSizeInfo information = new QueryFSSizeInfo();
result.TotalAllocationUnits = (ulong)(fileSystem.Size / NTFileSystemHelper.ClusterSize); information.TotalAllocationUnits = (ulong)(fileSystem.Size / NTFileSystemHelper.ClusterSize);
result.TotalFreeAllocationUnits = (ulong)(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize); information.TotalFreeAllocationUnits = (ulong)(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize);
result.BytesPerSector = NTFileSystemHelper.BytesPerSector; information.BytesPerSector = NTFileSystemHelper.BytesPerSector;
result.SectorsPerAllocationUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector; information.SectorsPerAllocationUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryFSInformationLevel.SMB_QUERY_FS_DEVICE_INFO: case QueryFSInformationLevel.SMB_QUERY_FS_DEVICE_INFO:
{ {
QueryFSDeviceInfo result = new QueryFSDeviceInfo(); QueryFSDeviceInfo information = new QueryFSDeviceInfo();
result.DeviceCharacteristics = DeviceCharacteristics.IsMounted; information.DeviceCharacteristics = DeviceCharacteristics.IsMounted;
result.DeviceType = DeviceType.Disk; information.DeviceType = DeviceType.Disk;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
case QueryFSInformationLevel.SMB_QUERY_FS_ATTRIBUTE_INFO: case QueryFSInformationLevel.SMB_QUERY_FS_ATTRIBUTE_INFO:
{ {
QueryFSAttibuteInfo result = new QueryFSAttibuteInfo(); QueryFSAttibuteInfo information = new QueryFSAttibuteInfo();
result.FileSystemAttributes = FileSystemAttributes.UnicodeOnDisk; information.FileSystemAttributes = FileSystemAttributes.UnicodeOnDisk;
result.MaxFileNameLengthInBytes = 255; information.MaxFileNameLengthInBytes = 255;
result.FileSystemName = fileSystem.Name; information.FileSystemName = fileSystem.Name;
return result; result = information;
return NTStatus.STATUS_SUCCESS;
} }
default: default:
{ {
throw new UnsupportedInformationLevelException(); result = null;
return NTStatus.STATUS_OS2_INVALID_LEVEL;
} }
} }
} }

View file

@ -43,7 +43,16 @@ namespace SMBLibrary.Server.SMB1
int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count);
List<FileSystemEntry> temp = entries.GetRange(0, entriesToReturn); List<FileSystemEntry> temp = entries.GetRange(0, entriesToReturn);
int maxLength = (int)state.GetMaxDataCount(header.PID).Value; int maxLength = (int)state.GetMaxDataCount(header.PID).Value;
FindInformationList findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength); FindInformationList findInformationList;
try
{
findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
}
catch (UnsupportedInformationLevelException)
{
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
return null;
}
int returnCount = findInformationList.Count; int returnCount = findInformationList.Count;
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response(); Transaction2FindFirst2Response response = new Transaction2FindFirst2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag); response.SetFindInformationList(findInformationList, header.UnicodeFlag);
@ -83,7 +92,16 @@ namespace SMBLibrary.Server.SMB1
int maxLength = (int)state.GetMaxDataCount(header.PID).Value; int maxLength = (int)state.GetMaxDataCount(header.PID).Value;
int maxCount = Math.Min(openSearch.Entries.Count - openSearch.EnumerationLocation, subcommand.SearchCount); int maxCount = Math.Min(openSearch.Entries.Count - openSearch.EnumerationLocation, subcommand.SearchCount);
List<FileSystemEntry> temp = openSearch.Entries.GetRange(openSearch.EnumerationLocation, maxCount); List<FileSystemEntry> temp = openSearch.Entries.GetRange(openSearch.EnumerationLocation, maxCount);
FindInformationList findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength); FindInformationList findInformationList;
try
{
findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
}
catch (UnsupportedInformationLevelException)
{
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
return null;
}
int returnCount = findInformationList.Count; int returnCount = findInformationList.Count;
Transaction2FindNext2Response response = new Transaction2FindNext2Response(); Transaction2FindNext2Response response = new Transaction2FindNext2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag); response.SetFindInformationList(findInformationList, header.UnicodeFlag);
@ -99,7 +117,13 @@ namespace SMBLibrary.Server.SMB1
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share) internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share)
{ {
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse(); Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
QueryFSInformation queryFSInformation = SMB1FileSystemHelper.GetFileSystemInformation(subcommand.InformationLevel, share.FileSystem); QueryFSInformation queryFSInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileSystemInformation(out queryFSInformation, subcommand.InformationLevel, share.FileSystem);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag); response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
return response; return response;
} }
@ -118,9 +142,14 @@ namespace SMBLibrary.Server.SMB1
return null; return null;
} }
Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse(); Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse();
QueryInformation queryInformation = SMB1FileSystemHelper.GetFileInformation(entry, false, subcommand.InformationLevel); QueryInformation queryInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileInformation(out queryInformation, entry, false, subcommand.InformationLevel);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryInformation(queryInformation); response.SetQueryInformation(queryInformation);
return response; return response;
} }
@ -142,9 +171,14 @@ namespace SMBLibrary.Server.SMB1
return null; return null;
} }
Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse(); Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse();
QueryInformation queryInformation = SMB1FileSystemHelper.GetFileInformation(entry, openFile.DeleteOnClose, subcommand.InformationLevel); QueryInformation queryInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileInformation(out queryInformation, entry, openFile.DeleteOnClose, subcommand.InformationLevel);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryInformation(queryInformation); response.SetQueryInformation(queryInformation);
return response; return response;
} }