You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/12/17 06:32:18 UTC

mina-sshd git commit: [SSHD-616] Added initial support for OpenSSH "hostkeys-XXX" global requests

Repository: mina-sshd
Updated Branches:
  refs/heads/master 68844229a -> 65ac5ba7c


[SSHD-616] Added initial support for OpenSSH "hostkeys-XXX" global requests


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

Branch: refs/heads/master
Commit: 65ac5ba7c5d8ca3917184e442301323a68f1020b
Parents: 6884422
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Thu Dec 17 07:32:06 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Thu Dec 17 07:32:06 2015 +0200

----------------------------------------------------------------------
 .../org/apache/sshd/agent/local/AgentImpl.java  |   2 +-
 .../org/apache/sshd/client/ClientBuilder.java   |  10 ++
 .../client/auth/pubkey/KeyPairIdentity.java     |   2 +-
 .../client/global/OpenSshHostKeysHandler.java   |  62 ++++++++++
 .../org/apache/sshd/common/SshException.java    |  23 ++--
 .../sshd/common/config/keys/KeyUtils.java       |   2 +-
 .../global/AbstractOpenSshHostKeysHandler.java  |  96 +++++++++++++++
 .../common/keyprovider/KeyPairProvider.java     |   5 +
 .../session/AbstractConnectionService.java      |  22 ++--
 ...AbstractConnectionServiceRequestHandler.java |  44 +++++++
 .../ConnectionServiceRequestHandler.java        |   1 -
 .../apache/sshd/common/util/buffer/Buffer.java  |  76 +++++-------
 .../keys/AbstractBufferPublicKeyParser.java     |  87 +++++++++++++
 .../util/buffer/keys/BufferPublicKeyParser.java | 121 +++++++++++++++++++
 .../buffer/keys/DSSBufferPublicKeyParser.java   |  51 ++++++++
 .../buffer/keys/ECBufferPublicKeyParser.java    |  81 +++++++++++++
 .../keys/ED25519BufferPublicKeyParser.java      |  56 +++++++++
 .../buffer/keys/RSABufferPublicKeyParser.java   |  48 ++++++++
 .../org/apache/sshd/server/ServerBuilder.java   |   4 +-
 .../global/CancelTcpipForwardHandler.java       |  48 ++++----
 .../sshd/server/global/KeepAliveHandler.java    |   8 +-
 .../server/global/NoMoreSessionsHandler.java    |   8 +-
 .../server/global/OpenSshHostKeysHandler.java   | 100 +++++++++++++++
 .../sshd/server/global/TcpipForwardHandler.java |  49 ++++----
 .../org/apache/sshd/server/kex/DHGEXServer.java |   5 +-
 .../org/apache/sshd/server/kex/DHGServer.java   |   5 +-
 26 files changed, 871 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
index cb562a6..3ccb551 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
@@ -91,7 +91,7 @@ public class AgentImpl implements SshAgent {
                 throw new SshException("Unsupported key type: " + pubKey.getClass().getSimpleName());
             }
             verif.initSigner(kp.getPrivate());
-            verif.update(data, 0, data.length);
+            verif.update(data);
             return verif.sign();
         } catch (IOException e) {
             throw e;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
index fe1deca..0129361 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
@@ -26,6 +26,7 @@ import java.util.List;
 import org.apache.sshd.client.config.hosts.DefaultConfigFileHostEntryResolver;
 import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
 import org.apache.sshd.client.config.keys.ClientIdentityLoader;
+import org.apache.sshd.client.global.OpenSshHostKeysHandler;
 import org.apache.sshd.client.kex.DHGClient;
 import org.apache.sshd.client.kex.DHGEXClient;
 import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
@@ -33,9 +34,11 @@ import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
 import org.apache.sshd.common.BaseBuilder;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.channel.Channel;
+import org.apache.sshd.common.channel.RequestHandler;
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
 import org.apache.sshd.common.kex.DHFactory;
 import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.util.Transformer;
 import org.apache.sshd.server.forward.ForwardedTcpipFactory;
 
@@ -59,6 +62,9 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
 
     public static final List<NamedFactory<Channel>> DEFAULT_CHANNEL_FACTORIES =
             Collections.unmodifiableList(Arrays.<NamedFactory<Channel>>asList(ForwardedTcpipFactory.INSTANCE));
+    public static final List<RequestHandler<ConnectionService>> DEFAULT_GLOBAL_REQUEST_HANDLERS =
+            Collections.unmodifiableList(Arrays.<RequestHandler<ConnectionService>>asList(
+                    OpenSshHostKeysHandler.INSTANCE));
 
     public static final ServerKeyVerifier DEFAULT_SERVER_KEY_VERIFIER = AcceptAllServerKeyVerifier.INSTANCE;
     public static final HostConfigEntryResolver DEFAULT_HOST_CONFIG_ENTRY_RESOLVER = DefaultConfigFileHostEntryResolver.INSTANCE;
@@ -106,6 +112,10 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
             channelFactories = DEFAULT_CHANNEL_FACTORIES;
         }
 
