diff --git a/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs b/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs index 42c8d79..e76ae3f 100644 --- a/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs +++ b/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs @@ -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; diff --git a/SMBLibrary/Server/SMB1/FileSystemResponseHelper.cs b/SMBLibrary/Server/SMB1/FileSystemResponseHelper.cs index b73b173..e4bdb5b 100644 --- a/SMBLibrary/Server/SMB1/FileSystemResponseHelper.cs +++ b/SMBLibrary/Server/SMB1/FileSystemResponseHelper.cs @@ -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); diff --git a/SMBLibrary/Server/SMB1/NTCreateHelper.cs b/SMBLibrary/Server/SMB1/NTCreateHelper.cs index 0c3606a..2adab81 100644 --- a/SMBLibrary/Server/SMB1/NTCreateHelper.cs +++ b/SMBLibrary/Server/SMB1/NTCreateHelper.cs @@ -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; diff --git a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs b/SMBLibrary/Server/SMB1/OpenAndXHelper.cs index 3b27690..0f95cef 100644 --- a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs +++ b/SMBLibrary/Server/SMB1/OpenAndXHelper.cs @@ -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) diff --git a/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs b/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs index 3b221fc..79a29cb 100644 --- a/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs +++ b/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs @@ -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) diff --git a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs index e9c1819..26d6899 100644 --- a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs +++ b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs @@ -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) { @@ -165,6 +179,12 @@ namespace SMBLibrary.Server.SMB1 header.Status = NTStatus.STATUS_INVALID_HANDLE; 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) { diff --git a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs index fcb329e..eeefb60 100644 --- a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs +++ b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs @@ -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); diff --git a/SMBLibrary/Server/SMB2/CreateHelper.cs b/SMBLibrary/Server/SMB2/CreateHelper.cs index 33df8ab..902614c 100644 --- a/SMBLibrary/Server/SMB2/CreateHelper.cs +++ b/SMBLibrary/Server/SMB2/CreateHelper.cs @@ -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); diff --git a/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs b/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs index 7f8e30f..fe5ca2c 100644 --- a/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs +++ b/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs @@ -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; diff --git a/SMBLibrary/Server/SMB2/QueryInfoHelper.cs b/SMBLibrary/Server/SMB2/QueryInfoHelper.cs index bbd820c..0a3c407 100644 --- a/SMBLibrary/Server/SMB2/QueryInfoHelper.cs +++ b/SMBLibrary/Server/SMB2/QueryInfoHelper.cs @@ -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); diff --git a/SMBLibrary/Server/SMB2/SetInfoHelper.cs b/SMBLibrary/Server/SMB2/SetInfoHelper.cs index 86120ab..0cfd56f 100644 --- a/SMBLibrary/Server/SMB2/SetInfoHelper.cs +++ b/SMBLibrary/Server/SMB2/SetInfoHelper.cs @@ -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) { diff --git a/SMBLibrary/Server/SMB2/TreeConnectHelper.cs b/SMBLibrary/Server/SMB2/TreeConnectHelper.cs index f32d02a..3763b48 100644 --- a/SMBLibrary/Server/SMB2/TreeConnectHelper.cs +++ b/SMBLibrary/Server/SMB2/TreeConnectHelper.cs @@ -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); } diff --git a/SMBLibrary/Server/SMBServer.SMB1.cs b/SMBLibrary/Server/SMBServer.SMB1.cs index 9918d3c..a481ddf 100644 --- a/SMBLibrary/Server/SMBServer.SMB1.cs +++ b/SMBLibrary/Server/SMBServer.SMB1.cs @@ -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); } diff --git a/SMBLibrary/Server/Shares/FileSystemShare.cs b/SMBLibrary/Server/Shares/FileSystemShare.cs index f65473e..aeed6de 100644 --- a/SMBLibrary/Server/Shares/FileSystemShare.cs +++ b/SMBLibrary/Server/Shares/FileSystemShare.cs @@ -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 ReadAccess; - public List WriteAccess; + + public event EventHandler 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 list, string value) + public bool HasAccess(string userName, string path, FileAccess requestedAccess, IPEndPoint clientEndPoint) { - return (IndexOf(list, value) >= 0); - } - - public static int IndexOf(List list, string value) - { - for (int index = 0; index < list.Count; index++) + // To be thread-safe we must capture the delegate reference first + EventHandler handler = OnAccessRequest; + if (handler != null) { - if (string.Equals(list[index], value, StringComparison.InvariantCultureIgnoreCase)) - { - return index; - } + AccessRequestArgs args = new AccessRequestArgs(userName, path, requestedAccess, clientEndPoint); + handler(this, args); + return args.Allow; } - return -1; + return true; } public string Name diff --git a/SMBLibrary/Server/Shares/ShareCollection.cs b/SMBLibrary/Server/Shares/ShareCollection.cs index ac16dd4..ca6beae 100644 --- a/SMBLibrary/Server/Shares/ShareCollection.cs +++ b/SMBLibrary/Server/Shares/ShareCollection.cs @@ -13,11 +13,9 @@ namespace SMBLibrary.Server { public class ShareCollection : List { - public void Add(string shareName, List readAccess, List 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); } diff --git a/SMBServer/ServerUI.cs b/SMBServer/ServerUI.cs index f130d16..25f4632 100644 --- a/SMBServer/ServerUI.cs +++ b/SMBServer/ServerUI.cs @@ -165,7 +165,23 @@ namespace SMBServer List readAccess = ReadAccessList(readAccessNode, allUsers); XmlNode writeAccessNode = shareNode.SelectSingleNode("WriteAccess"); List 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 list, string value) + { + return (IndexOf(list, value) >= 0); + } + + public static int IndexOf(List list, string value) + { + for (int index = 0; index < list.Count; index++) + { + if (string.Equals(list[index], value, StringComparison.InvariantCultureIgnoreCase)) + { + return index; + } + } + return -1; + } } } \ No newline at end of file