A project for work required me to interact with a Windows File Share. I had other constraints as well that made this a little more difficult. I needed to be cross-platform compatible (run on both Windows and Linux) and I couldn’t use the SMB1 protocol due to security vulnerabilities. Here are my findings and a basic implementation of how I interact with Windows File Shares with Dot Net Core.
What is SMB and What is Wrong with SMB1?
SMB or Server Message Block is a protocol dating back to 1983 and created by IBM to create network file shares on DOS systems. Microsoft got involved and merged it with other products of theirs for better integration. Microsoft has continued to evolve it over the years and has a new standard that was introduced in 2006.
Recently there have been some growing concerns about security issues with the SMB protocol version 1, relating to denial of service attacks and remote code execution. This caused Microsoft to put the SMB 1 protocol on the depreciated list for Windows Server 2012, and it is disabled in Windows Server 2016 by default.
Cross-Platform and Why not mount the share on Unix Systems?
The key benefit of using Dot Net Core is that apps can run on a variety of hosts, not just Linux or Windows. This allows the user to install and run on their preferred system. In my case, we have customers that run our application on-site and we use Linux for our cloud infrastructure. You should minimize any branching based on the platform, if at all possible.
With Unix systems such as Linux, to work with Windows file shares typically you would mount them as drives and they work like a directory would. I find this method hard to work with for a few reasons. The main reason I dislike mounting shares for Linux systems is that you have to have elevated permissions to mount the drive, which may not always be possible, especially in the case of Docker containers.
I tried a couple of different libraries and finally settled on SMBLibrary, available here https://github.com/TalAloni/SMBLibrary. This library was the only one I could find with Windows File Share Access using SMB version 2 protocol. You need to create a connection then access the file in blocks of 65536 bytes. This is a known limit of early implementations of the protocol.
The client implements Idisposable so we can use the c# using statement to set the connection and authentication up. See the example below for a sample client. While this implementation is not perfect it is the first time I have attempted to implement IDisposable.
Then we have a service that we pass a DTO into the method to retrieve a file from the share and display the contents. In the example below, we access the file in blocks and add them together, before we finally read out the byte array.
I have a full repository on GitHub implementing everything discussed in this post, available here: https://github.com/rebelweb/DotNetCoreFileShare. In part 2 we will look at writing files to the share.