+        if (globalRequestHandlers == null) {
+            globalRequestHandlers = DEFAULT_GLOBAL_REQUEST_HANDLERS;
+        }
+
         if (serverKeyVerifier == null) {
             serverKeyVerifier = DEFAULT_SERVER_KEY_VERIFIER;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
index f24b65f..5f3e9e0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
@@ -54,7 +54,7 @@ public class KeyPairIdentity implements PublicKeyIdentity {
                 "No signer could be located for key type=%s",
                 keyType);
         verifier.initSigner(pair.getPrivate());
-        verifier.update(data, 0, data.length);
+        verifier.update(data);
         return verifier.sign();
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/client/global/OpenSshHostKeysHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/global/OpenSshHostKeysHandler.java b/sshd-core/src/main/java/org/apache/sshd/client/global/OpenSshHostKeysHandler.java
new file mode 100644
index 0000000..0e81b0e
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/global/OpenSshHostKeysHandler.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.client.global;
+
+import java.security.PublicKey;
+import java.util.Collection;
+
+import org.apache.sshd.common.global.AbstractOpenSshHostKeysHandler;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.keys.BufferPublicKeyParser;
+
+/**
+ * A handler for the &quot;hostkeys-00@openssh.com&quot; request - for now, only
+ * reads the presented host key.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <a href="https://github.com/openssh/openssh-portable/blob/master/PROTOCOL">OpenSSH protocol - section 2.5</a>
+ */
+public class OpenSshHostKeysHandler extends AbstractOpenSshHostKeysHandler {
+    public static final String REQUEST = "hostkeys-00@openssh.com";
+    public static final OpenSshHostKeysHandler INSTANCE = new OpenSshHostKeysHandler();
+
+    public OpenSshHostKeysHandler() {
+        super(REQUEST);
+    }
+
+    public OpenSshHostKeysHandler(BufferPublicKeyParser<? extends PublicKey> parser) {
+        super(REQUEST, parser);
+    }
+
+    @Override
+    protected Result handleHostKeys(Session session, Collection<? extends PublicKey> keys, boolean wantReply, Buffer buffer) throws Exception {
+        // according to the spec, no reply should be required
+        ValidateUtils.checkTrue(!wantReply, "Unexpected reply required for the host keys of %s", session);
+        if (log.isDebugEnabled()) {
+            log.debug("handleHostKeys({})[want-reply={}] received {} keys",
+                      session, wantReply, GenericUtils.size(keys));
+        }
+
+        return Result.Replied;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/SshException.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/SshException.java b/sshd-core/src/main/java/org/apache/sshd/common/SshException.java
index e7cea6e..9f4b1d1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/SshException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/SshException.java
@@ -20,8 +20,11 @@ package org.apache.sshd.common;
 
 import java.io.IOException;
 
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+
 /**
- * TODO Add javadoc
+ * Represents an SSH related exception
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
@@ -31,24 +34,20 @@ public class SshException extends IOException {
 
     private final int disconnectCode;
 
-    public SshException() {
-        this(0, null, null);
+    public SshException(String message) {
+        this(message, null);
     }
 
-    public SshException(String message) {
-        this(0, message, null);
+    public SshException(Throwable cause) {
+        this(ValidateUtils.checkNotNull(cause, "No cause").getMessage(), cause);
     }
 
     public SshException(String message, Throwable cause) {
         this(0, message, cause);
     }
 
-    public SshException(Throwable cause) {
-        this(0, null, cause);
-    }
-
     public SshException(int disconnectCode) {
-        this(disconnectCode, null, null);
+        this(disconnectCode, SshConstants.getDisconnectReasonName(disconnectCode));
     }
 
     public SshException(int disconnectCode, String message) {
@@ -56,11 +55,11 @@ public class SshException extends IOException {
     }
 
     public SshException(int disconnectCode, Throwable cause) {
-        this(disconnectCode, null, cause);
+        this(disconnectCode, SshConstants.getDisconnectReasonName(disconnectCode), cause);
     }
 
     public SshException(int disconnectCode, String message, Throwable cause) {
-        super(message);
+        super(GenericUtils.isEmpty(message) ? SshConstants.getDisconnectReasonName(disconnectCode) : message);
         this.disconnectCode = disconnectCode;
         if (cause != null) {
             initCause(cause);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
index 2acc7ad..9622a3a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
@@ -446,7 +446,7 @@ public final class KeyUtils {
      * @see #getFingerPrint(Digest, PublicKey)
      */
     public static String getFingerPrint(Factory<? extends Digest> f, PublicKey key) {
-        return getFingerPrint(ValidateUtils.checkNotNull(f, "No digest factory").create(), key);
+        return (key == null) ? null : getFingerPrint(ValidateUtils.checkNotNull(f, "No digest factory").create(), key);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/global/AbstractOpenSshHostKeysHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/global/AbstractOpenSshHostKeysHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/global/AbstractOpenSshHostKeysHandler.java
new file mode 100644
index 0000000..28cb4d5
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/global/AbstractOpenSshHostKeysHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.global;
+
+import java.security.PublicKey;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.AbstractConnectionServiceRequestHandler;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.keys.BufferPublicKeyParser;
+import org.apache.sshd.common.util.buffer.keys.ED25519BufferPublicKeyParser;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractOpenSshHostKeysHandler extends AbstractConnectionServiceRequestHandler {
+
+    private final String request;
+    private final BufferPublicKeyParser<? extends PublicKey> parser;
+
+    protected AbstractOpenSshHostKeysHandler(String request) {
+        // TODO use only the default parser once ED25519 implementation is complete (see SSHD-440)
+        this(request, BufferPublicKeyParser.Utils.aggregate(Arrays.asList(
+                            BufferPublicKeyParser.Utils.DEFAULT,
+                            ED25519BufferPublicKeyParser.IGNORING
+                    )));
+    }
+
+    protected AbstractOpenSshHostKeysHandler(String request, BufferPublicKeyParser<? extends PublicKey> parser) {
+        this.request = ValidateUtils.checkNotNullAndNotEmpty(request, "No request identifier");
+        this.parser = ValidateUtils.checkNotNull(parser, "No publick keys extractor");
+    }
+
+    public final String getRequestName() {
+        return request;
+    }
+
+    public BufferPublicKeyParser<? extends PublicKey> getPublicKeysParser() {
+        return parser;
+    }
+
+    @Override
+    public Result process(ConnectionService connectionService, String request, boolean wantReply, Buffer buffer) throws Exception {
+        String expected = getRequestName();
+        if (!expected.equals(request)) {
+            return super.process(connectionService, request, wantReply, buffer);
+        }
+
+        Collection<PublicKey> keys = new LinkedList<>();
+        BufferPublicKeyParser<? extends PublicKey> p = getPublicKeysParser();
+        if (p != null) {
+            while (buffer.available() > 0) {
+                PublicKey key = buffer.getPublicKey(p);
+                if (log.isDebugEnabled()) {
+                    log.debug("process({})[{}] key type={}, fingerprint={}",
+                              connectionService, request, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+                }
+                if (key != null) {
+                    keys.add(key);
+                }
+            }
+        }
+
+        return handleHostKeys(connectionService.getSession(), keys, wantReply, buffer);
+    }
+
+    protected abstract Result handleHostKeys(Session session, Collection<? extends PublicKey> keys, boolean wantReply, Buffer buffer) throws Exception;
+
+    @Override
+    public String toString() {
+        return getRequestName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
index b4e7256..2357d48 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
@@ -42,6 +42,11 @@ public interface KeyPairProvider extends KeyIdentityProvider {
     String SSH_DSS = "ssh-dss";
 
     /**
+     * SSH identifier for ED25519 elliptic curve keys
+     */
+    String SSH_ED25519 = "ssh-ed25519";
+
+    /**
      * SSH identifier for EC keys in NIST curve P-256
      */
     String ECDSA_SHA2_NISTP256 = ECCurves.nistp256.getKeyType();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
index 176c867..4dd8cdd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
@@ -493,19 +493,19 @@ public abstract class AbstractConnectionService<S extends AbstractSession> exten
                                   this, handler.getClass().getSimpleName(), req, wantReply, result);
                     }
                 } else {
-                    sendResponse(buffer, req, result, wantReply);
+                    sendGlobalResponse(buffer, req, result, wantReply);
                     return;
                 }
             }
         }
 
         log.warn("globalRequest({}) unknown global request: {}", this, req);
-        sendResponse(buffer, req, RequestHandler.Result.Unsupported, wantReply);
+        sendGlobalResponse(buffer, req, RequestHandler.Result.Unsupported, wantReply);
     }
 
-    protected void sendResponse(Buffer buffer, String req, RequestHandler.Result result, boolean wantReply) throws IOException {
+    protected void sendGlobalResponse(Buffer buffer, String req, RequestHandler.Result result, boolean wantReply) throws IOException {
         if (log.isDebugEnabled()) {
-            log.debug("sendResponse({})[{}] result={}, want-reply={}", this, req, result, Boolean.valueOf(wantReply));
+            log.debug("sendGlobalResponse({})[{}] result={}, want-reply={}", this, req, result, wantReply);
         }
 
         if (RequestHandler.Result.Replied.equals(result) || (!wantReply)) {
@@ -513,15 +513,12 @@ public abstract class AbstractConnectionService<S extends AbstractSession> exten
         }
 
         byte cmd = RequestHandler.Result.ReplySuccess.equals(result)
-                 ? SshConstants.SSH_MSG_CHANNEL_SUCCESS
-                 : SshConstants.SSH_MSG_CHANNEL_FAILURE;
-        buffer.clear();
-        // leave room for the SSH header
-        buffer.ensureCapacity(5 + 1 + (Integer.SIZE / Byte.SIZE), RESPONSE_BUFFER_GROWTH_FACTOR);
-        buffer.rpos(5);
-        buffer.wpos(5);
+                 ? SshConstants.SSH_MSG_REQUEST_SUCCESS
+                 : SshConstants.SSH_MSG_REQUEST_FAILURE;
+        Session session = getSession();
+        buffer = session.prepareBuffer(cmd, BufferUtils.clear(buffer));
         buffer.putByte(cmd);
-        getSession().writePacket(buffer);
+        session.writePacket(buffer);
     }
 
     protected void requestSuccess(Buffer buffer) throws Exception {
@@ -536,5 +533,4 @@ public abstract class AbstractConnectionService<S extends AbstractSession> exten
     public String toString() {
         return getClass().getSimpleName() + "[" + getSession() + "]";
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionServiceRequestHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionServiceRequestHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionServiceRequestHandler.java
new file mode 100644
index 0000000..d10786f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionServiceRequestHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.session;
+
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractConnectionServiceRequestHandler
+        extends AbstractLoggingBean
+        implements ConnectionServiceRequestHandler {
+
+    protected AbstractConnectionServiceRequestHandler() {
+        super();
+    }
+
+    @Override
+    public Result process(ConnectionService connectionService, String request, boolean wantReply, Buffer buffer) throws Exception {
+        if (log.isDebugEnabled()) {
+            log.debug("process({}) request={}, want-reply={}", connectionService, request, wantReply);
+        }
+
+        return Result.Unsupported;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
index 029970f..3cf8481 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
@@ -33,5 +33,4 @@ public interface ConnectionServiceRequestHandler extends RequestHandler<Connecti
 
     @Override
     Result process(ConnectionService service, String request, boolean wantReply, Buffer buffer) throws Exception;
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
index c7aa090..727f461 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
@@ -58,6 +58,8 @@ import org.apache.sshd.common.util.Int2IntFunction;
 import org.apache.sshd.common.util.Readable;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.Transformer;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.keys.BufferPublicKeyParser;
 
 /**
  * Provides an abstract message buffer for encoding SSH messages
@@ -276,71 +278,51 @@ public abstract class Buffer implements Readable {
     }
 
     public PublicKey getPublicKey() throws SshException {
+        return getPublicKey(BufferPublicKeyParser.Utils.DEFAULT);
+    }
+
+    /**
+     * @param parser A {@link BufferPublicKeyParser} to extract the key from the buffer
+     * - never {@code null}
+     * @return The extracted {@link PublicKey} - may be {@code null} if the parser so decided
+     * @throws SshException If failed to extract the key
+     * @see #getRawPublicKey(BufferPublicKeyParser)
+     */
+    public PublicKey getPublicKey(BufferPublicKeyParser<? extends PublicKey> parser) throws SshException {
         int ow = wpos();
         int len = getInt();
         wpos(rpos() + len);
         try {
-            return getRawPublicKey();
+            return getRawPublicKey(parser);
         } finally {
             wpos(ow);
         }
     }
 
     public PublicKey getRawPublicKey() throws SshException {
-        try {
-            String keyAlg = getString();
-            if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
-                BigInteger e = getMPInt();
-                BigInteger n = getMPInt();
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
-                return keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
-            } else if (KeyPairProvider.SSH_DSS.equals(keyAlg)) {
-                BigInteger p = getMPInt();
-                BigInteger q = getMPInt();
-                BigInteger g = getMPInt();
-                BigInteger y = getMPInt();
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
-                return keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
-            }
+        return getRawPublicKey(BufferPublicKeyParser.Utils.DEFAULT);
+    }
 
-            ECCurves curve = ECCurves.fromKeyType(keyAlg);
-            if (curve == null) {
-                throw new NoSuchAlgorithmException("Unsupported raw public algorithm: " + keyAlg);
+    /**
+     * @param parser A {@link BufferPublicKeyParser} to extract the key from the buffer
+     * - never {@code null}
+     * @return The extracted {@link PublicKey} - may be {@code null} if the parser so decided
+     * @throws SshException If failed to extract the key
+     */
+    public PublicKey getRawPublicKey(BufferPublicKeyParser<? extends PublicKey> parser) throws SshException {
+        ValidateUtils.checkNotNull(parser, "No key data parser");
+        try {
+            String keyType = getString();
+            if (!parser.isKeyTypeSupported(keyType)) {
+                throw new NoSuchAlgorithmException("Key type=" + keyType + ") not supported by parser=" + parser);
             }
 
-            String curveName = curve.getName();
-            ECParameterSpec params = curve.getParameters();
-            return getRawECKey(curveName, params);
+            return parser.getRawPublicKey(keyType, this);
         } catch (GeneralSecurityException e) {
             throw new SshException(e);
         }
     }
 
-    protected PublicKey getRawECKey(String expectedCurve, ECParameterSpec spec) throws GeneralSecurityException {
-        String curveName = getString();
-        if (!expectedCurve.equals(curveName)) {
-            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ") curve name does not match expected: " + curveName);
-        }
-
-        if (spec == null) {
-            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ") missing curve parameters");
-        }
-
-        byte[] octets = getBytes();
-        ECPoint w;
-        try {
-            w = ECDSAPublicKeyEntryDecoder.octetStringToEcPoint(octets);
-        } catch (RuntimeException e) {
-            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ")"
-                    + " cannot (" + e.getClass().getSimpleName() + ")"
-                    + " retrieve W value: " + e.getMessage(),
-                    e);
-        }
-
-        KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
-        return keyFactory.generatePublic(new ECPublicKeySpec(w, spec));
-    }
-
     public KeyPair getKeyPair() throws SshException {
         try {
             final PublicKey pub;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/AbstractBufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/AbstractBufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/AbstractBufferPublicKeyParser.java
new file mode 100644
index 0000000..40a238b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/AbstractBufferPublicKeyParser.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+
+/**
+ * @param <PUB> Type of {@link PublicKey} being extracted
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractBufferPublicKeyParser<PUB extends PublicKey> implements BufferPublicKeyParser<PUB> {
+    private final Class<PUB> keyClass;
+    private final Collection<String> supported;
+
+    protected AbstractBufferPublicKeyParser(Class<PUB> keyClass, String ... supported) {
+        this(keyClass, GenericUtils.isEmpty(supported) ? Collections.<String>emptyList() : Arrays.asList(supported));
+    }
+
+    protected AbstractBufferPublicKeyParser(Class<PUB> keyClass, Collection<String> supported) {
+        this.keyClass = ValidateUtils.checkNotNull(keyClass, "No key class");
+        this.supported = ValidateUtils.checkNotNullAndNotEmpty(supported, "No supported types for %s", keyClass.getSimpleName());
+    }
+
+    public Collection<String> getSupportedKeyTypes() {
+        return supported;
+    }
+
+    public final Class<PUB> getKeyClass() {
+        return keyClass;
+    }
+
+    @Override
+    public boolean isKeyTypeSupported(String keyType) {
+        Collection<String> keys = getSupportedKeyTypes();
+        return (GenericUtils.length(keyType) > 0)
+            && (GenericUtils.size(keys) > 0)
+            && keys.contains(keyType);
+    }
+
+    protected <S extends KeySpec> PUB generatePublicKey(String algorithm, S keySpec) throws GeneralSecurityException {
+        KeyFactory keyFactory = getKeyFactory(algorithm);
+        PublicKey key = keyFactory.generatePublic(keySpec);
+        Class<PUB> kc = getKeyClass();
+        if (!kc.isInstance(key)) {
+            throw new InvalidKeySpecException("Mismatched generated key types: expected=" + kc.getSimpleName() + ", actual=" + key);
+        }
+
+        return kc.cast(key);
+    }
+
+    protected KeyFactory getKeyFactory(String algorithm) throws GeneralSecurityException {
+        return SecurityUtils.getKeyFactory(algorithm);
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " - supported=" + getSupportedKeyTypes();
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java
new file mode 100644
index 0000000..bcd3173
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * Parses a raw {@link PublicKey} from a {@link Buffer}
+ *
+ * @param <PUB> Type of {@link PublicKey} being extracted
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface BufferPublicKeyParser<PUB extends PublicKey> {
+    BufferPublicKeyParser<PublicKey> EMPTY = new BufferPublicKeyParser<PublicKey>() {
+        @Override
+        public boolean isKeyTypeSupported(String keyType) {
+            return false;
+        }
+
+        @Override
+        public PublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+            throw new NoSuchAlgorithmException(keyType);
+        }
+
+        @Override
+        public String toString() {
+            return "EMPTY";
+        }
+    };
+
+    /**
+     * @param keyType The key type - e.g., &quot;ssh-rsa&quot, &quot;ssh-dss&quot;
+     * @return {@code true} if this key type is supported by the parser
+     */
+    boolean isKeyTypeSupported(String keyType);
+
+    /**
+     * @param keyType The key type - e.g., &quot;ssh-rsa&quot, &quot;ssh-dss&quot;
+     * @param buffer The {@link Buffer} containing the encoded raw public key
+     * @return The decoded {@link PublicKey}
+     * @throws GeneralSecurityException If failed to generate the key
+     */
+    PUB getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException;
+
+    /**
+     * A helper class for {@link BufferPublicKeyParser} related operations
+     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+     */
+    // CHECKSTYLE:OFF
+    final class Utils {
+    // CHECKSTYLE:ON
+        public static final BufferPublicKeyParser<PublicKey> DEFAULT = aggregate(
+                Arrays.asList(
+                        RSABufferPublicKeyParser.INSTANCE,
+                        DSSBufferPublicKeyParser.INSTANCE,
+                        ECBufferPublicKeyParser.INSTANCE));
+
+        private Utils() {
+            throw new UnsupportedOperationException("No instance");
+        }
+
+        public static BufferPublicKeyParser<PublicKey> aggregate(final Collection<? extends BufferPublicKeyParser<? extends PublicKey>> parsers) {
+            if (GenericUtils.isEmpty(parsers)) {
+                return EMPTY;
+            }
+
+            return new BufferPublicKeyParser<PublicKey>() {
+                @Override
+                public boolean isKeyTypeSupported(String keyType) {
+                    for (BufferPublicKeyParser<? extends PublicKey> p : parsers) {
+                        if (p.isKeyTypeSupported(keyType)) {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                @Override
+                public PublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+                    for (BufferPublicKeyParser<? extends PublicKey> p : parsers) {
+                        if (p.isKeyTypeSupported(keyType)) {
+                            return p.getRawPublicKey(keyType, buffer);
+                        }
+                    }
+
+                    throw new NoSuchAlgorithmException("No aggregate matcher for " + keyType);
+                }
+
+                @Override
+                public String toString() {
+                    return String.valueOf(parsers);
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/DSSBufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/DSSBufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/DSSBufferPublicKeyParser.java
new file mode 100644
index 0000000..af1b383
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/DSSBufferPublicKeyParser.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DSSBufferPublicKeyParser extends AbstractBufferPublicKeyParser<DSAPublicKey> {
+    public static final DSSBufferPublicKeyParser INSTANCE = new DSSBufferPublicKeyParser();
+
+    public DSSBufferPublicKeyParser() {
+        super(DSAPublicKey.class, KeyPairProvider.SSH_DSS);
+    }
+
+    @Override
+    public DSAPublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+        ValidateUtils.checkTrue(isKeyTypeSupported(keyType), "Unsupported key type: %s", keyType);
+        BigInteger p = buffer.getMPInt();
+        BigInteger q = buffer.getMPInt();
+        BigInteger g = buffer.getMPInt();
+        BigInteger y = buffer.getMPInt();
+        return generatePublicKey("DSA", new DSAPublicKeySpec(y, p, q, g));
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ECBufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ECBufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ECBufferPublicKeyParser.java
new file mode 100644
index 0000000..71b80ff
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ECBufferPublicKeyParser.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.config.keys.ECDSAPublicKeyEntryDecoder;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ECBufferPublicKeyParser extends AbstractBufferPublicKeyParser<ECPublicKey> {
+    public static final ECBufferPublicKeyParser INSTANCE = new ECBufferPublicKeyParser();
+
+    public ECBufferPublicKeyParser() {
+        super(ECPublicKey.class, ECCurves.KEY_TYPES);
+    }
+
+    @Override
+    public ECPublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+        ValidateUtils.checkTrue(isKeyTypeSupported(keyType), "Unsupported key type: %s", keyType);
+        ECCurves curve = ECCurves.fromKeyType(keyType);
+        if (curve == null) {
+            throw new NoSuchAlgorithmException("Unsupported raw public algorithm: " + keyType);
+        }
+
+        String curveName = curve.getName();
+        ECParameterSpec params = curve.getParameters();
+        return getRawECKey(curveName, params, buffer);
+    }
+
+    protected ECPublicKey getRawECKey(String expectedCurve, ECParameterSpec spec, Buffer buffer) throws GeneralSecurityException {
+        String curveName = buffer.getString();
+        if (!expectedCurve.equals(curveName)) {
+            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ") curve name does not match expected: " + curveName);
+        }
+
+        if (spec == null) {
+            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ") missing curve parameters");
+        }
+
+        byte[] octets = buffer.getBytes();
+        ECPoint w;
+        try {
+            w = ECDSAPublicKeyEntryDecoder.octetStringToEcPoint(octets);
+        } catch (RuntimeException e) {
+            throw new InvalidKeySpecException("getRawECKey(" + expectedCurve + ")"
+                    + " cannot (" + e.getClass().getSimpleName() + ")"
+                    + " retrieve W value: " + e.getMessage(),
+                    e);
+        }
+
+        return generatePublicKey("EC", new ECPublicKeySpec(w, spec));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ED25519BufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ED25519BufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ED25519BufferPublicKeyParser.java
new file mode 100644
index 0000000..a490c5a
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/ED25519BufferPublicKeyParser.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * TODO complete this when SSHD-440 is done
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ED25519BufferPublicKeyParser extends AbstractBufferPublicKeyParser<PublicKey> {
+    // TODO define a (public) static (final) INSTANCE once completed
+    public static final ED25519BufferPublicKeyParser IGNORING = new ED25519BufferPublicKeyParser() {
+        @Override
+        protected PublicKey generatePublicKey(byte[] octets) throws GeneralSecurityException {
+            return null;
+        }
+    };
+
+    public ED25519BufferPublicKeyParser() {
+        super(PublicKey.class, KeyPairProvider.SSH_ED25519);
+    }
+
+    @Override
+    public PublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+        ValidateUtils.checkTrue(isKeyTypeSupported(keyType), "Unsupported key type: %s", keyType);
+        return generatePublicKey(buffer.getBytes());
+    }
+
+    protected PublicKey generatePublicKey(byte[] octets) throws GeneralSecurityException {
+        throw new NoSuchAlgorithmException("Unsupported curve: " + KeyPairProvider.SSH_ED25519);
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/RSABufferPublicKeyParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/RSABufferPublicKeyParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/RSABufferPublicKeyParser.java
new file mode 100644
index 0000000..1c8119f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/keys/RSABufferPublicKeyParser.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.buffer.keys;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPublicKeySpec;
+
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class RSABufferPublicKeyParser extends AbstractBufferPublicKeyParser<RSAPublicKey> {
+    public static final RSABufferPublicKeyParser INSTANCE = new RSABufferPublicKeyParser();
+
+    public RSABufferPublicKeyParser() {
+        super(RSAPublicKey.class, KeyPairProvider.SSH_RSA);
+    }
+
+    @Override
+    public RSAPublicKey getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
+        ValidateUtils.checkTrue(isKeyTypeSupported(keyType), "Unsupported key type: %s", keyType);
+        BigInteger e = buffer.getMPInt();
+        BigInteger n = buffer.getMPInt();
+        return generatePublicKey("RSA", new RSAPublicKeySpec(n, e));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
index d2fd0ab..d65716e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
@@ -40,6 +40,7 @@ import org.apache.sshd.server.forward.DirectTcpipFactory;
 import org.apache.sshd.server.global.CancelTcpipForwardHandler;
 import org.apache.sshd.server.global.KeepAliveHandler;
 import org.apache.sshd.server.global.NoMoreSessionsHandler;
+import org.apache.sshd.server.global.OpenSshHostKeysHandler;
 import org.apache.sshd.server.global.TcpipForwardHandler;
 import org.apache.sshd.server.kex.DHGEXServer;
 import org.apache.sshd.server.kex.DHGServer;
@@ -74,7 +75,8 @@ public class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
             KeepAliveHandler.INSTANCE,
             NoMoreSessionsHandler.INSTANCE,
             TcpipForwardHandler.INSTANCE,
-            CancelTcpipForwardHandler.INSTANCE
+            CancelTcpipForwardHandler.INSTANCE,
+            OpenSshHostKeysHandler.INSTANCE
         ));
 
     public static final PublickeyAuthenticator DEFAULT_PUBLIC_KEY_AUTHENTICATOR = DefaultAuthorizedKeysAuthenticator.INSTANCE;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/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 20e7a97..23724b5 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
@@ -21,19 +21,19 @@ package org.apache.sshd.server.global;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.forward.TcpipForwarder;
+import org.apache.sshd.common.session.AbstractConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.session.ConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.Int2IntFunction;
 import org.apache.sshd.common.util.buffer.Buffer;
-import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+import org.apache.sshd.common.util.buffer.BufferUtils;
 
 /**
  * Handler for cancel-tcpip-forward global request.
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class CancelTcpipForwardHandler extends AbstractLoggingBean implements ConnectionServiceRequestHandler {
+public class CancelTcpipForwardHandler extends AbstractConnectionServiceRequestHandler {
     public static final String REQUEST = "cancel-tcpip-forward";
     /**
      * Default growth factor function used to resize response buffers
@@ -48,34 +48,28 @@ public class CancelTcpipForwardHandler extends AbstractLoggingBean implements Co
 
     @Override
     public Result process(ConnectionService connectionService, String request, boolean wantReply, Buffer buffer) throws Exception {
-        if (REQUEST.equals(request)) {
-            String address = buffer.getString();
-            int port = buffer.getInt();
-            SshdSocketAddress socketAddress = new SshdSocketAddress(address, port);
-            if (log.isDebugEnabled()) {
-                log.debug("process(" + connectionService + ")[" + request + "] " + socketAddress + " reply=" + wantReply);
-            }
-
-            TcpipForwarder forwarder = connectionService.getTcpipForwarder();
-            forwarder.localPortForwardingCancelled(socketAddress);
+        if (!REQUEST.equals(request)) {
+            return super.process(connectionService, request, wantReply, buffer);
+        }
 
-            if (wantReply) {
-                buffer.clear();
-                // leave room for the SSH header
-                buffer.ensureCapacity(5 + 1 + (Integer.SIZE / Byte.SIZE), RESPONSE_BUFFER_GROWTH_FACTOR);
-                buffer.rpos(5);
-                buffer.wpos(5);
-                buffer.putByte(SshConstants.SSH_MSG_REQUEST_SUCCESS);
-                buffer.putInt(port);
+        String address = buffer.getString();
+        int port = buffer.getInt();
+        SshdSocketAddress socketAddress = new SshdSocketAddress(address, port);
+        if (log.isDebugEnabled()) {
+            log.debug("process({})[{}] {} reply=" + wantReply,
+                      connectionService, request, socketAddress, wantReply);
+        }
 
-                Session session = connectionService.getSession();
-                session.writePacket(buffer);
-            }
+        TcpipForwarder forwarder = connectionService.getTcpipForwarder();
+        forwarder.localPortForwardingCancelled(socketAddress);
 
-            return Result.Replied;
+        if (wantReply) {
+            Session session = connectionService.getSession();
+            buffer = session.prepareBuffer(SshConstants.SSH_MSG_REQUEST_SUCCESS, BufferUtils.clear(buffer));
+            buffer.putInt(port);
+            session.writePacket(buffer);
         }
 
-        return Result.Unsupported;
+        return Result.Replied;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/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 b9a0818..65a6f2c 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
@@ -18,8 +18,8 @@
  */
 package org.apache.sshd.server.global;
 
+import org.apache.sshd.common.session.AbstractConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.session.ConnectionServiceRequestHandler;
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
@@ -27,7 +27,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class KeepAliveHandler implements ConnectionServiceRequestHandler {
+public class KeepAliveHandler extends AbstractConnectionServiceRequestHandler {
     public static final KeepAliveHandler INSTANCE = new KeepAliveHandler();
 
     public KeepAliveHandler() {
@@ -38,8 +38,8 @@ public class KeepAliveHandler implements ConnectionServiceRequestHandler {
     public Result process(ConnectionService connectionService, String request, boolean wantReply, Buffer buffer) throws Exception {
         if (request.startsWith("keepalive@")) {
             return Result.ReplyFailure;
+        } else {
+            return super.process(connectionService, request, wantReply, buffer);
         }
-        return Result.Unsupported;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
index ed2acca..d243da3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
@@ -18,8 +18,8 @@
  */
 package org.apache.sshd.server.global;
 
+import org.apache.sshd.common.session.AbstractConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.session.ConnectionServiceRequestHandler;
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
@@ -27,7 +27,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class NoMoreSessionsHandler implements ConnectionServiceRequestHandler {
+public class NoMoreSessionsHandler extends AbstractConnectionServiceRequestHandler {
     public static final NoMoreSessionsHandler INSTANCE = new NoMoreSessionsHandler();
 
     public NoMoreSessionsHandler() {
@@ -39,8 +39,8 @@ public class NoMoreSessionsHandler implements ConnectionServiceRequestHandler {
         if (request.startsWith("no-more-sessions@")) {
             connectionService.setAllowMoreSessions(false);
             return Result.ReplyFailure;
+        } else {
+            return super.process(connectionService, request, wantReply, buffer);
         }
-        return Result.Unsupported;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
new file mode 100644
index 0000000..150b3d9
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.server.global;
+
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.util.Collection;
+
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.global.AbstractOpenSshHostKeysHandler;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.signature.Signature;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+import org.apache.sshd.common.util.buffer.keys.BufferPublicKeyParser;
+
+/**
+ * An initial handler for &quot;hostkeys-prove-00@openssh.com&quot; request
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <a href="https://github.com/openssh/openssh-portable/blob/master/PROTOCOL">OpenSSH protocol - section 2.5</a>
+ */
+public class OpenSshHostKeysHandler extends AbstractOpenSshHostKeysHandler {
+    public static final String REQUEST = "hostkeys-prove-00@openssh.com";
+    public static final OpenSshHostKeysHandler INSTANCE = new OpenSshHostKeysHandler();
+
+    public OpenSshHostKeysHandler() {
+        super(REQUEST);
+    }
+
+    public OpenSshHostKeysHandler(BufferPublicKeyParser<? extends PublicKey> parser) {
+        super(REQUEST, parser);
+    }
+
+    @Override
+    protected Result handleHostKeys(Session session, Collection<? extends PublicKey> keys, boolean wantReply, Buffer buffer) throws Exception {
+        // according to the specification there MUST be reply required by the server
+        ValidateUtils.checkTrue(wantReply, "No reply required for host keys of %s", session);
+        if (log.isDebugEnabled()) {
+            log.debug("handleHostKeys({})[want-reply={}] received {} keys",
+                      session, wantReply, GenericUtils.size(keys));
+        }
+
+        // generate the required signatures
+        buffer = session.prepareBuffer(SshConstants.SSH_MSG_REQUEST_SUCCESS, BufferUtils.clear(buffer));
+
+        Buffer buf = new ByteArrayBuffer();
+        byte[] sessionId = session.getSessionId();
+        FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No manager");
+        Collection<? extends NamedFactory<Signature>> factories = manager.getSignatureFactories();
+        KeyPairProvider kpp = ValidateUtils.checkNotNull(session.getKeyPairProvider(), "No server keys provider");
+        for (PublicKey k : keys) {
+            String keyType = KeyUtils.getKeyType(k);
+            Signature verifier = ValidateUtils.checkNotNull(
+                    NamedFactory.Utils.create(factories, keyType),
+                    "No signer could be located for key type=%s",
+                    keyType);
+
+            KeyPair kp = ValidateUtils.checkNotNull(kpp.loadKey(keyType), "No key of type=%s available", keyType);
+            verifier.initSigner(kp.getPrivate());
+
+            buf.clear();
+            buf.putString(REQUEST);
+            buf.putBytes(sessionId);
+            buf.putPublicKey(k);
+
+            byte[] data = buf.getCompactData();
+            verifier.update(data);
+
+            byte[] signature = verifier.sign();
+            buffer.putBytes(signature);
+        }
+
+        session.writePacket(buffer);
+        return Result.Replied;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/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 6cde83b..8541276 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
@@ -21,19 +21,19 @@ package org.apache.sshd.server.global;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.forward.TcpipForwarder;
+import org.apache.sshd.common.session.AbstractConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.session.ConnectionServiceRequestHandler;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.Int2IntFunction;
 import org.apache.sshd.common.util.buffer.Buffer;
-import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+import org.apache.sshd.common.util.buffer.BufferUtils;
 
 /**
  * Handler for tcpip-forward global request.
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class TcpipForwardHandler extends AbstractLoggingBean implements ConnectionServiceRequestHandler {
+public class TcpipForwardHandler extends AbstractConnectionServiceRequestHandler {
     public static final String REQUEST = "tcpip-forward";
 
     /**
@@ -49,33 +49,28 @@ public class TcpipForwardHandler extends AbstractLoggingBean implements Connecti
 
     @Override
     public Result process(ConnectionService connectionService, String request, boolean wantReply, Buffer buffer) throws Exception {
-        if (REQUEST.equals(request)) {
-            String address = buffer.getString();
-            int port = buffer.getInt();
-            SshdSocketAddress socketAddress = new SshdSocketAddress(address, port);
-            TcpipForwarder forwarder = connectionService.getTcpipForwarder();
-            SshdSocketAddress bound = forwarder.localPortForwardingRequested(socketAddress);
-            if (log.isDebugEnabled()) {
-                log.debug("process(" + connectionService + ")[" + request + "] " + socketAddress + " => " + bound + ", reply=" + wantReply);
-            }
+        if (!REQUEST.equals(request)) {
+            return super.process(connectionService, request, wantReply, buffer);
+        }
 
-            port = bound.getPort();
-            if (wantReply) {
-                buffer.clear();
-                // leave room for the SSH header
-                buffer.ensureCapacity(5 + 1 + (Integer.SIZE / Byte.SIZE), RESPONSE_BUFFER_GROWTH_FACTOR);
-                buffer.rpos(5);
-                buffer.wpos(5);
-                buffer.putByte(SshConstants.SSH_MSG_REQUEST_SUCCESS);
-                buffer.putInt(port);
+        String address = buffer.getString();
+        int port = buffer.getInt();
+        SshdSocketAddress socketAddress = new SshdSocketAddress(address, port);
+        TcpipForwarder forwarder = connectionService.getTcpipForwarder();
+        SshdSocketAddress bound = forwarder.localPortForwardingRequested(socketAddress);
+        if (log.isDebugEnabled()) {
+            log.debug("process({})[{}] {} => {}, reply={}",
+                      connectionService, request, socketAddress, bound, wantReply);
+        }
 
-                Session session = connectionService.getSession();
-                session.writePacket(buffer);
-            }
-            return Result.Replied;
+        port = bound.getPort();
+        if (wantReply) {
+            Session session = connectionService.getSession();
+            buffer = session.prepareBuffer(SshConstants.SSH_MSG_REQUEST_SUCCESS, BufferUtils.clear(buffer));
+            buffer.putInt(port);
+            session.writePacket(buffer);
         }
 
-        return Result.Unsupported;
+        return Result.Replied;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
index c2e0742..b05a763 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
@@ -205,14 +205,13 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
             buffer.putMPInt(k);
             hash.update(buffer.array(), 0, buffer.available());
             h = hash.digest();
+            sig.update(h);
 
-            byte[] sigH;
             buffer.clear();
-            sig.update(h, 0, h.length);
             buffer.putString(algo);
             buffer.putBytes(sig.sign());
-            sigH = buffer.getCompactData();
 
+            byte[] sigH = buffer.getCompactData();
             if (log.isTraceEnabled()) {
                 log.trace("next({})[{}][K_S]:  {}", this, session, BufferUtils.printHex(k_s));
                 log.trace("next({})[{}][f]:    {}", this, session, BufferUtils.printHex(f));

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/65ac5ba7/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
index 3cdcd17..dbc6cc8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
@@ -122,14 +122,13 @@ public class DHGServer extends AbstractDHServerKeyExchange {
         buffer.putMPInt(k);
         hash.update(buffer.array(), 0, buffer.available());
         h = hash.digest();
+        sig.update(h);
 
-        byte[] sigH;
         buffer.clear();
-        sig.update(h, 0, h.length);
         buffer.putString(algo);
         buffer.putBytes(sig.sign());
-        sigH = buffer.getCompactData();
 
+        byte[] sigH = buffer.getCompactData();
         if (log.isTraceEnabled()) {
             log.trace("next({})[{}][K_S]:  {}", this, session, BufferUtils.printHex(k_s));
             log.trace("next({})[{}][f]:    {}", this, session, BufferUtils.printHex(f));