diff --git a/SMBLibrary/SMBLibrary.csproj b/SMBLibrary/SMBLibrary.csproj index b8f4888..f7e695e 100644 --- a/SMBLibrary/SMBLibrary.csproj +++ b/SMBLibrary/SMBLibrary.csproj @@ -202,6 +202,7 @@ + diff --git a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs index e67faeb..a32f7c0 100644 --- a/SMBLibrary/Server/SMB1/TreeConnectHelper.cs +++ b/SMBLibrary/Server/SMB1/TreeConnectHelper.cs @@ -31,14 +31,15 @@ namespace SMBLibrary.Server.SMB1 else { share = shares.GetShareFromName(shareName); - serviceName = ServiceName.DiskShare; - supportFlags = OptionalSupportFlags.SMB_SUPPORT_SEARCH_BITS | OptionalSupportFlags.SMB_CSC_CACHE_MANUAL_REINT; if (share == null) { header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND; return new ErrorResponse(request.CommandName); } + serviceName = ServiceName.DiskShare; + supportFlags = OptionalSupportFlags.SMB_SUPPORT_SEARCH_BITS | GetCachingSupportFlags(((FileSystemShare)share).CachingPolicy); + if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { state.LogToServer(Severity.Verbose, "Tree Connect to '{0}' failed. User '{1}' was denied access.", share.Name, session.UserName); @@ -64,6 +65,21 @@ namespace SMBLibrary.Server.SMB1 } } + private static OptionalSupportFlags GetCachingSupportFlags(CachingPolicy cachingPolicy) + { + switch (cachingPolicy) + { + case CachingPolicy.ManualCaching: + return OptionalSupportFlags.SMB_CSC_CACHE_MANUAL_REINT; + case CachingPolicy.AutoCaching: + return OptionalSupportFlags.SMB_CSC_CACHE_AUTO_REINT; + case CachingPolicy.VideoCaching: + return OptionalSupportFlags.SMB_CSC_CACHE_VDO; + default: + return OptionalSupportFlags.SMB_CSC_NO_CACHING; + } + } + private static TreeConnectAndXResponse CreateTreeConnectResponse(ServiceName serviceName, OptionalSupportFlags supportFlags) { TreeConnectAndXResponse response = new TreeConnectAndXResponse(); diff --git a/SMBLibrary/Server/SMB2/TreeConnectHelper.cs b/SMBLibrary/Server/SMB2/TreeConnectHelper.cs index 6b2d79f..4538351 100644 --- a/SMBLibrary/Server/SMB2/TreeConnectHelper.cs +++ b/SMBLibrary/Server/SMB2/TreeConnectHelper.cs @@ -31,13 +31,13 @@ namespace SMBLibrary.Server.SMB2 else { share = shares.GetShareFromName(shareName); - shareType = ShareType.Disk; - shareFlags = ShareFlags.ManualCaching; if (share == null) { return new ErrorResponse(request.CommandName, NTStatus.STATUS_OBJECT_PATH_NOT_FOUND); } + shareType = ShareType.Disk; + shareFlags = GetShareCachingFlags(((FileSystemShare)share).CachingPolicy); if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\")) { state.LogToServer(Severity.Verbose, "Tree Connect to '{0}' failed. User '{1}' was denied access.", share.Name, session.UserName); @@ -62,6 +62,21 @@ namespace SMBLibrary.Server.SMB2 return response; } + private static ShareFlags GetShareCachingFlags(CachingPolicy cachingPolicy) + { + switch (cachingPolicy) + { + case CachingPolicy.ManualCaching: + return ShareFlags.ManualCaching; + case CachingPolicy.AutoCaching: + return ShareFlags.AutoCaching; + case CachingPolicy.VideoCaching: + return ShareFlags.VdoCaching; + default: + return ShareFlags.NoCaching; + } + } + internal static SMB2Command GetTreeDisconnectResponse(TreeDisconnectRequest request, ISMBShare share, SMB2ConnectionState state) { SMB2Session session = state.GetSession(request.Header.SessionID); diff --git a/SMBLibrary/Server/Shares/Enums/CachingPolicy.cs b/SMBLibrary/Server/Shares/Enums/CachingPolicy.cs new file mode 100644 index 0000000..005cf70 --- /dev/null +++ b/SMBLibrary/Server/Shares/Enums/CachingPolicy.cs @@ -0,0 +1,32 @@ + +namespace SMBLibrary.Server +{ + /// + /// Client-Side Caching Policy + /// + public enum CachingPolicy + { + /// + /// The client can cache files that are explicitly selected by the user for offline use. + /// Automatic file-by-file reintegration is not allowed. + /// + ManualCaching, + + /// + /// The client can automatically cache files that are used by the user for offline access. + /// Automatic file-by-file reintegration is allowed. + /// + AutoCaching, + + /// + /// The client can automatically cache files that are used by the user for offline access. + /// Clients are permitted to work from their local cache even while online. + /// + VideoCaching, + + /// + /// No offline caching is allowed for this share. + /// + NoCaching, + } +} diff --git a/SMBLibrary/Server/Shares/FileSystemShare.cs b/SMBLibrary/Server/Shares/FileSystemShare.cs index f141625..d5c3b0f 100644 --- a/SMBLibrary/Server/Shares/FileSystemShare.cs +++ b/SMBLibrary/Server/Shares/FileSystemShare.cs @@ -15,19 +15,26 @@ namespace SMBLibrary.Server { private string m_name; private INTFileStore m_fileSystem; + private CachingPolicy m_cachingPolicy; public event EventHandler AccessRequested; - public FileSystemShare(string shareName, INTFileStore fileSystem) + public FileSystemShare(string shareName, INTFileStore fileSystem) : this(shareName, fileSystem, CachingPolicy.ManualCaching) + { + } + + public FileSystemShare(string shareName, INTFileStore fileSystem, CachingPolicy cachingPolicy) { m_name = shareName; m_fileSystem = fileSystem; + m_cachingPolicy = cachingPolicy; } - public FileSystemShare(string shareName, IFileSystem fileSystem) + public FileSystemShare(string shareName, IFileSystem fileSystem, CachingPolicy cachingPolicy) { m_name = shareName; m_fileSystem = new NTFileSystemAdapter(fileSystem); + m_cachingPolicy = cachingPolicy; } public bool HasReadAccess(SecurityContext securityContext, string path) @@ -68,5 +75,13 @@ namespace SMBLibrary.Server return m_fileSystem; } } + + public CachingPolicy CachingPolicy + { + get + { + return m_cachingPolicy; + } + } } } diff --git a/SMBLibrary/Server/Shares/SMBShareCollection.cs b/SMBLibrary/Server/Shares/SMBShareCollection.cs index 4fa5b9d..cf5498b 100644 --- a/SMBLibrary/Server/Shares/SMBShareCollection.cs +++ b/SMBLibrary/Server/Shares/SMBShareCollection.cs @@ -13,9 +13,9 @@ namespace SMBLibrary.Server { public class SMBShareCollection : List { - public void Add(string shareName, IFileSystem fileSystem) + public void Add(string shareName, IFileSystem fileSystem, CachingPolicy cachingPolicy) { - FileSystemShare share = new FileSystemShare(shareName, fileSystem); + FileSystemShare share = new FileSystemShare(shareName, fileSystem, cachingPolicy); this.Add(share); }