PowerShell / Win32-OpenSSH

Win32 port of OpenSSH
7.31k stars 750 forks source link

Copying files by sftp to junction not possible under Windows 10 when ChrootDirectory is set in sshd_config #1403

Open Erik78De opened 5 years ago

Erik78De commented 5 years ago

When I try to copy files to a symlinked / junctioned folder in Windows 10, I get a file of 0KB size and an error "permission denied". Steps to teproduce:

1.) Install the latest OpenSSH Build for Windows (in my case 1607 LTSB, so I install it manually, by downloading the package from the binaries page on Github) 2.) In the Windows file system, create a folder Symlinks on C:. Also create a folder Temp on C:\ to copy data to later 3.) In the Windows file system, create a Junction like this: mklink /J C:\Symlinks\C C:\ 4.) In the sshd_config, set: ChrootDirectory C:\Symlinks 5.) Access your sftp Server using Winscp, Filezilla or a client of your choice 6.) In the sftp client, navigate to /C/Temp (note: /C is the junction we created in setp 3) 7.) the copy process will fail, creating a file of 0KB size, and a permission denied error.

Additional information: if you do NOT set ChrootDirectory, you will be taken to the Users Homepath by default. If you do so, and navigate to your /C/Symlinks/C/Temp folder, and then try to copy a file, everything works fine. So this seems not to be related to any permission issues in Windows. It is some strange behaviour of OpenSSH in combination with ChrootDirectory and Junctions.

Any idea why this is happening? If you need more information, feel free to ask!

NoMoreFood commented 5 years ago

My guess is this is a limitation of how of the ChrootDirectory code determines where you are on the file system. Are you allowed to simply enumerate the subfolders in the C:\Symlinks directory structure? Does the behavior change if you use an actual symlink (not a junction) or a volume mounted directly to a folder?

Erik78De commented 5 years ago

Yes, I can navigate through the structure, and the behaviour is the same wether I use a junction (mklink /J) or a symlink (mklink /d), I don't know any more possibilities how to do this. Actually, the file even gets created, but with 0KB size.

NoMoreFood commented 5 years ago

I haven't tried it myself, but I suspect that the only way this is going to work is if you mount a volume to a folder within C:\symlinks. To do that, you need to go into the Disk Management area. Of course, that limits you to only being able to "link" to the roots of those volumes.

On Linux, I believe the symlink would only work in a ChrootDirectory if it points to folder already within the Chroot. So if someone would look into addressing this, it would likely just be to disallow the enumeration and the not allow creation of the file at all.

Erik78De commented 5 years ago

Sorry, but isn't that a serious bug that should be fixed by the devs?

NoMoreFood commented 5 years ago

There's definitely a bug at play, but what it is is debatable. Either you should be able to copy the file or you shouldn't be able to navigate the link. If anything gets fixed, it's probably going to be the latter since that's how Linux behaves.

Erik78De commented 5 years ago

My problem is that I want to offer two different partitions from my "server" PC, accessible from one common start point, that's why I made it this way: Creating a symlink-path, and putting a link to the C and the D partition there. I am not aware of the situation in Linux, since it does not have that concept of drive letters at all, but from a Windows user's persspective I want to be able to offer both. Before I used SFTP based on SSH, I had a FTP-based solution using IIS, which worked the same way.

So the question is: why shouldn't a user be allowed to do this? The solution to this bug to me is allowing access to the symbolic linked folders, the same way they work without a ChrootDirectory set at all, which also works...

manojampalam commented 5 years ago

The behavior you are seeing is expected and by design. If symlink is pointed outside of chroot jail, you are not allowed to access that node. I believe this is the same behavior in Unix . If you think otherwise, let us know.

NoMoreFood commented 5 years ago

@Erik78De If they are truly two different partitions, just mount the partition as folders under a single subdirectory and that should work. See here: https://docs.microsoft.com/en-us/windows-server/storage/disk-management/assign-a-mount-point-folder-path-to-a-drive

jjverschoor commented 4 years ago

Hi,

We came across similar sftp symptoms in that..

..when using a /D symlink as chrootdirectory (whilst if we dont use a chrootdirectory and navigate to the symlink manually we can indeed download the files from the referred directory, so NTFS is all ok).

Is this something that the code can be updated for, i.e. to allow for file download when chrootdirectory is a /D symlink? or am I doing something wrong?

Info:

Server log: debug3: auth2_update_methods_lists: updating methods list after "password" [preauth] debug2: authentication methods list 0 complete [preauth] debug3: send packet: type 52 [preauth] debug3: mm_request_send entering: type 26 [preauth] debug3: mm_send_keystate: Finished sending state [preauth] debug3: ReadFileEx() ERROR:109, io:000000CFDD89E110 debug3: read - no more data, io:000000CFDD89E110 debug1: monitor_read_log: child log fd closed

Client log (winscp) 2019-10-22 10:49:41.029 Handling network read event on socket 1536 with error 0 2019-10-22 10:49:41.029 Received 38 bytes (0) 2019-10-22 10:49:41.029 Read 4 bytes (34 pending) 2019-10-22 10:49:41.029 Read 34 bytes (0 pending) 2019-10-22 10:49:41.030 Type: SSH_FXP_STATUS, Size: 34, Number: 21251 2019-10-22 10:49:41.030 65,00,00,53,03,00,00,00,03,00,00,00,11,50,65,72,6D,69,73,73,69,6F,6E,20,64, 2019-10-22 10:49:41.030 65,6E,69,65,64,00,00,00,00, 2019-10-22 10:49:41.030 Status code: 3, Message: 21251, Server: Permission denied, Language:
2019-10-22 10:49:41.030 (ETerminal) Permission denied. 2019-10-22 10:49:41.030 Error code: 3 2019-10-22 10:49:41.030 Error message from server: Permission denied 2019-10-22 10:49:41.030 Asking user: 2019-10-22 10:49:41.030 Cannot open remote file '/xxx/xx/x/xxx.txt'. ("Permission denied. 2019-10-22 10:49:41.030 Error code: 3 2019-10-22 10:49:41.030 Error message from server: Permission denied") 2019-10-22 10:49:41.114 Session upkeep

