[SSHD-886] Do not send SSH_MSG_UNIMPLEMENTED reply if registered ReservedSessionMessa...
authorLyor Goldstein <lgoldstein@apache.org>
Fri, 1 Feb 2019 16:54:33 +0000 (18:54 +0200)
committerLyor Goldstein <lgoldstein@apache.org>
Fri, 1 Feb 2019 17:30:38 +0000 (19:30 +0200)
CHANGES.md
README.md
sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java
sshd-core/src/main/java/org/apache/sshd/common/session/ReservedSessionMessagesHandler.java
sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
sshd-core/src/main/java/org/apache/sshd/common/session/helpers/ReservedSessionMessagesHandlerAdapter.java
sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java

index b5a3abe..c1a02e4 100644 (file)
@@ -168,6 +168,9 @@ for exposing the cipher's block size. **Note:** for the time being we declare a
 implement `AttributeStore` interface - which means that `SftpEventListener`(s) can now attach user-defined attributes
 to the generated handle(s).
 
+* [SSHD-886](https://issues.apache.org/jira/browse/SSHD-886) - Do not send `SSH_MSG_UNIMPLEMENTED` reply if registered
+`ReservedSessionMessagesHandler` signals that it has handled the unknown packet type.
+
 * `SftpCommandMain` shows by default `get/put` command progress using the hash sign (`#`) marker. The marker
 can be enabled/disabled via the `progress` command:
 
index ee5045f..c5237a3 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1637,6 +1637,22 @@ message received in the session as well.
 
 ```java
 
+    class MyClientSideReservedSessionMessagesHandler implements ReservedSessionMessagesHandler {
+        @Override
+        public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+            switch(cmd) {
+                case MY_SPECIAL_CMD1:
+                    ....
+                    return true;
+                case MY_SPECIAL_CMD2:
+                    ....
+                    return true;
+                default:
+                    return false;    // send SSH_MSG_UNIMPLEMENTED reply if necessary
+            }
+        }
+    }
+
     // client side
     SshClient client = SshClient.setupDefaultClient();
     // This is the default for ALL sessions unless specifically overridden
index fa56044..b72aa4b 100644 (file)
@@ -34,5 +34,4 @@ public interface IoWriteFuture extends SshFuture<IoWriteFuture>, VerifiableFutur
      * between the two.
      */
     Throwable getException();
-
 }
index c7c6012..48ab970 100644 (file)
@@ -60,10 +60,12 @@ public interface ReservedSessionMessagesHandler extends SshdEventListener {
      * @param session The {@code Session} through which the message was received
      * @param cmd The received (un-implemented) command
      * @param buffer The {@code Buffer} containing the data - positioned just beyond the command
+     * @return {@code true} if message handled internally, {@code false} if should
+     * return a {@code SSH_MSG_UNIMPLEMENTED} reply (default behavior)
      * @throws Exception If failed to handle the message
      * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-11.4">RFC 4253 - section 11.4</A>
      */
-    default void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
-        // ignored
+    default boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+        return false;
     }
 }
index f16a881..e582039 100644 (file)
@@ -1368,13 +1368,18 @@ public abstract class AbstractSession extends SessionHelper {
      * @param cmd The un-implemented command value
      * @param buffer The {@link Buffer} that contains the command. <b>Note:</b> the
      * buffer's read position is just beyond the command.
-     * @return An {@link IoWriteFuture} that can be used to wait for packet write completion
+     * @return An {@link IoWriteFuture} that can be used to wait for packet write
+     * completion - {@code null} if the registered {@link ReservedSessionMessagesHandler}
+     * decided to handle the command internally
      * @throws Exception if an error occurred while handling the packet.
      * @see #sendNotImplemented(long)
      */
     protected IoWriteFuture notImplemented(int cmd, Buffer buffer) throws Exception {
         ReservedSessionMessagesHandler handler = resolveReservedSessionMessagesHandler();
-        handler.handleUnimplementedMessage(this, cmd, buffer);
+        if (handler.handleUnimplementedMessage(this, cmd, buffer)) {
+            return null;
+        }
+
         return sendNotImplemented(seqi - 1L);
     }
 
index 6abd4b3..b88717a 100644 (file)
@@ -61,7 +61,9 @@ public class ReservedSessionMessagesHandlerAdapter
         handleDebugMessage(session, buffer.getBoolean(), buffer.getString(), buffer.getString(), buffer);
     }
 
-    public void handleDebugMessage(Session session, boolean display, String msg, String lang, Buffer buffer) throws Exception {
+    public void handleDebugMessage(
+            Session session, boolean display, String msg, String lang, Buffer buffer)
+                throws Exception {
         if (log.isDebugEnabled()) {
             log.debug("handleDebugMessage({}) SSH_MSG_DEBUG (display={}) [lang={}] '{}'",
                       session, display, lang, msg);
@@ -69,7 +71,7 @@ public class ReservedSessionMessagesHandlerAdapter
     }
 
     @Override
-    public void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+    public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
         boolean debugEnabled = log.isDebugEnabled();
         if (debugEnabled) {
             if (cmd == SshConstants.SSH_MSG_UNIMPLEMENTED) {
@@ -79,5 +81,7 @@ public class ReservedSessionMessagesHandlerAdapter
                 log.debug("handleUnimplementedMessage({}): {}", session, SshConstants.getCommandMessageName(cmd));
             }
         }
+
+        return false;
     }
 }
index 22eb511..770dca8 100644 (file)
@@ -203,8 +203,9 @@ public class AbstractSessionTest extends BaseTestSupport {
     public void testMalformedUnimplementedMessage() throws Exception {
         session.setReservedSessionMessagesHandler(new ReservedSessionMessagesHandler() {
             @Override
-            public void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+            public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
                 fail("Unexpected invocation: available=" + buffer.available());
+                return false;
             }
         });