mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-08-03 22:41:49 +02:00
Server: SMB1: Added support for pass-through Information Levels
This commit is contained in:
parent
2b14375876
commit
c1210d57bc
3 changed files with 154 additions and 47 deletions
|
@ -35,6 +35,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
Capabilities.RpcRemoteApi |
|
||||
Capabilities.NTStatusCode |
|
||||
Capabilities.NTFind |
|
||||
Capabilities.InfoLevelPassthrough |
|
||||
Capabilities.LargeRead |
|
||||
Capabilities.LargeWrite;
|
||||
response.SystemTime = DateTime.UtcNow;
|
||||
|
@ -67,6 +68,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
Capabilities.RpcRemoteApi |
|
||||
Capabilities.NTStatusCode |
|
||||
Capabilities.NTFind |
|
||||
Capabilities.InfoLevelPassthrough |
|
||||
Capabilities.LargeRead |
|
||||
Capabilities.LargeWrite |
|
||||
Capabilities.ExtendedSecurity;
|
||||
|
|
|
@ -29,6 +29,21 @@ namespace SMBLibrary.Server.SMB1
|
|||
return returnStatus;
|
||||
}
|
||||
|
||||
public static NTStatus GetFileInformation(out FileInformation result, INTFileStore fileStore, string path, FileInformationClass informationClass, SecurityContext securityContext)
|
||||
{
|
||||
object handle;
|
||||
FileStatus fileStatus;
|
||||
NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, (AccessMask)FileAccessMask.FILE_READ_ATTRIBUTES, 0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, securityContext);
|
||||
if (openStatus != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
result = null;
|
||||
return openStatus;
|
||||
}
|
||||
NTStatus returnStatus = fileStore.GetFileInformation(out result, handle, informationClass);
|
||||
fileStore.CloseFile(handle);
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
public static NTStatus GetFileInformation(out QueryInformation result, INTFileStore fileStore, object handle, QueryInformationLevel informationLevel)
|
||||
{
|
||||
result = null;
|
||||
|
|
|
@ -145,16 +145,32 @@ namespace SMBLibrary.Server.SMB1
|
|||
}
|
||||
|
||||
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
|
||||
QueryFSInformation queryFSInformation;
|
||||
NTStatus queryStatus = SMB1FileStoreHelper.GetFileSystemInformation(out queryFSInformation, share.FileStore, subcommand.QueryFSInformationLevel);
|
||||
if (queryStatus != NTStatus.STATUS_SUCCESS)
|
||||
if (subcommand.IsPassthroughInformationLevel)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information level: {1}, NTStatus: {2}", share.Name, subcommand.QueryFSInformationLevel, queryStatus);
|
||||
header.Status = queryStatus;
|
||||
return null;
|
||||
FileSystemInformation fileSystemInfo;
|
||||
NTStatus status = share.FileStore.GetFileSystemInformation(out fileSystemInfo, subcommand.FileSystemInformationClass);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information class: {1}, NTStatus: {2}", share.Name, subcommand.FileSystemInformationClass, status);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information class: {1}", share.Name, subcommand.FileSystemInformationClass);
|
||||
response.SetFileSystemInformation(fileSystemInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryFSInformation queryFSInformation;
|
||||
NTStatus status = SMB1FileStoreHelper.GetFileSystemInformation(out queryFSInformation, share.FileStore, subcommand.QueryFSInformationLevel);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information level: {1}, NTStatus: {2}", share.Name, subcommand.QueryFSInformationLevel, status);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information level: {1}", share.Name, subcommand.QueryFSInformationLevel);
|
||||
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information level: {1}", share.Name, subcommand.QueryFSInformationLevel);
|
||||
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -178,16 +194,37 @@ namespace SMBLibrary.Server.SMB1
|
|||
}
|
||||
|
||||
Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse();
|
||||
QueryInformation queryInformation;
|
||||
NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, path, subcommand.QueryInformationLevel, session.SecurityContext);
|
||||
if (queryStatus != NTStatus.STATUS_SUCCESS)
|
||||
if (subcommand.IsPassthroughInformationLevel && subcommand.FileInformationClass != FileInformationClass.FileAllInformation)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}", share.Name, path, subcommand.QueryInformationLevel, queryStatus);
|
||||
header.Status = queryStatus;
|
||||
return null;
|
||||
FileInformation fileInfo;
|
||||
NTStatus status = SMB1FileStoreHelper.GetFileInformation(out fileInfo, share.FileStore, path, subcommand.FileInformationClass, session.SecurityContext);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}", share.Name, path, subcommand.FileInformationClass, status);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information class: {2}", share.Name, path, subcommand.FileInformationClass);
|
||||
response.SetFileInformation(fileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The FILE_ALL_INFORMATION structure described in [MS-FSCC], is NOT used by [MS-SMB]
|
||||
if (subcommand.IsPassthroughInformationLevel && subcommand.FileInformationClass == FileInformationClass.FileAllInformation)
|
||||
{
|
||||
subcommand.QueryInformationLevel = QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO;
|
||||
}
|
||||
QueryInformation queryInformation;
|
||||
NTStatus status = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, path, subcommand.QueryInformationLevel, session.SecurityContext);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}", share.Name, path, subcommand.QueryInformationLevel, status);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}", share.Name, path, subcommand.QueryInformationLevel);
|
||||
response.SetQueryInformation(queryInformation);
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}", share.Name, path, subcommand.QueryInformationLevel);
|
||||
response.SetQueryInformation(queryInformation);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -213,16 +250,37 @@ namespace SMBLibrary.Server.SMB1
|
|||
}
|
||||
|
||||
Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse();
|
||||
QueryInformation queryInformation;
|
||||
NTStatus queryStatus = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, openFile.Handle, subcommand.QueryInformationLevel);
|
||||
if (queryStatus != NTStatus.STATUS_SUCCESS)
|
||||
if (subcommand.IsPassthroughInformationLevel && subcommand.FileInformationClass != FileInformationClass.FileAllInformation)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.QueryInformationLevel, queryStatus, subcommand.FID);
|
||||
header.Status = queryStatus;
|
||||
return null;
|
||||
FileInformation fileInfo;
|
||||
NTStatus status = share.FileStore.GetFileInformation(out fileInfo, openFile.Handle, subcommand.FileInformationClass);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.FileInformationClass, status, subcommand.FID);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.FileInformationClass, subcommand.FID);
|
||||
response.SetFileInformation(fileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The FILE_ALL_INFORMATION structure described in [MS-FSCC], is NOT used by [MS-SMB]
|
||||
if (subcommand.IsPassthroughInformationLevel && subcommand.FileInformationClass == FileInformationClass.FileAllInformation)
|
||||
{
|
||||
subcommand.QueryInformationLevel = QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO;
|
||||
}
|
||||
QueryInformation queryInformation;
|
||||
NTStatus status = SMB1FileStoreHelper.GetFileInformation(out queryInformation, share.FileStore, openFile.Handle, subcommand.QueryInformationLevel);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.QueryInformationLevel, status, subcommand.FID);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.QueryInformationLevel, subcommand.FID);
|
||||
response.SetQueryInformation(queryInformation);
|
||||
}
|
||||
state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.QueryInformationLevel, subcommand.FID);
|
||||
response.SetQueryInformation(queryInformation);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -247,32 +305,64 @@ namespace SMBLibrary.Server.SMB1
|
|||
}
|
||||
}
|
||||
|
||||
SetInformation information;
|
||||
try
|
||||
if (subcommand.IsPassthroughInformationLevel)
|
||||
{
|
||||
information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.SetInformationLevel);
|
||||
}
|
||||
catch(UnsupportedInformationLevelException)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.SetInformationLevel);
|
||||
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
|
||||
return null;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.SetInformationLevel);
|
||||
header.Status = NTStatus.STATUS_INVALID_PARAMETER;
|
||||
return null;
|
||||
}
|
||||
FileInformation fileInfo;
|
||||
try
|
||||
{
|
||||
fileInfo = FileInformation.GetFileInformation(subcommand.InformationBytes, 0, subcommand.FileInformationClass);
|
||||
}
|
||||
catch (UnsupportedInformationLevelException)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.FileInformationClass);
|
||||
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
|
||||
return null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.FileInformationClass);
|
||||
header.Status = NTStatus.STATUS_INVALID_PARAMETER;
|
||||
return null;
|
||||
}
|
||||
|
||||
NTStatus status = SMB1FileStoreHelper.SetFileInformation(share.FileStore, openFile.Handle, information);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.SetInformationLevel, status, subcommand.FID);
|
||||
header.Status = status;
|
||||
return null;
|
||||
NTStatus status = share.FileStore.SetFileInformation(openFile.Handle, fileInfo);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.FileInformationClass, status, subcommand.FID);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.FileInformationClass, subcommand.FID);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetInformation information;
|
||||
try
|
||||
{
|
||||
information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.SetInformationLevel);
|
||||
}
|
||||
catch (UnsupportedInformationLevelException)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.SetInformationLevel);
|
||||
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
|
||||
return null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.SetInformationLevel);
|
||||
header.Status = NTStatus.STATUS_INVALID_PARAMETER;
|
||||
return null;
|
||||
}
|
||||
|
||||
NTStatus status = SMB1FileStoreHelper.SetFileInformation(share.FileStore, openFile.Handle, information);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.SetInformationLevel, status, subcommand.FID);
|
||||
header.Status = status;
|
||||
return null;
|
||||
}
|
||||
state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.SetInformationLevel, subcommand.FID);
|
||||
}
|
||||
state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.SetInformationLevel, subcommand.FID);
|
||||
Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();
|
||||
return response;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue