Repository: mina-sshd
Updated Branches:
  refs/heads/master aa14ea40c -> 8c9fe09eb


[SSHD-694] Added documentation regarding global and channel-specific request 
messages


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/8c9fe09e
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/8c9fe09e
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/8c9fe09e

Branch: refs/heads/master
Commit: 8c9fe09eb8a998c804f92196f78f47486333e844
Parents: aa14ea4
Author: Lyor Goldstein <[email protected]>
Authored: Sun Oct 2 10:32:45 2016 +0300
Committer: Lyor Goldstein <[email protected]>
Committed: Sun Oct 2 10:32:45 2016 +0300

----------------------------------------------------------------------
 README.md                                       | 108 ++++++++++++++++++-
 .../org/apache/sshd/common/BaseBuilder.java     |  22 ++--
 .../global/CancelTcpipForwardHandler.java       |   3 +-
 .../sshd/server/global/KeepAliveHandler.java    |   2 +-
 .../sshd/server/global/TcpipForwardHandler.java |   3 +-
 5 files changed, 119 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8c9fe09e/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 94a1bd4..7c1cdf4 100644
--- a/README.md
+++ b/README.md
@@ -589,7 +589,8 @@ The code implements a 
[SOCKS](https://en.wikipedia.org/wiki/SOCKS) proxy for ver
 
 ### Proxy agent
 
-The code provides to some extent an SSH proxy agent via the available 
`SshAgentFactory` implementations.
+The code provides to some extent an SSH proxy agent via the available 
`SshAgentFactory` implementations. As of latest version both [ Secure Shell 
Authentication Agent Protocol Draft 
02](https://tools.ietf.org/html/draft-ietf-secsh-agent-02) and its 
[OpenSSH](https://www.libssh.org/features/) equivalent are supported.
+
 
 # Advanced configuration and interaction
 
@@ -801,12 +802,26 @@ Inform about SCP related events. 
`ScpTransferEventListener`(s) can be registered
 ```
 
 
-### `ReservedSessionMessagesHandler`
+### Reserved messages
+
+The implementation can be used to intercept and process the 
[SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2), 
[SSH_MSG_DEBUG](https://tools.ietf.org/html/rfc4253#section-11.3) and 
[SSH_MSG_UNIMPLEMENTED](https://tools.ietf.org/html/rfc4253#section-11.4) 
messages. The handler can be registered on either side - server
+or client, as well as on the session. A special 
[patch](https://issues.apache.org/jira/browse/SSHD-699) has been introduced
+that automatically ignores such messages if they are malformed - i.e., they 
never reach the handler.
+
+#### SSH message stream "stuffing" and keys re-exchange
 
-The implementation can be used to intercept and process the 
[SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2)
-and [SSH_MSG_DEBUG](https://tools.ietf.org/html/rfc4253#section-11.3) 
messages. The handler can be registered on either side - server
-or client, as well as on the session
+[RFC 4253 - section 9](https://tools.ietf.org/html/rfc4253#section-9) 
recommends re-exchanging keys every once in a while
+based on the amount of traffic and the selected cipher - the matter is further 
clarified in [RFC 4251 - section 
9.3.2](https://tools.ietf.org/html/rfc4251#section-9.3.2). These 
recommendations are mirrored in the code via the `FactoryManager`
+related `REKEY_TIME_LIMIT`, `REKEY_PACKETS_LIMIT` and `REKEY_BLOCKS_LIMIT` 
configuration properties that
+can be used to configure said behavior - please be sure to read the relevant 
_Javadoc_ as well the aforementioned RFC section(s) when
+manipulating them. This behavior can also be controlled programmatically by 
overriding the `AbstractSession#isRekeyRequired()` method.
 
+As an added security mechanism [RFC 4251 - section 
9.3.1](https://tools.ietf.org/html/rfc4251#section-9.3.1) recommends adding
+"spurious" [SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2) 
messages. This functionality is mirrored in the
+`FactoryManager` related `IGNORE_MESSAGE_FREQUENCY`, `IGNORE_MESSAGE_VARIANCE` 
and `IGNORE_MESSAGE_SIZE`
+configuration properties that can be used to configure said behavior - please 
be sure to read the relevant _Javadoc_ as well the aforementioned RFC section 
when manipulating them. This behavior can also be controlled programmatically 
by overriding the `AbstractSession#resolveIgnoreBufferDataLength()` method.
+
+#### `ReservedSessionMessagesHandler`
 
 ```java
 
@@ -857,6 +872,89 @@ rather than being accumulated. However, one can use the 
`EventListenerUtils` and
 `SessionListener` or `ChannelListener` proxies were implemented.
 
 
+### `RequestHandler`(s)
+
+The code supports both [global](https://tools.ietf.org/html/rfc4254#section-4) 
and [channel-specific](https://tools.ietf.org/html/rfc4254#section-5.4) 
requests via the registration of `RequestHandler`(s).
+The global handlers are derived from `ConnectionServiceRequestHandler`(s) 
whereas the channel-specific
+ones are derived from `ChannelRequestHandler`(s). In order to add a handler 
one need only register the correct
+implementation and handle the request when it is detected:
+
+```java
+
+    // NOTE: the following code can be employed on BOTH client and server - 
the example is for the server
+    SshServer server = SshServer.setUpDefaultServer();
+    List<RequestHandler<ConnectionService>> oldGlobals = 
server.getGlobalRequestHandlers();
+    // Create a copy in case current one is null/empty/un-modifiable
+    List<RequestHandler<ConnectionService>> newGlobals = new ArrayList<>();
+    if (GenericUtils.size(oldGlobals) > 0) {
+        newGlobals.addAll(oldGLobals);
+    }
+    newGlobals.add(new MyGlobalRequestHandler());
+    server.setGlobalRequestHandlers(newGlobals);
+    
+    // Similar code can be done with the server's channelRequestHandlers();
+```
+
+The way request handlers are invoked when a global/channel-specific request is 
received  is as follows:
+
+* All currently registered handlers' `process` method is invoked with the 
request type string parameter (among others).
+The implementation should examine the request parameters and decide whether it 
is able to process it.
+
+
+* If the handler returns `Result.Unsupported` then the next registered handler 
is invoked.
+In other words, processing stops at the **first** handler that returned a 
valid response. Thus the importance of
+the `List<RequestHandler<...>>` that defines the **order** in which the 
handlers are invoked. **Note**: while
+it is possible to register multiple handlers for the same request and rely on 
their order, it is highly recommended
+to avoid this situation as it makes debugging the code and diagnosing problems 
much more difficult.
+
+
+* If no handler reported a valid result value then a failure message is sent 
back to the peer. Otherwise, the returned
+result is translated into the appropriate success/failure response (if the 
sender asked for a response). In this context,
+the handler may choose to build and send the response within its own code, in 
which case it should return the
+`Result.Replied` value indicating that it has done so. 
+
+
+```java
+
+    public class MySpecialChannelRequestHandler implements 
ChannelRequestHandler {
+        ...
+        
+        @Override
+        public Result process(Channel channel, String request, boolean 
wantReply, Buffer buffer) throws Exception {
+            if (!"my-special-request".equals(request)) {
+               return Result.Unsupported;   // Not mine - maybe someone else 
can handle it
+            }
+            
+            ...handle the request - can read more parameters from the message 
buffer...
+            
+            return Result.ReplySuccess/Failure/Replied; // signal processing 
result
+        }
+    }
+```
+
+
+#### Default registered handlers
+
+* `exit-signal`, `exit-status` - As described in [RFC4254 section 
6.10](https://tools.ietf.org/html/rfc4254#section-6.10)
+
+
+* `*@putty.projects.tartarus.org` - As described in [Appendix F: SSH-2 names 
specified for 
PuTTY](http://tartarus.org/~simon/putty-snapshots/htmldoc/AppendixF.html)
+
+
+* `[email protected]`, `[email protected]` - As described in 
[OpenSSH protocol - section 
2.5](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL)
+
+
+* `tcpip-forward`, `cancel-tcpip-forward` - As described in [RFC4254 section 
7](https://tools.ietf.org/html/rfc4254#section-7)
+
+
+* `keepalive@*` - Used by many implementations (including this one) to "ping" 
the peer and make sure the connection is still alive.
+In this context, the SSHD code allows the user to configure both the frequency 
and content of the heartbeat request (including whether to send this request at 
all) via the `ClientFactoryManager`-s `HEARTBEAT_INTERVAL`, `HEARTBEAT_REQUEST` 
and `DEFAULT_KEEP_ALIVE_HEARTBEAT_STRING` configuration properties.
+
+
+* `no-more-sessions@*` - As described in [OpenSSH protocol section 
2.2](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL). In this 
context, the code consults the `ServerFactoryManagder.MAX_CONCURRENT_SESSIONS` 
server-side configuration property in order to
+decide whether to accept a successfully authentication session. 
+
+
 # Extension modules
 
 There are several extension modules available

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8c9fe09e/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java 
b/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
index 081db31..fa5a91c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
@@ -182,57 +182,57 @@ public class BaseBuilder<T extends 
AbstractFactoryManager, S extends BaseBuilder
         return me();
     }
 
-    public S signatureFactories(final List<NamedFactory<Signature>> 
signatureFactories) {
+    public S signatureFactories(List<NamedFactory<Signature>> 
signatureFactories) {
         this.signatureFactories = signatureFactories;
         return me();
     }
 
-    public S randomFactory(final Factory<Random> randomFactory) {
+    public S randomFactory(Factory<Random> randomFactory) {
         this.randomFactory = randomFactory;
         return me();
     }
 
-    public S cipherFactories(final List<NamedFactory<Cipher>> cipherFactories) 
{
+    public S cipherFactories(List<NamedFactory<Cipher>> cipherFactories) {
         this.cipherFactories = cipherFactories;
         return me();
     }
 
-    public S compressionFactories(final List<NamedFactory<Compression>> 
compressionFactories) {
+    public S compressionFactories(List<NamedFactory<Compression>> 
compressionFactories) {
         this.compressionFactories = compressionFactories;
         return me();
     }
 
-    public S macFactories(final List<NamedFactory<Mac>> macFactories) {
+    public S macFactories(List<NamedFactory<Mac>> macFactories) {
         this.macFactories = macFactories;
         return me();
     }
 
-    public S channelFactories(final List<NamedFactory<Channel>> 
channelFactories) {
+    public S channelFactories(List<NamedFactory<Channel>> channelFactories) {
         this.channelFactories = channelFactories;
         return me();
     }
 
-    public S fileSystemFactory(final FileSystemFactory fileSystemFactory) {
+    public S fileSystemFactory(FileSystemFactory fileSystemFactory) {
         this.fileSystemFactory = fileSystemFactory;
         return me();
     }
 
-    public S forwardingFilter(final ForwardingFilter filter) {
+    public S forwardingFilter(ForwardingFilter filter) {
         this.forwardingFilter = filter;
         return me();
     }
 
-    public S tcpipForwarderFactory(final TcpipForwarderFactory 
tcpipForwarderFactory) {
+    public S tcpipForwarderFactory(TcpipForwarderFactory 
tcpipForwarderFactory) {
         this.tcpipForwarderFactory = tcpipForwarderFactory;
         return me();
     }
 
-    public S globalRequestHandlers(final 
List<RequestHandler<ConnectionService>> globalRequestHandlers) {
+    public S globalRequestHandlers(List<RequestHandler<ConnectionService>> 
globalRequestHandlers) {
         this.globalRequestHandlers = globalRequestHandlers;
         return me();
     }
 
-    public S factory(final Factory<T> factory) {
+    public S factory(Factory<T> factory) {
         this.factory = factory;
         return me();
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8c9fe09e/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
index 354d678..9d28504 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
@@ -29,9 +29,10 @@ import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.net.SshdSocketAddress;
 
 /**
- * Handler for cancel-tcpip-forward global request.
+ * Handler for &quot;cancel-tcpip-forward&quot; global request.
  *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ * @see <A HREF="https://tools.ietf.org/html/rfc4254#section-7";>RFC4254 
section 7</A>
  */
 public class CancelTcpipForwardHandler extends 
AbstractConnectionServiceRequestHandler {
     public static final String REQUEST = "cancel-tcpip-forward";

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8c9fe09e/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java 
b/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
index 1cfe6b1..6b6ca2c 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
@@ -23,7 +23,7 @@ import 
org.apache.sshd.common.session.helpers.AbstractConnectionServiceRequestHa
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
- * Handler for keepalive@xxx global request.
+ * Handler for &quot;keepalive@xxx&quot; global request.
  *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8c9fe09e/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
index 8b3368e..325b899 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
@@ -29,9 +29,10 @@ import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.net.SshdSocketAddress;
 
 /**
- * Handler for tcpip-forward global request.
+ * Handler for &quot;tcpip-forward&quot; global request.
  *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ * @see <A HREF="https://tools.ietf.org/html/rfc4254#section-7";>RFC4254 
section 7</A>
  */
 public class TcpipForwardHandler extends 
AbstractConnectionServiceRequestHandler {
     public static final String REQUEST = "tcpip-forward";

Reply via email to