Open maltris opened 2 months ago
The mod_sftp
module only renames the files on close, not on open.
To better understand what's happening at the protocol level, I would need to see the SFTPLog
generated by the sshfs-using client machine, to see the order of specific SFTP requests being used.
2024-09-18 14:22:54,907 mod_sftp/1.1.1[797854]: user 'myuser' authenticated via 'password' method
2024-09-18 14:22:55,151 mod_sftp/1.1.1[797854]: 'env' channel request: 'LANG' = 'de_DE.UTF-8'
2024-09-18 14:22:55,151 mod_sftp/1.1.1[797854]: 'subsystem' channel request for 'sftp' subsystem
2024-09-18 14:22:55,151 mod_sftp/1.1.1[797854]: using SFTP protocol version 3 for this session (channel ID 0)
2024-09-18 14:24:03,849 mod_sftp/1.1.1[797854]: client sent GLOBAL_REQUEST for 'keepalive@openssh.com', denying
2024-09-18 14:24:21,926 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile' for LSTAT: No such file or directory
2024-09-18 14:24:21,952 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile' for LSTAT: No such file or directory
2024-09-18 14:24:36,998 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile2' for LSTAT: No such file or directory
2024-09-18 14:24:37,022 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile2' for LSTAT: No such file or directory
2024-09-18 14:25:57,467 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile3' for LSTAT: No such file or directory
2024-09-18 14:25:57,491 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile3' for LSTAT: No such file or directory
2024-09-18 14:25:57,516 mod_sftp/1.1.1[797854]: error checking '/test/mytestfile3' for LSTAT: No such file or directory
Thats what I get in the normal SFTPLog.
[00116] LSTAT
[00116] STATUS 38bytes (276ms)
[00117] OPEN
[00118] LSTAT
[00117] HANDLE 29bytes (26ms)
[00118] STATUS 38bytes (26ms)
[00119] CLOSE
[00120] LSTAT
[00119] STATUS 28bytes (26ms)
[00120] ATTRS 45bytes (26ms)
[00121] SETSTAT
[00121] STATUS 28bytes (23ms)
[00122] LSTAT
[00122] ATTRS 45bytes (24ms)
[00123] LSTAT
[00123] STATUS 38bytes (25ms)
[00124] OPEN
[00125] LSTAT
[00124] HANDLE 29bytes (23ms)
[00125] STATUS 38bytes (23ms)
[00126] CLOSE
[00126] STATUS 28bytes (27ms)
[00127] LSTAT
[00127] STATUS 38bytes (26ms)
[00128] LSTAT
[00128] STATUS 38bytes (23ms)
[00129] OPEN
[00130] LSTAT
[00129] HANDLE 29bytes (24ms)
[00130] STATUS 38bytes (24ms)
[00131] CLOSE
[00131] STATUS 28bytes (26ms)
This is what I get from the sshfs debug log. (The attempts from above mytestfile1-3 separated by a few newlines.)
I did another test with an editor (nano) opening the file on the sshfs:
2024-09-18 14:34:41,647 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:41,694 mod_sftp/1.1.1[797854]: error checking '/test/.test2.swp' for LSTAT: No such file or directory
2024-09-18 14:34:41,717 mod_sftp/1.1.1[797854]: error checking '/test/.test2.swp' for LSTAT: No such file or directory
2024-09-18 14:34:41,741 mod_sftp/1.1.1[797854]: error checking '/test/.test2.swp' for LSTAT: No such file or directory
2024-09-18 14:34:41,765 mod_sftp/1.1.1[797854]: error checking '/test/.test2.swp' for LSTAT: No such file or directory
2024-09-18 14:34:41,813 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:41,836 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:41,858 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,442 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,467 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,492 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,516 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,539 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
2024-09-18 14:34:46,567 mod_sftp/1.1.1[797854]: error checking '/test/test2' for LSTAT: No such file or directory
[00142] LSTAT
[00142] STATUS 38bytes (25ms)
[00143] LSTAT
[00143] ATTRS 45bytes (22ms)
[00144] LSTAT
[00144] STATUS 38bytes (23ms)
[00145] LSTAT
[00145] STATUS 38bytes (22ms)
[00146] LSTAT
[00146] STATUS 38bytes (22ms)
[00147] OPEN
[00148] LSTAT
[00147] HANDLE 29bytes (23ms)
[00148] STATUS 38bytes (23ms)
[00149] CLOSE
[00150] LSTAT
[00149] STATUS 28bytes (24ms)
[00150] ATTRS 45bytes (24ms)
[00151] LSTAT
[00151] STATUS 38bytes (22ms)
[00152] LSTAT
[00152] STATUS 38bytes (22ms)
[00153] LSTAT
[00153] STATUS 38bytes (22ms)
[00154] LSTAT
[00154] STATUS 38bytes (25ms)
[00155] LSTAT
[00155] STATUS 38bytes (25ms)
[00156] LSTAT
[00156] STATUS 38bytes (23ms)
[00157] LSTAT
[00157] STATUS 38bytes (22ms)
[00158] LSTAT
[00158] STATUS 38bytes (23ms)
[00159] OPEN
[00160] LSTAT
[00159] HANDLE 29bytes (27ms)
[00160] STATUS 38bytes (27ms)
[00161] CLOSE
[00161] STATUS 28bytes (24ms)
Hmm. Could you also enable trace logging, for more detailed logging of the underlying protocol requests?
TraceLog /path/to/proftpd-trace.log
Trace ssh2:30 sftp:30
I'm hoping to see the exact sequence of protocol-level interactions with these files. Thanks!
@Castaglia To not leak any information accidentially, because the trace is very verbose, I sent the trace to you via mail just in this moment.
Thanks for the trace logging. I understand the issue now.
When mod_sftp receives the OPEN
SFTP request to create a file, and if HiddenStores are enabled, then the actual path created on the filesystem will be the temporary filename -- not the name as requested by the client. Only when the final CLOSE
SFTP request is received, for that file, will mod_sftp rename the temporary file atomically to the requested filename. This is how HiddenStores is intended to work.
But your SFTP client (sshfs, in this case) is sending LSTAT
requests, with the requested filename, during this file transfer. Hence why those LSTAT
requests are properly receiving the "no such file or directory" response -- as that requested filename doesn't exist yet, not until the CLOSE
.
The simplest approach would be to not use the HiddenStores directives for your SFTP clients. Or perhaps to create two different SFTP <VirtualHost>
sections, differentiated by DNS name or port, so that you point your sshfs clients at the <VirtualHost>
configuration that does not enable HiddenStores, while all other SFTP clients use the <VirtualHost>
that does enable HiddenStores.
Ideally the sshfs client would be using FSTAT
SFTP requests, not LSTAT
requests. FSTAT
uses the file handle as returned to the client for its OPEN
requests; it is effectively the file descriptor, and thus can be used to obtain the desired information regardless of the filesystem path.
Highly interesting!
HiddenStores as of now cannot be disabled with SFTPClientMatch if I understood correctly, so the only solution would be a separate instance or vhost?
Is there any other way to control it?
I will try to ask the sshfs community as well if there could be any compatibility mode for this.
Currently HiddenStores cannot be enabled/disabled based on SFTPClientMatch, correct.
Another possibility might be to use mod_ifsession's <IfUser>
, <IfGroup>
, <IfClass>
sections to enable/disable HiddenStores based on the user/group used by the sshfs client, or perhaps the network class. That, in addition to the possibility of using separate <VirtualHost>
sections.
What I Did
I try to use HiddenStores with mod_sftp but some clients use sshfs.
What I Expected/Wanted
I expect nothing, but I am curious how to prevent "No such file or directory" situations where applications like file editors or simple writes to a new file try to create a file, then open it for writing but the then-opened file (the hidden version with .in) does not exist because right after creation it had been renamed by proftpd.
In my understanding there is no protocol way to lock the file in the hidden position until it had really been written on sshfs. But is there any other way? Or is it possible to disable HiddenStores ONLY for the sshfs clients (they send the normal OpenSSH client identifier).
I have read about writeback_cache in libfuse/sshfs, but it is not available currently:
https://github.com/search?q=repo%3Alibfuse%2Fsshfs+writeback_cache&type=commits
Any ideas?
ProFTPD Version and Configuration
Please help us reproduce the problem/issue you are encountering. To do this, we need to know which version of ProFTPD you are using, how it was built, etc. The following command is an easy way to get all of this information:
In addition, we need to see all of the ProFTPD configuration files you are using (minus any sensitive information like passwords, of course). Armed with the version and configuration data, then, we can set up ProFTPD locally using the same configuration, and see what happens.