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 23d2763f79be6067ee881c761659b85c610ae99e Author: Lyor Goldstein <lgoldst...@apache.org> AuthorDate: Thu Feb 27 11:21:01 2020 +0200 [SSHD-968] Added SessionHelper#preProcessEncodeBuffer --- .../common/session/helpers/AbstractSession.java | 17 ++++++----- .../sshd/common/session/helpers/SessionHelper.java | 33 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java index 4468276..05e6275 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java @@ -1069,15 +1069,18 @@ public abstract class AbstractSession extends SessionHelper { // Check that the packet has some free space for the header int curPos = buffer.rpos(); int cmd = buffer.rawByte(curPos) & 0xFF; // usually the 1st byte is an SSH opcode - if (curPos < SshConstants.SSH_PACKET_HEADER_LEN) { - log.warn("encode({}) command={}[{}] performance cost: available buffer packet header length ({}) below min. required ({})", - this, cmd, SshConstants.getCommandMessageName(cmd), - curPos, SshConstants.SSH_PACKET_HEADER_LEN); - Buffer nb = new ByteArrayBuffer(buffer.available() + Long.SIZE, false); - nb.wpos(SshConstants.SSH_PACKET_HEADER_LEN); - nb.putBuffer(buffer); + Buffer nb = preProcessEncodeBuffer(cmd, buffer); + if (nb != buffer) { buffer = nb; curPos = buffer.rpos(); + + int newCmd = buffer.rawByte(curPos) & 0xFF; + if (cmd != newCmd) { + log.warn("encode({}) - command changed from {}[{}] to {}[{}] by pre-processor", + this, cmd, SshConstants.getCommandMessageName(cmd), + newCmd, SshConstants.getCommandMessageName(newCmd)); + cmd = newCmd; + } } // Grab the length of the packet (excluding the 5 header bytes) diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java index 6003372..8fd2b44 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java @@ -996,9 +996,40 @@ public abstract class SessionHelper extends AbstractKexFactoryManager implements listener.sessionNegotiationEnd(this, c2sOptions, s2cOptions, negotiatedGuess, null); } + /** + * Invoked by the session before encoding the buffer in order to make sure that it is + * at least of size {@link SshConstants#SSH_PACKET_HEADER_LEN SSH_PACKET_HEADER_LEN}. + * This is required in order to efficiently handle the encoding. If necessary, it + * re-allocates a new buffer and returns it instead. + * + * @param cmd The command stored in the buffer + * @param buffer The original {@link Buffer} - assumed to be properly formatted + * and be of at least the required minimum length. + * @return The adjusted {@link Buffer}. <B>Note:</B> users may use this method to + * totally alter the contents of the buffer being sent but it is highly discouraged + * as it may have unexpected results. + * @throws IOException If failed to process the buffer + */ + protected Buffer preProcessEncodeBuffer(int cmd, Buffer buffer) throws IOException { + int curPos = buffer.rpos(); + if (curPos >= SshConstants.SSH_PACKET_HEADER_LEN) { + return buffer; + } + + log.warn("preProcessEncodeBuffer({}) command={}[{}] performance cost:" + + " available buffer packet header length ({}) below min. required ({})", + this, cmd, SshConstants.getCommandMessageName(cmd), + curPos, SshConstants.SSH_PACKET_HEADER_LEN); + Buffer nb = new ByteArrayBuffer(buffer.available() + Long.SIZE, false); + nb.wpos(SshConstants.SSH_PACKET_HEADER_LEN); + nb.putBuffer(buffer); + return nb; + } + @Override public void disconnect(int reason, String msg) throws IOException { - log.info("Disconnecting({}): {} - {}", this, SshConstants.getDisconnectReasonName(reason), msg); + log.info("Disconnecting({}): {} - {}", + this, SshConstants.getDisconnectReasonName(reason), msg); String languageTag = ""; // TODO configure language... signalDisconnect(reason, msg, languageTag, true);