Right response to an SFTP "open" on non-existing file
protocols, sftp, ssh
Solution
Reply to the `SSH_FXP_OPEN` request also with a `SSH_FX_NO_SUCH_FILE` status code. That should solve the problem with `psftp`.
Anyway, you have to keep a register of the active file and directory handles. When the remote side request an operation for a handle that is not active or that is not of the right type, respond with a `SSH_FX_FAILURE` status message. Use the `error message` slot on the `SSH_FXP_STATUS` packet to include a more informative and user friendly error as just the code is not very useful.
Problem
I'm writing custom filesystem classes for Apache SSHd. I've hit an issue when the client tries to `get` a file that doesn't exist. My object returns `doesExist() == false`. This causes the server to send an SSH_FX_NO_SUCH_FILE packet in response to a SSH_FXP_STAT. Using an the OpenSSH client, this works fine : the client reports "File '/foo' not found". However, PSFTP (the Putty SFTP client) pipelines its requests, so it sends an OPEN packet regardless of the response to STAT. It then sends a READ on the resulting filehandle, which currently causes an exception in my code, which results in the whole session terminating. What should the server response be when there is an attempt to read a file which does not exist? With apologies for verbosity, here's the Apache code in question. I'd prefer not to modify it -- my class is the SshFile "file" here. But if the Apache code is definitely buggy, I guess I'll have to give them a patch. ``` if (version <= 4) { String path = buffer.getString(); int pflags = buffer.getInt(); // attrs try { SshFile file = resolveFile(path); if (file.doesExist()) { if (((pflags & SSH_FXF_CREAT) != 0) && ((pflags & SSH_FXF_EXCL) != 0)) { sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, path); return; } } else { if (((pflags & SSH_FXF_CREAT) != 0)) { if (!file.isWritable()) { sendStatus(id, SSH_FX_FAILURE, "Can not create " + path); return; } file.create(); } } String acc = ((pflags & (SSH_FXF_READ | SSH_FXF_WRITE)) != 0 ? "r" : "") + ((pflags & SSH_FXF_WRITE) != 0 ? "w" : ""); if ((pflags & SSH_FXF_TRUNC) != 0) { file.truncate(); } String handle = UUID.randomUUID().toString(); handles.put(handle, new FileHandle(file, pflags)); // handle flags conversion sendHandle(id, handle); } catch (IOException e) { sendStatus(id, SSH_FX_FAILURE, e.getMessage()); } ```