I am trying to figure out how to implement Server side listeners for a Java based SFTP server to alert me to an incoming file transfer. I'm using the latest version of Apache Mina. My scenario is for my server to simply receive a file from a client and do "something" to the file before storing it. That something could be error checking / rules validation / forwarding the contents elsewhere. The thing is I want to do that before it is saved on my system. I'm having difficulty with the documentation and can't find a working example that shows a listener implemented with access to the incoming file stream. I have a very simple server taken from a guide:
public void setupServer() throws IOException {
sshd = SshServer.setUpDefaultServer();
sshd.setFileSystemFactory(new NativeFileSystemFactory() {
@Override
public FileSystemView createFileSystemView(final Session session) {
return new NativeFileSystemView(session.getUsername(), false) {
@Override
public String getVirtualUserDir() {
return testFolder.getRoot().getAbsolutePath();
}
};
};
});
sshd.setPort(8001);
sshd.setSubsystemFactories(Arrays
.<NamedFactory<Command>> asList(new SftpSubsystem.Factory()));
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(testFolder
.newFile("hostkey.ser").getAbsolutePath()));
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(final String username, final String password,
final ServerSession session) {
return StringUtils.equals(username, USERNAME)
&& StringUtils.equals(password, PASSWORD);
}
});
// SessionListener event = new SessionListener();
sshd.start();
}
That server is capable of receiving a file and storing it on the virtual file system. I can read the file / verify the contents but only after the file is received and stored. Basic authentication is fine for now, the authentication mechanisms are really well documented thankfully!
So my question is:
or
Thanks in advance! Leigh.
You seem to have an idea that the SFTP is similar protocol to an HTTP. I.e. the client opens a connection with "write" request (like HTTP PUT), sends a file contents of request body, disconnects and that's it.
That's not how the SFTP works.
The SFTP is like a remote file system. The client connects to the SSH/SFTP server and keeps the connection open. During the session, the client sends an "open" file request (with either read or write or both privileges) and gets a handle to the opened file. Then it sends a sequence of read/write-block requests using the file handle. And finally it closes the handle. During a single session, the client can (and typically does) read/write or both any number of files it likes. It can even have several files opened in parallel, accessing them in a completely random order. It is very similar to a way an application works with a local file system.
Implications:
You cannot reject connection when you do not like a file, because the connection request itself is not associated with a specific file. All you can is reject the file "open" (or "create") request.
One way to intercept a file open/create request:
NativeFileSystemView
.NativeSshFile
.NativeFileSystemView.createNativeSshFile
to create your NativeSshFile
NativeFileSystemView.isWritable()
You cannot redirect an SFTP connection. SSH/SFTP does not support connection "redirect" (unlike HTTP)
There's not a single moment where you have a complete file in a memory at once, so that you can inspect it somehow. Instead the client sends the file in chunks. You can of course reimplement the MINA SFTP "input stream" in a way that it keeps the file contents in a memory and inspect a complete contents once you get a "close" request; saving the file to a disk only once you are happy with the file. Beware of DOS attacks though.
A protocol that is more close to what you imagine is the SCP, which also runs over SSH. For it, there's ScpTransferEventListener
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With