EDIT1: This seems a known error: line 599 of fileio.c reads:

/ on W2012, ReadFileEx on file throws a synchronous EOF error/ else if ((FILETYPE(pio) == FILE_TYPE_DISK) && (errno == ERROR_HANDLE_EOF)) { debug3("read - no more data, io:%p", pio); errno = 0; return 0;

..which is what invokes this error, but I don't understand why this isn't an issue without a chroot jail .

TimPla commented 4 years ago

We also have the requirement to do the same. Will this be fixed or do we need to found another sftp solution?

jjverschoor commented 4 years ago

Hi TimPla,

I opened a new issue 1493, as this issue 1403 references outside of the chroot, which we actually don't: Rather our chroot is a symlink, and we stay within the chroot. So, in 1493 I provide a temporary workaround that may work for you as well (but please be aware of the security implications mentioned in 1493).

Kind regards, JJ

frankhetterich commented 3 years ago

Hi, any progress on this issue? We´re facing exactly the same problem

pv2b commented 3 years ago

I can also report that I'm getting the same exact issue. The use case in my case was that I wanted to do something like

ChrootDirectory E:\Sftp\Roots\%u

In my configuration, and then just use a hierarchy of directory junctions inside of those SFTP roots to give a "virtual file system" for giving access points into specific parts of the server.

I'm getting the exact same things, I can create directories, delete directories and files, but I cannot upload or download files. It does end up creating an empty file though. So from my point of view, this is broken one way or another. Either it should be impossible to navigate out of the chroot using a junction/symlink, and impossible to do any file operations at all, or it should be possible to do all file operations allowed by ACL.

I also tried a new idea, which was to try to use DFS-N to create this kind of virtual file structure, unfortunately this also does not work because ChrootDirectory does not support UNC paths.

I can also mention this is a fairly common issue to be encountering:

https://superuser.com/questions/1445883/open-ssh-in-windows-10-cannot-copy-files-to-junctions-when-chrootdirectory-is-s https://serverfault.com/questions/967833/issue-hardlink-junction-not-working-when-chroot-all-users-to-c-share-dir-in-win

However, I have identified one possible workaround:

Workaround: Use different users for each folder

Match User contoso\sftp-user1
    ChrootDirectory C:\path\to\stuff
Match User contoso\sftp-user2
    ChrootDirectory D:\path\to\different\stuff
Match User contoso\sftp-user3
    ChrootDirectory E:\completely\different\path\to\other\stuff

And then you ended up creating individual users for every single directory I want to expose. Pretty terrible, but it has the advantage of working.

One way to make this solution more workable is to just have one single user per directory, use only SSH Key authentication, and manage access by adding/removing SSH keys to those specific users. This way you don't have to be creating a ton of Windows users, but it has the major disadvantage of being harder to audit. (Maybe you can make it log which SSH key was used for every connection? I don't know.)

Of course, I'd much rather either have some kind of "virtual directory" support in sftp, where you can define "virtual mount points" for different directories to be exposed, or simply if somehow symlinks/junctions could be made to "just work" in this case.

If this was Linux, I'd just use a bind mount and call it a day, unfortunately, that's not possible on Windows.

ocenteno commented 2 years ago

I think the problem is more that that.

The need is to be able to map multiple folders for the same user, thus the need of the symlink.

As an example, I need a shared folder to be accessible by 2 users (but this will escalate) but each of them need their own jailed content. I tried to put the jailed folder inside the shared one but then each of them can see the folder of the other (not navigate to it) but the mere display at the root is not wanted, it must be fully hidden.

Actual folders:

What user1 shall see:

What user2 shall see:

And it's forbidden that any user sees the folder of any other.

zvekan commented 1 year ago

like many has mentioned. In chrooted directory I have created directory symlinks to different parts of machine. When you login you are able to access and browse structure. You are also able to create/delete/rename directories. But problem is if you try to upload/download files, then you get error

image

This is only reason why I can't start using sftp on windows.

Also would suggest to connect with IIS team to see how to add this as option because I would like to replace FTP/S with SFTP.

NoMoreFood commented 1 year ago

The fact that symlinks do not work inside of a ChrootDirectory is consistent with how OpenSSH works on Linux so I doubt that's going to change. I know it's not as flexible and a little more dangerous, but a hard link may work.

zvekan commented 1 year ago

but it is strange that creating/deleting/renaming folders/files is working in symlinked locations while upload/download files don't work. Shouldn't then even entering/browsing symlink give permission denied? Hard links works on same disk/partition while symlink can point to different disks/partition and even smb locations. But it would be nice to enable upload/download to symlink locations so that we have some flexibility and not that user need to have 10 users because he need access to 10 different locations. I then control what user can with NTFS permissions. Some other sftp servers have similar solution but maybe with virtual folders, and some even have option between system and virtual users. Why not to enable this so that we have good SFTP solution on windows. Maybe option to create some kind of virtual folders with target location under chrootdirectory is better solution. I know that don't exist now but maybe is good feature to implement. I even found this now Simplify your AWS SFTP Structure with chroot and logical directories

DrPepperBianco commented 6 months ago

I still have the same problem. Any update here?