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

Mark Ebbers commented on SSHD-775:
----------------------------------

I did not find any guidelines regarding the 'error message' string part of the 
SSH_FX_STATUS response message and the latest draft RFC only stated the 
following:

{quote}
*9.1.  Status Response*
 error message
      Human readable description of the error.
{quote}

So I did a quick investigation of the source of the latest version of OpenSSH 
and it appears that OpenSSH only returns a small set of error messages.

{code:java}
Openssh-7.2p2/sftp-server.c
status_to_message(u_int32_t status)
{
        const char *status_messages[] = {
                "Success",                      /* SSH_FX_OK */
                "End of file",                  /* SSH_FX_EOF */
                "No such file",                 /* SSH_FX_NO_SUCH_FILE */
                "Permission denied",            /* SSH_FX_PERMISSION_DENIED */
                "Failure",                      /* SSH_FX_FAILURE */
                "Bad message",                  /* SSH_FX_BAD_MESSAGE */
                "No connection",                /* SSH_FX_NO_CONNECTION */
                "Connection lost",              /* SSH_FX_CONNECTION_LOST */
                "Operation unsupported",        /* SSH_FX_OP_UNSUPPORTED */
                "Unknown error"                 /* Others */
        };
        return (status_messages[MIN(status,SSH2_FX_MAX)]);
}

openssh-7.2p2/sftp-common.c
/* Convert from SSH2_FX_ status to text error message */
const char *
fx2txt(int status)
{
        switch (status) {
        case SSH2_FX_OK:
                return("No error");
        case SSH2_FX_EOF:
                return("End of file");
        case SSH2_FX_NO_SUCH_FILE:
                return("No such file or directory");
        case SSH2_FX_PERMISSION_DENIED:
                return("Permission denied");
        case SSH2_FX_FAILURE:
                return("Failure");
        case SSH2_FX_BAD_MESSAGE:
                return("Bad message");
        case SSH2_FX_NO_CONNECTION:
                return("No connection");
        case SSH2_FX_CONNECTION_LOST:
                return("Connection lost");
        case SSH2_FX_OP_UNSUPPORTED:
                return("Operation unsupported");
        default:
                return("Unknown status");
        }
        /* NOTREACHED */
}
{code}

Based on the source of OpenSSH I suggest two possible options:

h3. Option 1
{code:java}
public static String resolveStatusMessage(final Throwable t) {
        if (t == null) {
            return "";
        } else if ((t instanceof NoSuchFileException) || (t instanceof 
FileNotFoundException)) {
            return "No such file or directory";
        } else if (t instanceof InvalidHandleException) {
            return "Invalid handle";
        } else if (t instanceof FileAlreadyExistsException) {
            return "File already exists";
        } else if (t instanceof DirectoryNotEmptyException) {
            return "Directory not empty";
        } else if (t instanceof NotDirectoryException) {
            return "Not a directory";
        } else if (t instanceof AccessDeniedException) {
            return "Permission denied";
        } else if (t instanceof EOFException) {
            return "End of file";
        } else if (t instanceof OverlappingFileLockException) {
            return "Lock conflict";
        } else if (t instanceof UnsupportedOperationException) {
            return "Operation unsupported";
        } else if (t instanceof InvalidPathException) {
            return "Invalid filename";
        } else if (t instanceof IllegalArgumentException) {
            return "Invalid parameter";
        } else if (t instanceof UnsupportedOperationException) {
            return "Operation unsupported";
        } else if (t instanceof UserPrincipalNotFoundException) {
            return "Unknown principal";
        } else if (t instanceof FileSystemLoopException) {
            return "Link loop";
        } else if (t instanceof SftpException) {
            return "Failure";
        }

        return "Unknown error";
    }
{code}

h4. Motivation
* This version is somewhat more verbose and clearer to the client in the case 
something goes wrong than OpenSSH.
* No use of the exception message itself to prevent information leakage. Also 
not needed. For example the NoSuchFileException has a reference to the file 
which could not be found, but the client already knowns which file because it 
initiated the request.
* The SFTPException can be a problem. For example see 
_SftpSubSystem::doRemove(): throw new 
SftpException(SftpConstants.SSH_FX_FILE_IS_A_DIRECTORY, p.toString() + " is a 
folder");_ If this is the case the client will receive a "Failure". However the 
client also received the substatus SSH_FX_FILE_IS_A_DIRECTORY....

h3. Option 2
{code:java}
 private static String resolveSubStatusMessage(int status) {

        switch (status) {
            case SSH_FX_OK:
                return "Success";
            case SSH_FX_EOF:
                return "End of file";
            case SSH_FX_NO_SUCH_FILE:
                return "No such file or directory";
            case SSH_FX_PERMISSION_DENIED:
                return "Permission denied";
            case SSH_FX_FAILURE:
                return "Failure";
            case SSH_FX_OP_UNSUPPORTED:
                return "Operation unsupported";
        }

        return "Unknown error";
    }
{code}

h4. Motivation
* Inline with OpenSSH.
* Based on substatus instead of Throwable.
* Does not make the client smarter then needed.
* One might consider to also use this option to resolve a message for 
_SftpException.getStatus()_.

I go for option 2 in my project. I think the combination of status + substatus 
is already enough information for the client especially with option 2.

h4. Sources
*SFTP RFC draft 13*
* https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13
* 9.1.  Status Response
* 11.  Implementation Considerations
* 13.  Security Considerations

*OpenSSH 7.2p2 source code*
* http://archive.ubuntu.com/ubuntu/pool/main/o/openssh/openssh_7.2p2.orig.tar.gz

> SftpSubSystem::sendStatus leaks Exception information
> -----------------------------------------------------
>
>                 Key: SSHD-775
>                 URL: https://issues.apache.org/jira/browse/SSHD-775
>             Project: MINA SSHD
>          Issue Type: Improvement
>    Affects Versions: 1.6.0
>            Reporter: Mark Ebbers
>            Priority: Minor
>              Labels: security
>
> I'm using SSHD-core 1.6.0 in my own Sftp server implementation and make use 
> of the rooted file-system. Now did I notice that a client did try to rename a 
> file, which was no longer available, and got a response with the substatus 
> SSH_FX_NO_SUCH_FILE and the message ' Internal NoSuchFileException: 
> /srv/sftp/chroot/11738/file.txt'.
> As a client I now know the following two things:
> * The full path on the file-system.
> * The server was written in Java. (NoSuchFileException)
> I noticed that the SftpSubsystem.sendStatus(Buffer, int, Throwable) uses the 
> SftpHelper.resolveStatusMessage() method to create a message string to be 
> send to the client without further checking what information is inside the 
> Exception message. 



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

Reply via email to