diff --git a/SMBLibrary/NTFileStore/Adapter/NTFileSystemAdapter.cs b/SMBLibrary/NTFileStore/Adapter/NTFileSystemAdapter.cs index 90c0bc2..fd82cc1 100644 --- a/SMBLibrary/NTFileStore/Adapter/NTFileSystemAdapter.cs +++ b/SMBLibrary/NTFileStore/Adapter/NTFileSystemAdapter.cs @@ -25,7 +25,7 @@ namespace SMBLibrary m_fileSystem = fileSystem; } - public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions) + public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext) { handle = null; fileStatus = FileStatus.FILE_DOES_NOT_EXIST; diff --git a/SMBLibrary/NTFileStore/INTFileStore.cs b/SMBLibrary/NTFileStore/INTFileStore.cs index 9f4b3a1..dc3a7e6 100644 --- a/SMBLibrary/NTFileStore/INTFileStore.cs +++ b/SMBLibrary/NTFileStore/INTFileStore.cs @@ -16,7 +16,7 @@ namespace SMBLibrary /// public interface INTFileStore { - NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions); + NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext); NTStatus CloseFile(object handle); diff --git a/SMBLibrary/NTFileStore/NTFileStoreHelper.cs b/SMBLibrary/NTFileStore/NTFileStoreHelper.cs index 9b6ddc3..fbbf4ba 100644 --- a/SMBLibrary/NTFileStore/NTFileStoreHelper.cs +++ b/SMBLibrary/NTFileStore/NTFileStoreHelper.cs @@ -99,11 +99,11 @@ namespace SMBLibrary return result; } - public static FileNetworkOpenInformation GetNetworkOpenInformation(INTFileStore fileStore, string path) + public static FileNetworkOpenInformation GetNetworkOpenInformation(INTFileStore fileStore, string path, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { return null; diff --git a/SMBLibrary/NTFileStore/NamedPipeStore.cs b/SMBLibrary/NTFileStore/NamedPipeStore.cs index d0922c1..5020db9 100644 --- a/SMBLibrary/NTFileStore/NamedPipeStore.cs +++ b/SMBLibrary/NTFileStore/NamedPipeStore.cs @@ -22,7 +22,7 @@ namespace SMBLibrary m_services = services; } - public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions) + public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext) { fileStatus = FileStatus.FILE_DOES_NOT_EXIST; // It is possible to have a named pipe that does not use RPC (e.g. MS-WSP), diff --git a/SMBLibrary/SMBLibrary.csproj b/SMBLibrary/SMBLibrary.csproj index d6ba0d1..6956ffc 100644 --- a/SMBLibrary/SMBLibrary.csproj +++ b/SMBLibrary/SMBLibrary.csproj @@ -176,6 +176,7 @@ + diff --git a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs b/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs index 55708e5..ecf21a8 100644 --- a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs +++ b/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs @@ -52,20 +52,20 @@ namespace SMBLibrary.Server return null; } - public SMB1Session CreateSession(ushort userID, string userName) + public SMB1Session CreateSession(ushort userID, string userName, string machineName) { - SMB1Session session = new SMB1Session(this, userID, userName); + SMB1Session session = new SMB1Session(this, userID, userName, machineName); m_sessions.Add(userID, session); return session; } /// null if all UserID values have already been allocated - public SMB1Session CreateSession(string userName) + public SMB1Session CreateSession(string userName, string machineName) { ushort? userID = AllocateUserID(); if (userID.HasValue) { - return CreateSession(userID.Value, userName); + return CreateSession(userID.Value, userName, machineName); } return null; } diff --git a/SMBLibrary/Server/ConnectionState/SMB1Session.cs b/SMBLibrary/Server/ConnectionState/SMB1Session.cs index 67df3ed..2d8e96b 100644 --- a/SMBLibrary/Server/ConnectionState/SMB1Session.cs +++ b/SMBLibrary/Server/ConnectionState/SMB1Session.cs @@ -17,7 +17,7 @@ namespace SMBLibrary.Server private SMB1ConnectionState m_connection; private ushort m_userID; - private string m_userName; + private SecurityContext m_securityContext; // Key is TID private Dictionary m_connectedTrees = new Dictionary(); @@ -29,11 +29,11 @@ namespace SMBLibrary.Server private Dictionary m_openSearches = new Dictionary(); private ushort m_nextSearchHandle = 1; - public SMB1Session(SMB1ConnectionState connection, ushort userID, string userName) + public SMB1Session(SMB1ConnectionState connection, ushort userID, string userName, string machineName) { m_connection = connection; m_userID = userID; - m_userName = userName; + m_securityContext = new SecurityContext(userName, machineName, connection.ClientEndPoint); } public ushort? AddConnectedTree(ISMBShare share) @@ -141,11 +141,19 @@ namespace SMBLibrary.Server } } + public SecurityContext SecurityContext + { + get + { + return m_securityContext; + } + } + public string UserName { get { - return m_userName; + return m_securityContext.UserName; } } } diff --git a/SMBLibrary/Server/ConnectionState/SMB2ConnectionState.cs b/SMBLibrary/Server/ConnectionState/SMB2ConnectionState.cs index 69901bd..0cc4f64 100644 --- a/SMBLibrary/Server/ConnectionState/SMB2ConnectionState.cs +++ b/SMBLibrary/Server/ConnectionState/SMB2ConnectionState.cs @@ -44,9 +44,9 @@ namespace SMBLibrary.Server return null; } - public SMB2Session CreateSession(ulong sessionID, string userName) + public SMB2Session CreateSession(ulong sessionID, string userName, string machineName) { - SMB2Session session = new SMB2Session(this, sessionID, userName); + SMB2Session session = new SMB2Session(this, sessionID, userName, machineName); m_sessions.Add(sessionID, session); return session; } diff --git a/SMBLibrary/Server/ConnectionState/SMB2Session.cs b/SMBLibrary/Server/ConnectionState/SMB2Session.cs index a97abb5..a0be205 100644 --- a/SMBLibrary/Server/ConnectionState/SMB2Session.cs +++ b/SMBLibrary/Server/ConnectionState/SMB2Session.cs @@ -16,7 +16,7 @@ namespace SMBLibrary.Server { private SMB2ConnectionState m_connection; private ulong m_sessionID; - private string m_userName; + private SecurityContext m_securityContext; // Key is TreeID private Dictionary m_connectedTrees = new Dictionary(); @@ -28,11 +28,11 @@ namespace SMBLibrary.Server // Key is the persistent portion of the FileID private Dictionary m_openSearches = new Dictionary(); - public SMB2Session(SMB2ConnectionState connecton, ulong sessionID, string userName) + public SMB2Session(SMB2ConnectionState connecton, ulong sessionID, string userName, string machineName) { m_connection = connecton; m_sessionID = sessionID; - m_userName = userName; + m_securityContext = new SecurityContext(userName, machineName, connecton.ClientEndPoint); } private uint? AllocateTreeID() @@ -138,11 +138,19 @@ namespace SMBLibrary.Server m_openSearches.Remove(fileID); } + public SecurityContext SecurityContext + { + get + { + return m_securityContext; + } + } + public string UserName { get { - return m_userName; + return m_securityContext.UserName; } } } diff --git a/SMBLibrary/Server/ConnectionState/SecurityContext.cs b/SMBLibrary/Server/ConnectionState/SecurityContext.cs new file mode 100644 index 0000000..cc1d17a --- /dev/null +++ b/SMBLibrary/Server/ConnectionState/SecurityContext.cs @@ -0,0 +1,50 @@ +/* Copyright (C) 2017 Tal Aloni . All rights reserved. + * + * You can redistribute this program and/or modify it under the terms of + * the GNU Lesser Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + */ +using System; +using System.Collections.Generic; +using System.Net; + +namespace SMBLibrary +{ + public class SecurityContext + { + private string m_userName; + private string m_machineName; + private IPEndPoint m_clientEndPoint; + + public SecurityContext(string userName, string machineName, IPEndPoint clientEndPoint) + { + m_userName = userName; + m_machineName = machineName; + m_clientEndPoint = clientEndPoint; + } + + public string UserName + { + get + { + return m_userName; + } + } + + public string MachineName + { + get + { + return m_machineName; + } + } + + public IPEndPoint ClientEndPoint + { + get + { + return m_clientEndPoint; + } + } + } +} diff --git a/SMBLibrary/Server/SMB1/FileStoreResponseHelper.cs b/SMBLibrary/Server/SMB1/FileStoreResponseHelper.cs index d35d266..7541ae8 100644 --- a/SMBLibrary/Server/SMB1/FileStoreResponseHelper.cs +++ b/SMBLibrary/Server/SMB1/FileStoreResponseHelper.cs @@ -20,14 +20,14 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.DirectoryName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.DirectoryName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } } - header.Status = SMB1FileStoreHelper.CreateDirectory(share.FileStore, request.DirectoryName); + header.Status = SMB1FileStoreHelper.CreateDirectory(share.FileStore, request.DirectoryName, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -41,14 +41,14 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.DirectoryName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.DirectoryName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } } - header.Status = SMB1FileStoreHelper.DeleteDirectory(share.FileStore, request.DirectoryName); + header.Status = SMB1FileStoreHelper.DeleteDirectory(share.FileStore, request.DirectoryName, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -61,7 +61,7 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.FileName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.FileName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -69,7 +69,7 @@ namespace SMBLibrary.Server.SMB1 } // [MS-CIFS] This command cannot delete directories or volumes. - header.Status = SMB1FileStoreHelper.DeleteFile(share.FileStore, request.FileName); + header.Status = SMB1FileStoreHelper.DeleteFile(share.FileStore, request.FileName, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -82,19 +82,19 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.OldFileName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.OldFileName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.NewFileName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.NewFileName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } } - header.Status = SMB1FileStoreHelper.Rename(share.FileStore, request.OldFileName, request.NewFileName, request.SearchAttributes); + header.Status = SMB1FileStoreHelper.Rename(share.FileStore, request.OldFileName, request.NewFileName, request.SearchAttributes, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -107,14 +107,14 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, request.DirectoryName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, request.DirectoryName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } } - header.Status = SMB1FileStoreHelper.CheckDirectory(share.FileStore, request.DirectoryName); + header.Status = SMB1FileStoreHelper.CheckDirectory(share.FileStore, request.DirectoryName, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -128,7 +128,7 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, request.FileName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, request.FileName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -136,7 +136,7 @@ namespace SMBLibrary.Server.SMB1 } FileNetworkOpenInformation fileInfo; - header.Status = SMB1FileStoreHelper.QueryInformation(out fileInfo, share.FileStore, request.FileName); + header.Status = SMB1FileStoreHelper.QueryInformation(out fileInfo, share.FileStore, request.FileName, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -154,14 +154,14 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, request.FileName, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, request.FileName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); } } - header.Status = SMB1FileStoreHelper.SetInformation(share.FileStore, request.FileName, request.FileAttributes, request.LastWriteTime); + header.Status = SMB1FileStoreHelper.SetInformation(share.FileStore, request.FileName, request.FileAttributes, request.LastWriteTime, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); @@ -182,7 +182,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); diff --git a/SMBLibrary/Server/SMB1/NTCreateHelper.cs b/SMBLibrary/Server/SMB1/NTCreateHelper.cs index 336ade0..f4bd729 100644 --- a/SMBLibrary/Server/SMB1/NTCreateHelper.cs +++ b/SMBLibrary/Server/SMB1/NTCreateHelper.cs @@ -24,7 +24,7 @@ namespace SMBLibrary.Server.SMB1 FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasAccess(session.UserName, path, createAccess, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -33,7 +33,7 @@ namespace SMBLibrary.Server.SMB1 object handle; FileStatus fileStatus; - NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions); + NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext); if (createStatus != NTStatus.STATUS_SUCCESS) { header.Status = createStatus; diff --git a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs b/SMBLibrary/Server/SMB1/OpenAndXHelper.cs index 104bbce..51d7093 100644 --- a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs +++ b/SMBLibrary/Server/SMB1/OpenAndXHelper.cs @@ -41,7 +41,7 @@ namespace SMBLibrary.Server.SMB1 FileAccess fileAccess = ToFileAccess(request.AccessMode.AccessMode); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasAccess(session.UserName, path, fileAccess, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, fileAccess)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -50,7 +50,7 @@ namespace SMBLibrary.Server.SMB1 object handle; FileStatus fileStatus; - header.Status = share.FileStore.CreateFile(out handle, out fileStatus, path, desiredAccess, shareAccess, createDisposition, createOptions); + header.Status = share.FileStore.CreateFile(out handle, out fileStatus, path, desiredAccess, shareAccess, createDisposition, createOptions, session.SecurityContext); if (header.Status != NTStatus.STATUS_SUCCESS) { return new ErrorResponse(request.CommandName); diff --git a/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs b/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs index cd8a6fc..28cb614 100644 --- a/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs +++ b/SMBLibrary/Server/SMB1/ReadWriteResponseHelper.cs @@ -29,7 +29,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -61,7 +61,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -102,7 +102,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); @@ -132,7 +132,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); diff --git a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.Query.cs b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.Query.cs index a961a91..8e501a8 100644 --- a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.Query.cs +++ b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.Query.cs @@ -14,11 +14,11 @@ namespace SMBLibrary.Server.SMB1 { public partial class SMB1FileStoreHelper { - public static NTStatus GetFileInformation(out QueryInformation result, INTFileStore fileStore, string path, QueryInformationLevel informationLevel) + public static NTStatus GetFileInformation(out QueryInformation result, INTFileStore fileStore, string path, QueryInformationLevel informationLevel, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { result = null; diff --git a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.QueryDirectory.cs b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.QueryDirectory.cs index f89aa4d..d5b9712 100644 --- a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.QueryDirectory.cs +++ b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.QueryDirectory.cs @@ -22,7 +22,7 @@ namespace SMBLibrary.Server.SMB1 // '\Directory\exefile"*' (cmd.exe will use this syntax when entering an exe without its extension, explorer will use this opening a directory from the run menu) /// The filename pattern to search for. This field MAY contain wildcard characters /// - public static NTStatus QueryDirectory(out List result, INTFileStore fileStore, string fileNamePattern, FileInformationClass fileInformation) + public static NTStatus QueryDirectory(out List result, INTFileStore fileStore, string fileNamePattern, FileInformationClass fileInformation, SecurityContext securityContext) { int separatorIndex = fileNamePattern.LastIndexOf('\\'); if (separatorIndex >= 0) @@ -31,7 +31,7 @@ namespace SMBLibrary.Server.SMB1 string fileName = fileNamePattern.Substring(separatorIndex + 1); object handle; FileStatus fileStatus; - NTStatus createStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.FILE_LIST_DIRECTORY | DirectoryAccessMask.FILE_TRAVERSE, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE); + NTStatus createStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.FILE_LIST_DIRECTORY | DirectoryAccessMask.FILE_TRAVERSE, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, securityContext); if (createStatus != NTStatus.STATUS_SUCCESS) { result = null; diff --git a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.cs b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.cs index 8b3edcf..58fe08c 100644 --- a/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.cs +++ b/SMBLibrary/Server/SMB1/SMB1FileStoreHelper.cs @@ -14,11 +14,11 @@ namespace SMBLibrary.Server.SMB1 { public partial class SMB1FileStoreHelper { - public static NTStatus CreateDirectory(INTFileStore fileStore, string path) + public static NTStatus CreateDirectory(INTFileStore fileStore, string path, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus createStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.FILE_ADD_SUBDIRECTORY, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_CREATE, CreateOptions.FILE_DIRECTORY_FILE); + NTStatus createStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.FILE_ADD_SUBDIRECTORY, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_CREATE, CreateOptions.FILE_DIRECTORY_FILE, securityContext); if (createStatus != NTStatus.STATUS_SUCCESS) { return createStatus; @@ -27,21 +27,21 @@ namespace SMBLibrary.Server.SMB1 return createStatus; } - public static NTStatus DeleteDirectory(INTFileStore fileStore, string path) + public static NTStatus DeleteDirectory(INTFileStore fileStore, string path, SecurityContext securityContext) { - return Delete(fileStore, path, CreateOptions.FILE_DIRECTORY_FILE); + return Delete(fileStore, path, CreateOptions.FILE_DIRECTORY_FILE, securityContext); } - public static NTStatus DeleteFile(INTFileStore fileStore, string path) + public static NTStatus DeleteFile(INTFileStore fileStore, string path, SecurityContext securityContext) { - return Delete(fileStore, path, CreateOptions.FILE_NON_DIRECTORY_FILE); + return Delete(fileStore, path, CreateOptions.FILE_NON_DIRECTORY_FILE, securityContext); } - public static NTStatus Delete(INTFileStore fileStore, string path, CreateOptions createOptions) + public static NTStatus Delete(INTFileStore fileStore, string path, CreateOptions createOptions, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.DELETE, 0, CreateDisposition.FILE_OPEN, createOptions); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, DirectoryAccessMask.DELETE, 0, CreateDisposition.FILE_OPEN, createOptions, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { return openStatus; @@ -57,7 +57,7 @@ namespace SMBLibrary.Server.SMB1 return closeStatus; } - public static NTStatus Rename(INTFileStore fileStore, string oldName, string newName, SMBFileAttributes searchAttributes) + public static NTStatus Rename(INTFileStore fileStore, string oldName, string newName, SMBFileAttributes searchAttributes, SecurityContext securityContext) { object handle; FileStatus fileStatus; @@ -70,7 +70,7 @@ namespace SMBLibrary.Server.SMB1 { createOptions = CreateOptions.FILE_DIRECTORY_FILE; } - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, oldName, DirectoryAccessMask.DELETE, 0, CreateDisposition.FILE_OPEN, createOptions); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, oldName, DirectoryAccessMask.DELETE, 0, CreateDisposition.FILE_OPEN, createOptions, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { return openStatus; @@ -87,11 +87,11 @@ namespace SMBLibrary.Server.SMB1 return closeStatus; } - public static NTStatus CheckDirectory(INTFileStore fileStore, string path) + public static NTStatus CheckDirectory(INTFileStore fileStore, string path, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, (AccessMask)0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, (AccessMask)0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { return openStatus; @@ -101,11 +101,11 @@ namespace SMBLibrary.Server.SMB1 return NTStatus.STATUS_SUCCESS; } - public static NTStatus QueryInformation(out FileNetworkOpenInformation fileInfo, INTFileStore fileStore, string path) + public static NTStatus QueryInformation(out FileNetworkOpenInformation fileInfo, INTFileStore fileStore, string path, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_READ_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { fileInfo = null; @@ -116,11 +116,11 @@ namespace SMBLibrary.Server.SMB1 return NTStatus.STATUS_SUCCESS; } - public static NTStatus SetInformation(INTFileStore fileStore, string path, SMBFileAttributes fileAttributes, DateTime? lastWriteTime) + public static NTStatus SetInformation(INTFileStore fileStore, string path, SMBFileAttributes fileAttributes, DateTime? lastWriteTime, SecurityContext securityContext) { object handle; FileStatus fileStatus; - NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_WRITE_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0); + NTStatus openStatus = fileStore.CreateFile(out handle, out fileStatus, path, FileAccessMask.FILE_WRITE_ATTRIBUTES, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, securityContext); if (openStatus != NTStatus.STATUS_SUCCESS) { return openStatus; diff --git a/SMBLibrary/Server/SMB1/SessionSetupHelper.cs b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs index 9fd6f1a..b359c56 100644 --- a/SMBLibrary/Server/SMB1/SessionSetupHelper.cs +++ b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs @@ -40,7 +40,7 @@ namespace SMBLibrary.Server.SMB1 if (loginSuccess) { state.LogToServer(Severity.Information, "User '{0}' authenticated successfully", message.UserName); - SMB1Session session = state.CreateSession(message.UserName); + SMB1Session session = state.CreateSession(message.UserName, message.WorkStation); if (session == null) { header.Status = NTStatus.STATUS_TOO_MANY_SESSIONS; @@ -52,7 +52,7 @@ namespace SMBLibrary.Server.SMB1 else if (users.FallbackToGuest(message.UserName)) { state.LogToServer(Severity.Information, "User '{0}' failed authentication. logged in as guest", message.UserName); - SMB1Session session = state.CreateSession("Guest"); + SMB1Session session = state.CreateSession("Guest", message.WorkStation); if (session == null) { header.Status = NTStatus.STATUS_TOO_MANY_SESSIONS; @@ -145,12 +145,12 @@ namespace SMBLibrary.Server.SMB1 if (loginSuccess) { state.LogToServer(Severity.Information, "User '{0}' authenticated successfully", authenticateMessage.UserName); - state.CreateSession(header.UID, authenticateMessage.UserName); + state.CreateSession(header.UID, authenticateMessage.UserName, authenticateMessage.WorkStation); } else if (users.FallbackToGuest(authenticateMessage.UserName)) { state.LogToServer(Severity.Information, "User '{0}' failed authentication. logged in as guest", authenticateMessage.UserName); - state.CreateSession(header.UID, "Guest"); + state.CreateSession(header.UID, "Guest", authenticateMessage.WorkStation); response.Action = SessionSetupAction.SetupGuest; } else diff --git a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs index ff3af4c..79668d9 100644 --- a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs +++ b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs @@ -32,7 +32,7 @@ namespace SMBLibrary.Server.SMB1 return null; } - NTStatus searchStatus = SMB1FileStoreHelper.QueryDirectory(out entries, share.FileStore, fileNamePattern, informationClass); + NTStatus searchStatus = SMB1FileStoreHelper.QueryDirectory(out entries, share.FileStore, fileNamePattern, informationClass, session.SecurityContext); if (searchStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "FindFirst2: Searched for '{0}', NTStatus: {1}", fileNamePattern, searchStatus.ToString()); @@ -120,7 +120,7 @@ namespace SMBLibrary.Server.SMB1 SMB1Session session = state.GetSession(header.UID); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return null; @@ -146,7 +146,7 @@ namespace SMBLibrary.Server.SMB1 string path = subcommand.FileName; if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return null; @@ -178,7 +178,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return null; @@ -210,7 +210,7 @@ namespace SMBLibrary.Server.SMB1 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return null; diff --git a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs index 4209181..2cef329 100644 --- a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs +++ b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs @@ -36,7 +36,7 @@ namespace SMBLibrary.Server.SMB1 return new ErrorResponse(request.CommandName); } - if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return new ErrorResponse(request.CommandName); diff --git a/SMBLibrary/Server/SMB2/CreateHelper.cs b/SMBLibrary/Server/SMB2/CreateHelper.cs index a45d869..713e9a6 100644 --- a/SMBLibrary/Server/SMB2/CreateHelper.cs +++ b/SMBLibrary/Server/SMB2/CreateHelper.cs @@ -26,7 +26,7 @@ namespace SMBLibrary.Server.SMB2 FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition); if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasAccess(session.UserName, path, createAccess, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess)) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } @@ -34,7 +34,7 @@ namespace SMBLibrary.Server.SMB2 object handle; FileStatus fileStatus; - NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions); + NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext); 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 34abf68..8e1eb0a 100644 --- a/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs +++ b/SMBLibrary/Server/SMB2/QueryDirectoryHelper.cs @@ -23,7 +23,7 @@ namespace SMBLibrary.Server.SMB2 return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED); } - if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } diff --git a/SMBLibrary/Server/SMB2/QueryInfoHelper.cs b/SMBLibrary/Server/SMB2/QueryInfoHelper.cs index c6927cb..8a9279d 100644 --- a/SMBLibrary/Server/SMB2/QueryInfoHelper.cs +++ b/SMBLibrary/Server/SMB2/QueryInfoHelper.cs @@ -27,7 +27,7 @@ namespace SMBLibrary.Server.SMB2 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } @@ -49,7 +49,7 @@ namespace SMBLibrary.Server.SMB2 { if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasReadAccess(session.UserName, @"\", state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } diff --git a/SMBLibrary/Server/SMB2/SessionSetupHelper.cs b/SMBLibrary/Server/SMB2/SessionSetupHelper.cs index 39880cd..25712ba 100644 --- a/SMBLibrary/Server/SMB2/SessionSetupHelper.cs +++ b/SMBLibrary/Server/SMB2/SessionSetupHelper.cs @@ -76,12 +76,12 @@ namespace SMBLibrary.Server.SMB2 if (loginSuccess) { state.LogToServer(Severity.Information, "User '{0}' authenticated successfully", authenticateMessage.UserName); - state.CreateSession(request.Header.SessionID, authenticateMessage.UserName); + state.CreateSession(request.Header.SessionID, authenticateMessage.UserName, authenticateMessage.WorkStation); } else if (users.FallbackToGuest(authenticateMessage.UserName)) { state.LogToServer(Severity.Information, "User '{0}' failed authentication. logged in as guest", authenticateMessage.UserName); - state.CreateSession(request.Header.SessionID, "Guest"); + state.CreateSession(request.Header.SessionID, "Guest", authenticateMessage.WorkStation); response.SessionFlags = SessionFlags.IsGuest; } else diff --git a/SMBLibrary/Server/SMB2/SetInfoHelper.cs b/SMBLibrary/Server/SMB2/SetInfoHelper.cs index c1a1ba7..02ffb3c 100644 --- a/SMBLibrary/Server/SMB2/SetInfoHelper.cs +++ b/SMBLibrary/Server/SMB2/SetInfoHelper.cs @@ -27,7 +27,7 @@ namespace SMBLibrary.Server.SMB2 if (share is FileSystemShare) { - if (!((FileSystemShare)share).HasWriteAccess(session.UserName, openFile.Path, state.ClientEndPoint)) + if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } diff --git a/SMBLibrary/Server/SMB2/TreeConnectHelper.cs b/SMBLibrary/Server/SMB2/TreeConnectHelper.cs index 3763b48..1fdfe95 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, @"\", state.ClientEndPoint)) + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED); } diff --git a/SMBLibrary/Server/Shares/FileSystemShare.cs b/SMBLibrary/Server/Shares/FileSystemShare.cs index 1791b38..d6ac136 100644 --- a/SMBLibrary/Server/Shares/FileSystemShare.cs +++ b/SMBLibrary/Server/Shares/FileSystemShare.cs @@ -18,14 +18,16 @@ namespace SMBLibrary.Server public string UserName; public string Path; public FileAccess RequestedAccess; + public string MachineName; public IPEndPoint ClientEndPoint; public bool Allow = true; - public AccessRequestArgs(string userName, string path, FileAccess requestedAccess, IPEndPoint clientEndPoint) + public AccessRequestArgs(string userName, string path, FileAccess requestedAccess, string machineName, IPEndPoint clientEndPoint) { UserName = userName; Path = path; RequestedAccess = requestedAccess; + MachineName = machineName; ClientEndPoint = clientEndPoint; } } @@ -49,23 +51,23 @@ namespace SMBLibrary.Server m_fileSystem = new NTFileSystemAdapter(fileSystem); } - public bool HasReadAccess(string userName, string path, IPEndPoint clientEndPoint) + public bool HasReadAccess(SecurityContext securityContext, string path) { - return HasAccess(userName, path, FileAccess.Read, clientEndPoint); + return HasAccess(securityContext, path, FileAccess.Read); } - public bool HasWriteAccess(string userName, string path, IPEndPoint clientEndPoint) + public bool HasWriteAccess(SecurityContext securityContext, string path) { - return HasAccess(userName, path, FileAccess.Write, clientEndPoint); + return HasAccess(securityContext, path, FileAccess.Write); } - public bool HasAccess(string userName, string path, FileAccess requestedAccess, IPEndPoint clientEndPoint) + public bool HasAccess(SecurityContext securityContext, string path, FileAccess requestedAccess) { // To be thread-safe we must capture the delegate reference first EventHandler handler = OnAccessRequest; if (handler != null) { - AccessRequestArgs args = new AccessRequestArgs(userName, path, requestedAccess, clientEndPoint); + AccessRequestArgs args = new AccessRequestArgs(securityContext.UserName, path, requestedAccess, securityContext.MachineName, securityContext.ClientEndPoint); handler(this, args); return args.Allow; }