This is an automated email from the ASF dual-hosted git repository. lgoldstein pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit 0dc159ab3bbac86ccd99a370c87518b9ea98866b Author: Lyor Goldstein <lgoldst...@apache.org> AuthorDate: Fri Feb 26 10:44:31 2021 +0200 [SSHD-1133] Added capability to specify a custom charset for parsing incoming commands to the ScpShell --- CHANGES.md | 3 +++ docs/scp.md | 13 +++++++++++++ .../main/java/org/apache/sshd/scp/ScpModuleProperties.java | 13 ++++++++++--- .../src/main/java/org/apache/sshd/scp/server/ScpShell.java | 5 +++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6e44df8..6de775d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,8 @@ * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Re-factored locations and names of `ServerSession` and server-side `ChannelSession` related classes +## Potential compatibility issues + ## Minor code helpers * [SSHD-525](https://issues.apache.org/jira/browse/SSHD-525) Added support for SFTP **client-side** ["posix-ren...@openssh.com" @@ -43,3 +45,4 @@ * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added capability for interactive key based authentication participation via UserInteraction * [SSHD-1125](https://issues.apache.org/jira/browse/SSHD-1125) Added mechanism to throttle pending write requests in BufferedIoOutputStream * [SSHD-1127](https://issues.apache.org/jira/browse/SSHD-1127) Added capability to register a custom receiver for SFTP STDERR channel raw or stream data +* [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Added capability to specify a custom charset for parsing incoming commands to the `ScpShell` \ No newline at end of file diff --git a/docs/scp.md b/docs/scp.md index d7274b1..06364c1 100644 --- a/docs/scp.md +++ b/docs/scp.md @@ -191,6 +191,19 @@ sshd.setShellFactory(factory); **Note:** a similar result can be achieved if activating SSHD from the command line by specifying `-o ShellFactory=scp` +### Text encoding/decoding + +The SCP "shell" is text-based and therefore subject to character encoding/decoding of the data being exchanged. By default, the exchange is supposed to use the UTF-8 encoding which is the default/standard one for SSH. However, there are clients/servers "in the wild" that do not conform to this convention. For this purpose, it is possible to define a different character encoding via the `SHELL_NAME_EN/DECODING_CHARSET` properties - e.g.: + +```java +SshServer sshd = ...setup server... +// Can also use the character name string rather than the object instance itself +ScpModuleProperties.SHELL_NAME_ENCODING_CHARSET.set(sshd, Charset.forName("US-ASCII")); +ScpModuleProperties.SHELL_NAME_DECODING_CHARSET.set(sshd, Charset.forName("US-ASCII")); +``` + +**Caveat emptor:** that the code does not enforce "symmetry" of the chosen character sets - in other words, user can either by design or error cause different encoding to be used for the incoming commands vs. the outgoing responses. It is important to bear in mind that if the text to be encoded/decoded contains characters that cannot be safely handled by the chosen encoder/decoder than the result might not be correctly parsed/understood by the peer. + ## Remote-to-remote transfer The code provides an `ScpTransferHelper` class that enables copying files between 2 remote accounts without going through diff --git a/sshd-scp/src/main/java/org/apache/sshd/scp/ScpModuleProperties.java b/sshd-scp/src/main/java/org/apache/sshd/scp/ScpModuleProperties.java index 4821f34..4bdae9a 100644 --- a/sshd-scp/src/main/java/org/apache/sshd/scp/ScpModuleProperties.java +++ b/sshd-scp/src/main/java/org/apache/sshd/scp/ScpModuleProperties.java @@ -53,12 +53,19 @@ public final class ScpModuleProperties { = Property.bool("scp-auto-sync-on-write", true); /** - * Used to indicate the {@link Charset} (or its name) for encoding referenced files/folders names - extracted from - * the client channel session when 1st initialized. + * Used to indicate the {@link Charset} (or its name) for encoding returned textual responses from the + * {@code ScpShell} - extracted from the channel session when shell initialized. */ - public static final Property<Charset> NAME_ENCODING_CHARSET + public static final Property<Charset> SHELL_NAME_ENCODING_CHARSET = Property.charset("scp-shell-name-encoding-charset", StandardCharsets.UTF_8); + /** + * Used to indicate the {@link Charset} (or its name) for decoding incoming commands to be processed by the + * {@code ScpShell} - extracted from the channel session when shell initialized. + */ + public static final Property<Charset> SHELL_NAME_DECODING_CHARSET + = Property.charset("scp-shell-name-decoding-charset", StandardCharsets.UTF_8); + private ScpModuleProperties() { throw new UnsupportedOperationException("No instance"); } diff --git a/sshd-scp/src/main/java/org/apache/sshd/scp/server/ScpShell.java b/sshd-scp/src/main/java/org/apache/sshd/scp/server/ScpShell.java index ca413be..af31fbc 100644 --- a/sshd-scp/src/main/java/org/apache/sshd/scp/server/ScpShell.java +++ b/sshd-scp/src/main/java/org/apache/sshd/scp/server/ScpShell.java @@ -106,7 +106,7 @@ public class ScpShell extends AbstractFileSystemCommand implements ServerChannel super(null, executorService); this.channelSession = Objects.requireNonNull(channelSession, "No channel session provided"); - nameEncodingCharset = ScpModuleProperties.NAME_ENCODING_CHARSET.getRequired(channelSession); + nameEncodingCharset = ScpModuleProperties.SHELL_NAME_ENCODING_CHARSET.getRequired(channelSession); if (sendSize < ScpHelper.MIN_SEND_BUFFER_SIZE) { throw new IllegalArgumentException( @@ -185,9 +185,10 @@ public class ScpShell extends AbstractFileSystemCommand implements ServerChannel prepareEnvironment(getEnvironment()); + Charset decodingCharset = ScpModuleProperties.SHELL_NAME_DECODING_CHARSET.getRequired(channel); // Use a special stream reader so that the stream can be used with the scp command try (InputStream inputStream = getInputStream(); - Reader r = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + Reader r = new InputStreamReader(inputStream, decodingCharset)) { for (int executedCommands = 0;; executedCommands++) { command = readLine(r); if (GenericUtils.isEmpty(command)) {