[ 
https://issues.apache.org/jira/browse/SSHD-785?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16256844#comment-16256844
 ] 

Antti S. Lankila commented on SSHD-785:
---------------------------------------

Thanks for the quick fix.

Since you asked, I needed something like SFTP share that was backed by a web 
service that was written as the counterpart of the SFTP server. The idea was 
that users could upload files using the WWW interface, or equivalently, would 
see a specific directory structure and could perform equivalent functions by 
e.g. uploading reports and downloading feedback files. One of the goals was, as 
these files are highly sensitive, was to avoid storing them anywhere on the 
frontend machine that performs the SFTP work.

I did not originally know that SFTP is kind of POSIX file operations on top of 
TCP/IP as concept. I did not yet realize that I could have used the SFTP 
protocol implementation as it was, and just supply my own FileSystemProvider 
and FileSystem implementations. What happened was, I looked into the code, saw 
it using Paths and stuff and figured it's so tightly married to the concept of 
physical files that I have to rewrite the protocol handler itself to lift this 
limitation. So, basically, doing this was a SNAFU that I could have avoided had 
I realized that java's FileSystems are in fact totally abstract and can do 
anything.

That being said, writing your own FilesystemProvider + Filesystem looks like it 
would have been a pretty significant task as well. For another project, I have 
a similar need but in that case I decided to back the SFTP directory tree 
exposed to clients with a true physical filesystem. To support dynamism that I 
needed, I used couple of those event listeners provided for SFTP. E.g. when a 
new client logs in, I create the directory hierarchy populated with certain 
0-byte files that correspond to data sources available, and then trap attempts 
to open these files for reading so that I can quickly materialize them for the 
client before I allow the client to actually open that file. Similarly, when 
client performs write, I check that it's in the upload area of the system, and 
then I allow the writes to proceed unaltered, but I have trapped the close, and 
will immediately process the file when client closes it.

The upside of the first approach was that apart from doing redundant work, e.g. 
reimplementing the parts of SFTPv3 which clients generally emit, it granted me 
exact control over everything, and I did not have to really understand how MINA 
SSHD is put together. The upside of the second approach is that it only has a 
little bit of code required, as it is a kind of hybrid approach. Especially 
providing POSIX operations seems like a PITA. Maybe at some point in future I 
will revisit all of this nonsense, once I've figured out what the best way to 
do these kind of SFTP file APIs is. More realistically, though, I'm 

> ChannelPipedInputStream attempts to read from client even for 0-byte reads.
> ---------------------------------------------------------------------------
>
>                 Key: SSHD-785
>                 URL: https://issues.apache.org/jira/browse/SSHD-785
>             Project: MINA SSHD
>          Issue Type: Bug
>    Affects Versions: 1.6.0
>            Reporter: Antti S. Lankila
>            Assignee: Goldstein Lyor
>            Priority: Minor
>             Fix For: 1.7.0
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> I ran into interoperability issue between my own implementation of SFTP 
> protocol (don't even ask) and JSch. The interaction between the client and 
> server hangs on JSch attempting to issue REALPATH command for the empty 
> string. This is method called getHome(), and it is used to handle resolving 
> relative paths on the client side. The specifics why it does this are not 
> important; the bug I ran into affects the situations where any ssh command 
> packet contains the empty string.
> Using the REALPATH "" as example, the data for this command is just 4 zero 
> bytes (length of string as 32-bit integer), and no string data.
> My code attempted to create the 0-byte string based on the length value, and 
> basically executed this:
>     byte[] buffer = new byte[0];
>     in.read(buffer);
> The javadocs for InputStream says that if the length fo the passed byte[] 
> buffer is 0, then the implementation just returns 0 and doesn't attempt to 
> read anything. Unfortunately, ChannelPipedInputStream has its own 
> implementation of read(byte[], int, int), and seems to attempt to read 
> something from client before not actually using the data and returning 0. 
> Client and server deadlock here: client waits for server reply, server waits 
> for more data from client. Eventually, JSch timeouts, and closes the 
> connection. What happens is that this 0 byte read then succeeds, server 
> attempts to write back the FX_NAME response, but client has already closed 
> connection, and the server gets an exception. In my case, this takes about 8 
> minutes to happen, which corresponds to some default timeout in JSch.
> The fix would be to detect the attempt to read 0 bytes in 
> ChannelPipedInputStream and just return early, similar to how 
> java.io.InputStream does read(byte[], int, int). This bug should be fixed 
> because this would align CPIS's implementation with the documentation and 
> general behavior of java's InputStreams.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to