mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-05-15 17:06:59 +02:00
API improvement: FileSystemShare: Added OnAccessRequest event that allows the subscriber to manage read / write permissions
This commit is contained in:
parent
f9ad9f9b5e
commit
fd26380dab
16 changed files with 248 additions and 81 deletions
|
@ -20,10 +20,10 @@ namespace SMBLibrary.Server
|
|||
public const int BytesPerSector = 512;
|
||||
public const int ClusterSize = 4096;
|
||||
|
||||
public static NTStatus CreateFile(out FileSystemEntry entry, FileSystemShare share, string userName, string path, CreateDisposition createDisposition, CreateOptions createOptions, AccessMask desiredAccess, ConnectionState state)
|
||||
public static NTStatus CreateFile(out FileSystemEntry entry, IFileSystem fileSystem, string path, AccessMask desiredAccess, CreateDisposition createDisposition, CreateOptions createOptions, ConnectionState state)
|
||||
{
|
||||
bool hasWriteAccess = share.HasWriteAccess(userName);
|
||||
IFileSystem fileSystem = share.FileSystem;
|
||||
FileAccess createAccess = ToCreateFileAccess(desiredAccess, createDisposition);
|
||||
bool requestedWriteAccess = (createAccess & FileAccess.Write) > 0;
|
||||
|
||||
bool forceDirectory = (createOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0;
|
||||
bool forceFile = (createOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0;
|
||||
|
@ -82,7 +82,7 @@ namespace SMBLibrary.Server
|
|||
return NTStatus.STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
if (!hasWriteAccess)
|
||||
if (!requestedWriteAccess)
|
||||
{
|
||||
return NTStatus.STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace SMBLibrary.Server
|
|||
return NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!hasWriteAccess)
|
||||
if (!requestedWriteAccess)
|
||||
{
|
||||
return NTStatus.STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ namespace SMBLibrary.Server
|
|||
createDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
|
||||
createDisposition == CreateDisposition.FILE_SUPERSEDE)
|
||||
{
|
||||
if (!hasWriteAccess)
|
||||
if (!requestedWriteAccess)
|
||||
{
|
||||
return NTStatus.STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
@ -208,12 +208,6 @@ namespace SMBLibrary.Server
|
|||
return NTStatus.STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FileAccess fileAccess = ToFileAccess(desiredAccess.File);
|
||||
if (!hasWriteAccess && (fileAccess == FileAccess.Write || fileAccess == FileAccess.ReadWrite))
|
||||
{
|
||||
return NTStatus.STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NTStatus.STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -395,6 +389,48 @@ namespace SMBLibrary.Server
|
|||
}
|
||||
}
|
||||
|
||||
public static FileAccess ToCreateFileAccess(AccessMask desiredAccess, CreateDisposition createDisposition)
|
||||
{
|
||||
FileAccess result = 0;
|
||||
|
||||
if ((desiredAccess.File & FileAccessMask.FILE_READ_DATA) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.FILE_READ_EA) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.FILE_READ_ATTRIBUTES) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.MAXIMUM_ALLOWED) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.GENERIC_ALL) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.GENERIC_READ) > 0)
|
||||
{
|
||||
result |= FileAccess.Read;
|
||||
}
|
||||
|
||||
if ((desiredAccess.File & FileAccessMask.FILE_WRITE_DATA) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.FILE_APPEND_DATA) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.FILE_WRITE_EA) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.FILE_WRITE_ATTRIBUTES) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.DELETE) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.WRITE_DAC) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.WRITE_OWNER) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.MAXIMUM_ALLOWED) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.GENERIC_ALL) > 0 ||
|
||||
(desiredAccess.File & FileAccessMask.GENERIC_WRITE) > 0)
|
||||
{
|
||||
result |= FileAccess.Write;
|
||||
}
|
||||
|
||||
if ((desiredAccess.Directory & DirectoryAccessMask.FILE_DELETE_CHILD) > 0)
|
||||
{
|
||||
result |= FileAccess.Write;
|
||||
}
|
||||
|
||||
if (createDisposition == CreateDisposition.FILE_CREATE ||
|
||||
createDisposition == CreateDisposition.FILE_SUPERSEDE)
|
||||
{
|
||||
result |= FileAccess.Write;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FileAccess ToFileAccess(FileAccessMask desiredAccess)
|
||||
{
|
||||
FileAccess result = 0;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
internal static SMB1Command GetCreateDirectoryResponse(SMB1Header header, CreateDirectoryRequest request, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, request.DirectoryName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY);
|
||||
|
@ -48,7 +48,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
internal static SMB1Command GetDeleteDirectoryResponse(SMB1Header header, DeleteDirectoryRequest request, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, request.DirectoryName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
|
||||
|
@ -103,7 +103,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
internal static SMB1Command GetDeleteResponse(SMB1Header header, DeleteRequest request, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, request.FileName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_DELETE);
|
||||
|
@ -146,7 +146,12 @@ namespace SMBLibrary.Server.SMB1
|
|||
internal static SMB1Command GetRenameResponse(SMB1Header header, RenameRequest request, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, request.OldFileName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_RENAME);
|
||||
}
|
||||
if (!share.HasWriteAccess(session.UserName, request.NewFileName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_RENAME);
|
||||
|
@ -210,7 +215,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
internal static SMB1Command GetSetInformationResponse(SMB1Header header, SetInformationRequest request, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, request.FileName, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
|
||||
|
@ -259,7 +264,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
|
||||
}
|
||||
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
if (!share.HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
|
||||
|
|
|
@ -48,9 +48,15 @@ namespace SMBLibrary.Server.SMB1
|
|||
else // FileSystemShare
|
||||
{
|
||||
FileSystemShare fileSystemShare = (FileSystemShare)share;
|
||||
string userName = session.UserName;
|
||||
FileAccess createAccess = NTFileSystemHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition);
|
||||
if (!fileSystemShare.HasAccess(session.UserName, path, createAccess, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
|
||||
FileSystemEntry entry;
|
||||
NTStatus createStatus = NTFileSystemHelper.CreateFile(out entry, fileSystemShare, userName, path, request.CreateDisposition, request.CreateOptions, request.DesiredAccess, state);
|
||||
NTStatus createStatus = NTFileSystemHelper.CreateFile(out entry, fileSystemShare.FileSystem, path, request.DesiredAccess, request.CreateDisposition, request.CreateOptions, state);
|
||||
if (createStatus != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
header.Status = createStatus;
|
||||
|
|
|
@ -48,20 +48,19 @@ namespace SMBLibrary.Server.SMB1
|
|||
else // FileSystemShare
|
||||
{
|
||||
FileSystemShare fileSystemShare = (FileSystemShare)share;
|
||||
string userName = session.UserName;
|
||||
bool hasWriteAccess = fileSystemShare.HasWriteAccess(userName);
|
||||
FileAccess fileAccess = ToFileAccess(request.AccessMode.AccessMode);
|
||||
if (!fileSystemShare.HasAccess(session.UserName, path, fileAccess, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
|
||||
IFileSystem fileSystem = fileSystemShare.FileSystem;
|
||||
|
||||
OpenResult openResult;
|
||||
FileSystemEntry entry = fileSystem.GetEntry(path);
|
||||
if (entry != null)
|
||||
{
|
||||
if (!hasWriteAccess && request.AccessMode.AccessMode == AccessMode.Write || request.AccessMode.AccessMode == AccessMode.ReadWrite)
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX);
|
||||
}
|
||||
|
||||
if (request.OpenMode.FileExistsOpts == FileExistsOpts.ReturnError)
|
||||
{
|
||||
header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
|
||||
|
@ -121,7 +120,6 @@ namespace SMBLibrary.Server.SMB1
|
|||
openResult = OpenResult.NotExistedAndWasCreated;
|
||||
}
|
||||
|
||||
FileAccess fileAccess = ToFileAccess(request.AccessMode.AccessMode);
|
||||
FileShare fileShare = ToFileShare(request.AccessMode.SharingMode);
|
||||
Stream stream = null;
|
||||
if (!entry.IsDirectory)
|
||||
|
|
|
@ -26,6 +26,16 @@ namespace SMBLibrary.Server.SMB1
|
|||
header.Status = NTStatus.STATUS_INVALID_HANDLE;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (share is FileSystemShare)
|
||||
{
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] data;
|
||||
header.Status = NTFileSystemHelper.ReadFile(out data, openFile, request.ReadOffsetInBytes, request.CountOfBytesToRead, state);
|
||||
if (header.Status != NTStatus.STATUS_SUCCESS)
|
||||
|
@ -48,6 +58,16 @@ namespace SMBLibrary.Server.SMB1
|
|||
header.Status = NTStatus.STATUS_INVALID_HANDLE;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (share is FileSystemShare)
|
||||
{
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
}
|
||||
|
||||
uint maxCount = request.MaxCount;
|
||||
if ((share is FileSystemShare) && state.LargeRead)
|
||||
{
|
||||
|
@ -79,6 +99,16 @@ namespace SMBLibrary.Server.SMB1
|
|||
header.Status = NTStatus.STATUS_INVALID_HANDLE;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
|
||||
if (share is FileSystemShare)
|
||||
{
|
||||
if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfBytesWritten;
|
||||
header.Status = NTFileSystemHelper.WriteFile(out numberOfBytesWritten, openFile, request.WriteOffsetInBytes, request.Data, state);
|
||||
if (header.Status != NTStatus.STATUS_SUCCESS)
|
||||
|
@ -99,6 +129,16 @@ namespace SMBLibrary.Server.SMB1
|
|||
header.Status = NTStatus.STATUS_INVALID_HANDLE;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
|
||||
if (share is FileSystemShare)
|
||||
{
|
||||
if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(request.CommandName);
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfBytesWritten;
|
||||
header.Status = NTFileSystemHelper.WriteFile(out numberOfBytesWritten, openFile, (long)request.Offset, request.Data, state);
|
||||
if (header.Status != NTStatus.STATUS_SUCCESS)
|
||||
|
|
|
@ -116,6 +116,13 @@ namespace SMBLibrary.Server.SMB1
|
|||
|
||||
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
if (!share.HasReadAccess(session.UserName, @"\", state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return null;
|
||||
}
|
||||
|
||||
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
|
||||
QueryFSInformation queryFSInformation;
|
||||
NTStatus queryStatus = SMB1FileSystemHelper.GetFileSystemInformation(out queryFSInformation, subcommand.InformationLevel, share.FileSystem);
|
||||
|
@ -131,8 +138,15 @@ namespace SMBLibrary.Server.SMB1
|
|||
|
||||
internal static Transaction2QueryPathInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2QueryPathInformationRequest subcommand, FileSystemShare share, SMB1ConnectionState state)
|
||||
{
|
||||
IFileSystem fileSystem = share.FileSystem;
|
||||
SMB1Session session = state.GetSession(header.UID);
|
||||
string path = subcommand.FileName;
|
||||
if (!share.HasReadAccess(session.UserName, path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return null;
|
||||
}
|
||||
|
||||
IFileSystem fileSystem = share.FileSystem;
|
||||
FileSystemEntry entry = fileSystem.GetEntry(path);
|
||||
if (entry == null)
|
||||
{
|
||||
|
@ -166,6 +180,12 @@ namespace SMBLibrary.Server.SMB1
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!share.HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return null;
|
||||
}
|
||||
|
||||
FileSystemEntry entry = fileSystem.GetEntry(openFile.Path);
|
||||
if (entry == null)
|
||||
{
|
||||
|
@ -195,6 +215,12 @@ namespace SMBLibrary.Server.SMB1
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!share.HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return null;
|
||||
}
|
||||
|
||||
SetInformation information;
|
||||
try
|
||||
{
|
||||
|
@ -211,12 +237,6 @@ namespace SMBLibrary.Server.SMB1
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!share.HasWriteAccess(session.UserName))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return null;
|
||||
}
|
||||
|
||||
NTStatus status = SMB1FileSystemHelper.SetFileInformation(share.FileSystem, openFile, information, state);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace SMBLibrary.Server.SMB1
|
|||
return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
|
||||
}
|
||||
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName))
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
|
||||
|
|
|
@ -42,9 +42,14 @@ namespace SMBLibrary.Server.SMB2
|
|||
else
|
||||
{
|
||||
FileSystemShare fileSystemShare = (FileSystemShare)share;
|
||||
FileAccess createAccess = NTFileSystemHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition);
|
||||
if (!fileSystemShare.HasAccess(session.UserName, path, createAccess, state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
FileSystemEntry entry;
|
||||
NTStatus createStatus = NTFileSystemHelper.CreateFile(out entry, (FileSystemShare)share, session.UserName, path, request.CreateDisposition, request.CreateOptions, request.DesiredAccess, state);
|
||||
NTStatus createStatus = NTFileSystemHelper.CreateFile(out entry, fileSystemShare.FileSystem, path, request.DesiredAccess, request.CreateDisposition, request.CreateOptions, state);
|
||||
if (createStatus != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, createStatus);
|
||||
|
|
|
@ -28,6 +28,11 @@ namespace SMBLibrary.Server.SMB2
|
|||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED);
|
||||
}
|
||||
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
FileSystemShare fileSystemShare = (FileSystemShare)share;
|
||||
IFileSystem fileSystem = fileSystemShare.FileSystem;
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ namespace SMBLibrary.Server.SMB2
|
|||
}
|
||||
else // FileSystemShare
|
||||
{
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
IFileSystem fileSystem = ((FileSystemShare)share).FileSystem;
|
||||
FileSystemEntry entry = fileSystem.GetEntry(openFile.Path);
|
||||
if (entry == null)
|
||||
|
@ -56,6 +60,10 @@ namespace SMBLibrary.Server.SMB2
|
|||
{
|
||||
if (share is FileSystemShare)
|
||||
{
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
IFileSystem fileSystem = ((FileSystemShare)share).FileSystem;
|
||||
FileSystemInformation fileSystemInformation;
|
||||
NTStatus queryStatus = NTFileSystemHelper.GetFileSystemInformation(out fileSystemInformation, request.FileSystemInformationClass, fileSystem);
|
||||
|
|
|
@ -28,10 +28,11 @@ namespace SMBLibrary.Server.SMB2
|
|||
if (share is FileSystemShare)
|
||||
{
|
||||
IFileSystem fileSystem = ((FileSystemShare)share).FileSystem;
|
||||
if (!((FileSystemShare)share).HasWriteAccess(session.UserName))
|
||||
if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
FileInformation information;
|
||||
try
|
||||
{
|
||||
|
@ -50,6 +51,15 @@ namespace SMBLibrary.Server.SMB2
|
|||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (information is FileRenameInformationType2)
|
||||
{
|
||||
string newFileName = ((FileRenameInformationType2)information).FileName;
|
||||
if (!((FileSystemShare)share).HasWriteAccess(session.UserName, newFileName, state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
NTStatus status = NTFileSystemHelper.SetFileInformation(fileSystem, openFile, information, state);
|
||||
if (status != NTStatus.STATUS_SUCCESS)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace SMBLibrary.Server.SMB2
|
|||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_OBJECT_PATH_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName))
|
||||
if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint))
|
||||
{
|
||||
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
|
|
@ -218,12 +218,6 @@ namespace SMBLibrary.Server
|
|||
}
|
||||
else if (command is WriteRequest)
|
||||
{
|
||||
string userName = session.UserName;
|
||||
if (share is FileSystemShare && !((FileSystemShare)share).HasWriteAccess(userName))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(command.CommandName);
|
||||
}
|
||||
WriteRequest request = (WriteRequest)command;
|
||||
return ReadWriteResponseHelper.GetWriteResponse(header, request, share, state);
|
||||
}
|
||||
|
@ -272,12 +266,6 @@ namespace SMBLibrary.Server
|
|||
}
|
||||
else if (command is WriteAndXRequest)
|
||||
{
|
||||
string userName = session.UserName;
|
||||
if (share is FileSystemShare && !((FileSystemShare)share).HasWriteAccess(userName))
|
||||
{
|
||||
header.Status = NTStatus.STATUS_ACCESS_DENIED;
|
||||
return new ErrorResponse(command.CommandName);
|
||||
}
|
||||
WriteAndXRequest request = (WriteAndXRequest)command;
|
||||
return ReadWriteResponseHelper.GetWriteResponse(header, request, share, state);
|
||||
}
|
||||
|
|
|
@ -6,17 +6,36 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Server
|
||||
{
|
||||
public class AccessRequestArgs : EventArgs
|
||||
{
|
||||
public string UserName;
|
||||
public string Path;
|
||||
public FileAccess RequestedAccess;
|
||||
public IPEndPoint ClientEndPoint;
|
||||
public bool Allow = true;
|
||||
|
||||
public AccessRequestArgs(string userName, string path, FileAccess requestedAccess, IPEndPoint clientEndPoint)
|
||||
{
|
||||
UserName = userName;
|
||||
Path = path;
|
||||
RequestedAccess = requestedAccess;
|
||||
ClientEndPoint = clientEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileSystemShare : ISMBShare
|
||||
{
|
||||
private string m_name;
|
||||
public IFileSystem m_fileSystem;
|
||||
public List<string> ReadAccess;
|
||||
public List<string> WriteAccess;
|
||||
|
||||
public event EventHandler<AccessRequestArgs> OnAccessRequest;
|
||||
|
||||
public FileSystemShare(string shareName, IFileSystem fileSystem)
|
||||
{
|
||||
|
@ -24,31 +43,27 @@ namespace SMBLibrary.Server
|
|||
m_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public bool HasReadAccess(string userName)
|
||||
public bool HasReadAccess(string userName, string path, IPEndPoint clientEndPoint)
|
||||
{
|
||||
return Contains(ReadAccess, userName);
|
||||
return HasAccess(userName, path, FileAccess.Read, clientEndPoint);
|
||||
}
|
||||
|
||||
public bool HasWriteAccess(string userName)
|
||||
public bool HasWriteAccess(string userName, string path, IPEndPoint clientEndPoint)
|
||||
{
|
||||
return Contains(WriteAccess, userName);
|
||||
return HasAccess(userName, path, FileAccess.Write, clientEndPoint);
|
||||
}
|
||||
|
||||
public static bool Contains(List<string> list, string value)
|
||||
public bool HasAccess(string userName, string path, FileAccess requestedAccess, IPEndPoint clientEndPoint)
|
||||
{
|
||||
return (IndexOf(list, value) >= 0);
|
||||
// To be thread-safe we must capture the delegate reference first
|
||||
EventHandler<AccessRequestArgs> handler = OnAccessRequest;
|
||||
if (handler != null)
|
||||
{
|
||||
AccessRequestArgs args = new AccessRequestArgs(userName, path, requestedAccess, clientEndPoint);
|
||||
handler(this, args);
|
||||
return args.Allow;
|
||||
}
|
||||
|
||||
public static int IndexOf(List<string> list, string value)
|
||||
{
|
||||
for (int index = 0; index < list.Count; index++)
|
||||
{
|
||||
if (string.Equals(list[index], value, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public string Name
|
||||
|
|
|
@ -13,11 +13,9 @@ namespace SMBLibrary.Server
|
|||
{
|
||||
public class ShareCollection : List<FileSystemShare>
|
||||
{
|
||||
public void Add(string shareName, List<string> readAccess, List<string> writeAccess, IFileSystem fileSystem)
|
||||
public void Add(string shareName, IFileSystem fileSystem)
|
||||
{
|
||||
FileSystemShare share = new FileSystemShare(shareName, fileSystem);
|
||||
share.ReadAccess = readAccess;
|
||||
share.WriteAccess = writeAccess;
|
||||
this.Add(share);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,23 @@ namespace SMBServer
|
|||
List<string> readAccess = ReadAccessList(readAccessNode, allUsers);
|
||||
XmlNode writeAccessNode = shareNode.SelectSingleNode("WriteAccess");
|
||||
List<string> writeAccess = ReadAccessList(writeAccessNode, allUsers);
|
||||
shares.Add(shareName, readAccess, writeAccess, new DirectoryFileSystem(sharePath));
|
||||
FileSystemShare share = new FileSystemShare(shareName, new DirectoryFileSystem(sharePath));
|
||||
share.OnAccessRequest += delegate(object sender, AccessRequestArgs args)
|
||||
{
|
||||
if (args.RequestedAccess == FileAccess.Read)
|
||||
{
|
||||
args.Allow = Contains(readAccess, args.UserName);
|
||||
}
|
||||
else if (args.RequestedAccess == FileAccess.Write)
|
||||
{
|
||||
args.Allow = Contains(writeAccess, args.UserName);
|
||||
}
|
||||
else // FileAccess.ReadWrite
|
||||
{
|
||||
args.Allow = Contains(readAccess, args.UserName) && Contains(writeAccess, args.UserName);
|
||||
}
|
||||
};
|
||||
shares.Add(share);
|
||||
}
|
||||
return shares;
|
||||
}
|
||||
|
@ -207,13 +223,6 @@ namespace SMBServer
|
|||
}
|
||||
}
|
||||
|
||||
private static XmlDocument GetXmlDocument(string path)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(path);
|
||||
return doc;
|
||||
}
|
||||
|
||||
private void Server_OnLogEntry(object sender, LogEntry entry)
|
||||
{
|
||||
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ");
|
||||
|
@ -236,5 +245,29 @@ namespace SMBServer
|
|||
chkSMB1.Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static XmlDocument GetXmlDocument(string path)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(path);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static bool Contains(List<string> list, string value)
|
||||
{
|
||||
return (IndexOf(list, value) >= 0);
|
||||
}
|
||||
|
||||
public static int IndexOf(List<string> list, string value)
|
||||
{
|
||||
for (int index = 0; index < list.Count; index++)
|
||||
{
|
||||
if (string.Equals(list[index], value, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue