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/07/05 08:29:11 UTC

mina-sshd git commit: [SSHD-518] Add support for SFTP 'copy-file' extension

Repository: mina-sshd
Updated Branches:
  refs/heads/master ed92ebe89 -> 9d0662215


[SSHD-518] Add support for SFTP 'copy-file' extension


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

Branch: refs/heads/master
Commit: 9d06622153a4121948e49a4c61282eb5636c3f42
Parents: ed92ebe
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Sun Jul 5 09:29:00 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Sun Jul 5 09:29:00 2015 +0300

----------------------------------------------------------------------
 sshd-core/key.pem                               |  12 ++
 .../sshd/agent/common/AbstractAgentClient.java  |   2 +-
 .../sshd/agent/common/AbstractAgentProxy.java   |  10 +-
 .../auth/UserAuthKeyboardInteractive.java       |   4 +-
 .../sshd/client/auth/UserAuthPassword.java      |   2 +-
 .../sshd/client/auth/UserAuthPublicKey.java     |   2 +-
 .../org/apache/sshd/client/kex/DHGClient.java   |   2 +-
 .../org/apache/sshd/client/kex/DHGEXClient.java |   2 +-
 .../client/session/ClientUserAuthService.java   |   4 +-
 .../subsystem/sftp/DefaultSftpClient.java       |  18 +--
 .../sshd/client/subsystem/sftp/SftpClient.java  |   2 +-
 .../java/org/apache/sshd/common/Service.java    |   7 +-
 .../apache/sshd/common/forward/SocksProxy.java  |  16 +--
 .../session/AbstractConnectionService.java      |   4 +-
 .../sshd/common/session/AbstractSession.java    |   6 +-
 .../common/subsystem/sftp/SftpConstants.java    |   1 +
 .../subsystem/sftp/extensions/ParserUtils.java  |   4 +-
 .../sftp/extensions/Supported2Parser.java       |  91 +++++++++++++
 .../sftp/extensions/SupportedParser.java        |  80 ++++++++++++
 .../apache/sshd/common/util/buffer/Buffer.java  | 128 +++++++++++++++++--
 .../org/apache/sshd/common/util/io/IoUtils.java |   2 +
 .../auth/UserAuthKeyboardInteractive.java       |   2 +-
 .../sshd/server/auth/gss/UserAuthGSS.java       |   2 +-
 .../org/apache/sshd/server/kex/DHGEXServer.java |   2 +-
 .../org/apache/sshd/server/kex/DHGServer.java   |   2 +-
 .../server/session/ServerUserAuthService.java   |   2 +-
 .../server/subsystem/sftp/SftpSubsystem.java    |  64 +++++++---
 .../test/java/org/apache/sshd/WindowTest.java   |   2 +-
 .../java/org/apache/sshd/client/ClientTest.java |   2 +-
 .../sshd/client/subsystem/sftp/SftpTest.java    |  32 ++++-
 .../deprecated/ClientUserAuthServiceOld.java    |   2 +-
 .../apache/sshd/deprecated/UserAuthAgent.java   |   4 +-
 .../deprecated/UserAuthKeyboardInteractive.java |   6 +-
 .../sshd/deprecated/UserAuthPassword.java       |   2 +-
 .../sshd/deprecated/UserAuthPublicKey.java      |   4 +-
 35 files changed, 441 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/key.pem
----------------------------------------------------------------------
diff --git a/sshd-core/key.pem b/sshd-core/key.pem
new file mode 100644
index 0000000..0837e2e
--- /dev/null
+++ b/sshd-core/key.pem
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBugIBAAKBgQCssuzdF9+pjVpV+u5t9fYg52q74giD9EUvJ1YHDOsepVgJMgbi
+P8ECg1nGbXxpmVMakdchnZCZBQ84O1MngGBMH0TOa1ySwei0tceeSn/XxVgm0V/c
+X67x0ascNmKzJOvaVyvzsu7dQKxU/g6HhNapWl3JYLupWcMI2eYjSoENPQIVAIT4
+Urb8PSPDAXjy4eDouBluDFlBAoGAePjF+apIm2zWFoxjQ65guG0dc0UnxKIHgf2L
+FhYS129RWkCLQhimh9Z55g+vYLxzhHSnF+7IvlZdtUPoN2HDUEFc30XFA8d+ahjr
+kkLbVzOq7yOkSxO5+rTMWNXiTvvssIhsz6nCDBrViRKJJ8F3Au4W5THoJuLFAgho
+oZWKceICgYBTGx3tQocQnGXdV+D2Kg7A0x8Yi/T9ZET0kBhGVjQzYDOCtJvML3sD
+uA+iPMKt6lgULDL+czK5aOSRKBjo1hckUyEGQLfVo3nYq6EspIjrf47HQqmGSUzL
+P5gv99dWn0+dgzAlZZdeWtO9g/KqrgfdZhnLRCdU5TgMgjYlzckg5AIUR7iHDKCB
+1Whmb6WCKX67kWyc6PY=
+-----END DSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
index 548b411..6940bcd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
@@ -76,7 +76,7 @@ public abstract class AbstractAgentClient extends AbstractLoggingBean {
     }
 
     protected void process(Buffer req, Buffer rep) throws Exception {
-        int cmd = req.getByte();
+        int cmd = req.getUByte();
         switch (cmd) {
             case SSH2_AGENTC_REQUEST_IDENTITIES: {
                 List<Pair<PublicKey,String>> keys = agent.getIdentities();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
index a5a7304..b3dc062 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
@@ -77,7 +77,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
     public List<Pair<PublicKey, String>> getIdentities() throws IOException {
         Buffer buffer = createBuffer(SSH2_AGENTC_REQUEST_IDENTITIES);
         buffer = request(prepare(buffer));
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
             throw new SshException("Bad agent identities answer: " + type);
         }
@@ -103,7 +103,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
         buffer.putInt(0);
         buffer = request(prepare(buffer));
         
-        byte responseType = buffer.getByte(); 
+        int responseType = buffer.getUByte(); 
         if (responseType != SSH2_AGENT_SIGN_RESPONSE) {
             throw new SshException("Bad signing response type: " + (responseType & 0xFF));
         }
@@ -128,7 +128,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
         buffer = request(prepare(buffer));
         
         int available = buffer.available();
-        byte response = (available >= 1) ? buffer.getByte() : -1;
+        int response = (available >= 1) ? buffer.getUByte() : -1;
         if ((available != 1) || (response != SSH_AGENT_SUCCESS)) {
             throw new SshException("Bad addIdentity response (" + (response & 0xFF) + ") - available=" + available);
         }
@@ -145,7 +145,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
         buffer = request(prepare(buffer));
 
         int available = buffer.available();
-        byte response = (available >= 1) ? buffer.getByte() : -1;
+        int response = (available >= 1) ? buffer.getUByte() : -1;
         if ((available != 1) || (response != SSH_AGENT_SUCCESS)) {
             throw new SshException("Bad removeIdentity response (" + (response & 0xFF) + ") - available=" + available);
         }
@@ -160,7 +160,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
         buffer = request(prepare(buffer));
 
         int available = buffer.available();
-        byte response = (available >= 1) ? buffer.getByte() : -1;
+        int response = (available >= 1) ? buffer.getUByte() : -1;
         if ((available != 1) || (response != SSH_AGENT_SUCCESS)) {
             throw new SshException("Bad removeAllIdentities response (" + (response & 0xFF) + ") - available=" + available);
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
index 100f0bd..f7f66c4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
@@ -91,7 +91,7 @@ public class UserAuthKeyboardInteractive extends AbstractLoggingBean implements
             return true;
         }
 
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd == SSH_MSG_USERAUTH_INFO_REQUEST) {
             log.debug("Received SSH_MSG_USERAUTH_INFO_REQUEST");
             String name = buffer.getString();
@@ -107,7 +107,7 @@ public class UserAuthKeyboardInteractive extends AbstractLoggingBean implements
             for (int i = 0; i < num; i++) {
                 // according to RFC4256: "The prompt field(s) MUST NOT be empty strings."
                 prompt[i] = buffer.getString();
-                echo[i] = (buffer.getByte() != 0);
+                echo[i] = buffer.getBoolean();
             }
             
             if (log.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
index cfa9de4..7ca3170 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
@@ -75,7 +75,7 @@ public class UserAuthPassword extends AbstractLoggingBean implements UserAuth {
             }
             return false;
         }
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd == SshConstants.SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) {
             String prompt = buffer.getString();
             String lang = buffer.getString();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
index 7fb9954..4a8b881 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
@@ -114,7 +114,7 @@ public class UserAuthPublicKey extends AbstractLoggingBean implements UserAuth {
             return false;
         }
 
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd == SshConstants.SSH_MSG_USERAUTH_PK_OK) {
             PublicKey key = current.getPublicKey();
             String algo = KeyUtils.getKeyType(key);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
index cdbf6a4..3d533fa 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
@@ -93,7 +93,7 @@ public class DHGClient extends AbstractDHClientKeyExchange {
 
     @Override
     public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd != SshConstants.SSH_MSG_KEXDH_REPLY) {
             throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
                                    "Protocol error: expected packet SSH_MSG_KEXDH_REPLY, got " + cmd);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
index 79c1a4a..35dd0c3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
@@ -92,7 +92,7 @@ public class DHGEXClient extends AbstractDHClientKeyExchange {
 
     @Override
     public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd != expected) {
             throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
                     "Protocol error: expected packet " + expected + ", got " + cmd);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
index c32fc8d..41a0d37 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
@@ -115,7 +115,7 @@ public class ClientUserAuthService extends CloseableUtils.AbstractCloseable impl
     }
 
     @Override
-    public void process(byte cmd, Buffer buffer) throws Exception {
+    public void process(int cmd, Buffer buffer) throws Exception {
         if (this.authFuture.isSuccess()) {
             throw new IllegalStateException("UserAuth message delivered to authenticated client");
         } else if (this.authFuture.isDone()) {
@@ -143,7 +143,7 @@ public class ClientUserAuthService extends CloseableUtils.AbstractCloseable impl
      * @throws java.io.IOException
      */
     private void processUserAuth(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
             log.info("Received SSH_MSG_USERAUTH_SUCCESS");
             log.debug("Succeeded with {}", userAuth);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/DefaultSftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/DefaultSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/DefaultSftpClient.java
index 2f743b9..9f064c0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/DefaultSftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/DefaultSftpClient.java
@@ -335,7 +335,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
         }
 
         int length = buffer.getInt();
-        int type = buffer.getByte() & 0xFF;
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_VERSION) {
             if (id < SFTP_V3) {
@@ -364,7 +364,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected void checkStatus(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -384,7 +384,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected String checkHandle(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -404,7 +404,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected Attributes checkAttributes(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -423,7 +423,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected String checkOneName(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -475,7 +475,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
                 attrs.mtime = buffer.getInt();
             }
         } else if (version >= SFTP_V4) {
-            attrs.type = buffer.getByte();
+            attrs.type = buffer.getUByte();
             if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
                 attrs.flags.add(Attribute.Size);
                 attrs.size = buffer.getLong();
@@ -596,7 +596,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
                 }
             }
             buffer.putInt(flags);
-            buffer.putByte(attributes.type);
+            buffer.putByte((byte) attributes.type);
             if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
                 buffer.putLong(attributes.size);
             }
@@ -757,7 +757,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected int checkData(Buffer buffer, int dstoff, byte[] dst) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -836,7 +836,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
 
     protected DirEntry[] checkDir(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
index 8b18c2f..d7ded06 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
@@ -90,7 +90,7 @@ public interface SftpClient extends SubsystemClient {
     public static class Attributes {
         public final Set<Attribute> flags = EnumSet.noneOf(Attribute.class);
         public long size;
-        public byte type;
+        public int type;
         public int uid;
         public int gid;
         public int perms;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/Service.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Service.java b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
index 2339c4c..a70de53 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Service.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
@@ -37,10 +37,11 @@ public interface Service extends Closeable {
 
     /**
      * Service the request.
-     * @param buffer
-     * @throws Exception
+     * @param cmd The incoming command type
+     * @param buffer The {@link Buffer} containing optional command parameters
+     * @throws Exception If failed to process the command
      */
-    void process(byte cmd, Buffer buffer) throws Exception;
+    void process(int cmd, Buffer buffer) throws Exception;
 
     /**
      * Close the service.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
index 84b96a3..cb70913 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
@@ -69,7 +69,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         buffer.putBuffer(message);
         Proxy proxy = proxies.get(session);
         if (proxy == null) {
-            int version = buffer.getByte();
+            int version = buffer.getUByte();
             if (version == 0x04) {
                 proxy = new Socks4(session);
             } else if (version == 0x05) {
@@ -112,11 +112,11 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         }
 
         protected int getUByte(Buffer buffer) {
-            return buffer.getByte() & 0xFF;
+            return buffer.getUByte();
         }
 
         protected int getUShort(Buffer buffer) {
-            return (getUByte(buffer) << 8) + getUByte(buffer);
+            return (getUByte(buffer) << Byte.SIZE) + getUByte(buffer);
         }
     }
 
@@ -132,7 +132,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         @Override
         protected void onMessage(Buffer buffer) throws IOException {
             if (channel == null) {
-                int cmd = buffer.getByte();
+                int cmd = buffer.getUByte();
                 if (cmd != 1) {
                     throw new IllegalStateException("Unsupported socks command: " + cmd);
                 }
@@ -233,16 +233,16 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
                 if (version != 0x05) {
                     throw new IllegalStateException("Unexpected version: " + version);
                 }
-                int cmd = buffer.getByte();
+                int cmd = buffer.getUByte();
                 if (cmd != 1) { // establish a TCP/IP stream connection
                     throw new IllegalStateException("Unsupported socks command: " + cmd);
                 }
-                final int res = buffer.getByte();
+                final int res = buffer.getUByte();
                 if (res != 0) {
-                    log.debug("No zero reserved value: " + (res & 0x00FF));
+                    log.debug("No zero reserved value: " + res);
                 }
 
-                int type = buffer.getByte();
+                int type = buffer.getUByte();
                 String host;
                 if (type == 0x01) {
                     host = Integer.toString(getUByte(buffer)) + "."

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/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 ab52948..109ffb1 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
@@ -155,7 +155,7 @@ public abstract class AbstractConnectionService extends CloseableUtils.AbstractI
     }
 
     @Override
-    public void process(byte cmd, Buffer buffer) throws Exception {
+    public void process(int cmd, Buffer buffer) throws Exception {
         switch (cmd) {
             case SSH_MSG_CHANNEL_OPEN:
                 channelOpen(buffer);
@@ -320,7 +320,7 @@ public abstract class AbstractConnectionService extends CloseableUtils.AbstractI
         Channel channel = channels.get(Integer.valueOf(recipient));
         if (channel == null) {
             buffer.rpos(buffer.rpos() - 5);
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             throw new SshException("Received " + cmd + " on unknown channel " + recipient);
         }
         return channel;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index fd1655c..ed8aced 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -328,7 +328,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     }
 
     protected void doHandleMessage(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         switch (cmd) {
             case SSH_MSG_DISCONNECT: {
                 int code = buffer.getInt();
@@ -443,7 +443,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         checkRekey();
     }
 
-    protected void validateKexState(byte cmd, KexState expected) {
+    protected void validateKexState(int cmd, KexState expected) {
         KexState actual = kexState.get();
         if (!expected.equals(actual)) {
             throw new IllegalStateException("Received KEX command=" + cmd + " while in state=" + actual + " instead of " + expected);
@@ -778,7 +778,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
                     // Increment incoming packet sequence number
                     seqi = (seqi + 1) & 0xffffffffL;
                     // Get padding
-                    byte pad = decoderBuffer.getByte();
+                    int pad = decoderBuffer.getUByte();
                     Buffer buf;
                     int wpos = decoderBuffer.wpos();
                     // Decompress if needed

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
index 41c3a1a..431085a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
@@ -228,6 +228,7 @@ public final class SftpConstants {
     public static final String EXT_SUPPORTED = "supported";
     public static final String EXT_SUPPORTED2 = "supported2";
     public static final String EXT_VERSELECT = "version-select";
+    public static final String EXT_COPYFILE = "copy-file";
 
     private SftpConstants() {
         throw new UnsupportedOperationException("No instance");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
index 0dd33ea..d64bebc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
@@ -40,7 +40,9 @@ public final class ParserUtils {
                     Arrays.<ExtensionParser<?>>asList(
                             VendorIdParser.INSTANCE,
                             NewlineParser.INSTANCE,
-                            VersionsParser.INSTANCE
+                            VersionsParser.INSTANCE,
+                            SupportedParser.INSTANCE,
+                            Supported2Parser.INSTANCE
                     ));
 
     private static final Map<String,ExtensionParser<?>> parsersMap = new TreeMap<String,ExtensionParser<?>>(String.CASE_INSENSITIVE_ORDER) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/Supported2Parser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/Supported2Parser.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/Supported2Parser.java
new file mode 100644
index 0000000..f8e3fba
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/Supported2Parser.java
@@ -0,0 +1,91 @@
+/*
+ * 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.subsystem.sftp.extensions;
+
+import java.util.Collection;
+
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.subsystem.sftp.extensions.Supported2Parser.Supported2;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+
+/**
+ * Parses the &quot;supported2&quot; extension as defined in 
+ * <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-10">DRAFT 13 section 5.4</A>
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class Supported2Parser extends AbstractParser<Supported2> {
+    /**
+     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+     * @see <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-10">DRAFT 13 section 5.4</A>
+     */
+    public static class Supported2 {
+        public int supportedAttributeMask;
+        public int supportedAttributeBits;
+        public int supportedOpenFlags;
+        public int supportedAccessMask;
+        public int maxReadSize;
+        public short supportedOpenBlockVector;
+        public short supportedBlock;
+//        uint32 attrib-extension-count
+        public Collection<String> attribExtensionNames;
+//        uint32 extension-count
+        public Collection<String> extensionNames;
+        
+        @Override
+        public String toString() {
+            return "attrsMask=0x" + Integer.toHexString(supportedAttributeMask)
+                 + ",attrsBits=0x" + Integer.toHexString(supportedAttributeBits)
+                 + ",openFlags=0x" + Integer.toHexString(supportedOpenFlags)
+                 + ",accessMask=0x" + Integer.toHexString(supportedAccessMask)
+                 + ",maxRead=" + maxReadSize
+                 + ",openBlock=0x" + Integer.toHexString(supportedOpenBlockVector & 0xFFFF)
+                 + ",block=" + Integer.toHexString(supportedBlock & 0xFFFF)
+                 + ",attribs=" + attribExtensionNames
+                 + ",exts=" + extensionNames
+                 ;
+        }
+    }
+    
+    public static final Supported2Parser INSTANCE = new Supported2Parser();
+
+    public Supported2Parser() {
+        super(SftpConstants.EXT_SUPPORTED2);
+    }
+
+    @Override
+    public Supported2 parse(byte[] input, int offset, int len) {
+        return parse(new ByteArrayBuffer(input, offset, len));
+    }
+    
+    public Supported2 parse(Buffer buffer) {
+        Supported2 sup2 = new Supported2();
+        sup2.supportedAttributeMask = buffer.getInt();
+        sup2.supportedAttributeBits = buffer.getInt();
+        sup2.supportedOpenFlags = buffer.getInt();
+        sup2.supportedAccessMask = buffer.getInt();
+        sup2.maxReadSize = buffer.getInt();
+        sup2.supportedOpenBlockVector = buffer.getShort();
+        sup2.supportedBlock = buffer.getShort();
+        sup2.attribExtensionNames = buffer.getStringList(true);
+        sup2.extensionNames = buffer.getStringList(true);
+        return sup2;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/SupportedParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/SupportedParser.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/SupportedParser.java
new file mode 100644
index 0000000..fc13c49
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/SupportedParser.java
@@ -0,0 +1,80 @@
+/*
+ * 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.subsystem.sftp.extensions;
+
+import java.util.Collection;
+
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.subsystem.sftp.extensions.SupportedParser.Supported;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+
+/**
+ * Parses the &quot;supported&quot; extension as defined in
+ * <A HREF="http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt">DRAFT 05 - section 4.4</A>
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SupportedParser extends AbstractParser<Supported> {
+    /**
+     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+     * @see <A HREF="http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt">DRAFT 05 - section 4.4</A>
+     */
+    public static class Supported {
+        public int supportedAttributeMask;
+        public int supportedAttributeBits;
+        public int supportedOpenFlags;
+        public int supportedAccessMask;
+        public int maxReadSize;
+        public Collection<String> extensionNames;
+        
+        @Override
+        public String toString() {
+            return "attrsMask=0x" + Integer.toHexString(supportedAttributeMask)
+                 + ",attrsBits=0x" + Integer.toHexString(supportedAttributeBits)
+                 + ",openFlags=0x" + Integer.toHexString(supportedOpenFlags)
+                 + ",accessMask=0x" + Integer.toHexString(supportedAccessMask)
+                 + ",maxReadSize=" + maxReadSize
+                 + ",extensions=" + extensionNames
+                 ;
+        }
+    }
+
+    public static final SupportedParser INSTANCE = new SupportedParser();
+
+    public SupportedParser() {
+        super(SftpConstants.EXT_SUPPORTED);
+    }
+
+    @Override
+    public Supported parse(byte[] input, int offset, int len) {
+        return parse(new ByteArrayBuffer(input, offset, len));
+    }
+
+    public Supported parse(Buffer buffer) {
+        Supported sup = new Supported();
+        sup.supportedAttributeMask = buffer.getInt();
+        sup.supportedAttributeBits = buffer.getInt();
+        sup.supportedOpenFlags = buffer.getInt();
+        sup.supportedAccessMask = buffer.getInt();
+        sup.maxReadSize = buffer.getInt();
+        sup.extensionNames = buffer.getStringList(false);
+        return sup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/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 b4c507f..bada2de 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
@@ -43,7 +43,11 @@ import java.security.spec.ECPublicKeySpec;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.RSAPrivateCrtKeySpec;
 import java.security.spec.RSAPublicKeySpec;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Objects;
 
 import org.apache.sshd.common.SshException;
@@ -104,6 +108,10 @@ public abstract class Buffer implements Readable {
        Read methods
      ======================*/
 
+    public int getUByte() {
+        return getByte() & 0xFF;
+    }
+
     public byte getByte() {
         // TODO use Byte.BYTES for JDK-8
         ensureAvailable(Byte.SIZE / Byte.SIZE);
@@ -111,6 +119,16 @@ public abstract class Buffer implements Readable {
         return workBuf[0];
     }
 
+    public short getShort() {
+        // TODO use Short.BYTES for JDK-8
+        ensureAvailable(Short.SIZE / Byte.SIZE);
+        getRawBytes(workBuf, 0, Short.SIZE / Byte.SIZE);
+        short v = (short) (((workBuf[1] << Byte.SIZE) & 0xFF00)
+                         | ((workBuf[0] ) & 0xF))
+                ;
+        return v;
+    }
+
     public int getInt() {
         return (int) getUInt();
     }
@@ -146,6 +164,89 @@ public abstract class Buffer implements Readable {
         return getString(StandardCharsets.UTF_8);
     }
 
+    /**
+     * @param usePrependedLength If {@code true} then there is a 32-bit
+     * value indicating the number of strings to read. Otherwise, the
+     * method will use a &quot;greedy&quot; reading of strings while more
+     * data available
+     * @return A {@link Collection} of the read strings
+     * @see #getStringList(boolean, Charset)
+     */
+    public Collection<String> getStringList(boolean usePrependedLength) {
+        return getStringList(usePrependedLength, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * @param usePrependedLength If {@code true} then there is a 32-bit
+     * value indicating the number of strings to read. Otherwise, the
+     * method will use a &quot;greedy&quot; reading of strings while more
+     * data available
+     * @param charset The {@link Charset} to use for the string
+     * @return A {@link Collection} of the read strings
+     * @see {@link #getStringList(int, Charset)}
+     * @see {@link #getAvailableStrings()} 
+     */
+    public Collection<String> getStringList(boolean usePrependedLength, Charset charset) {
+        if (usePrependedLength) {
+            int count = getInt();
+            return getStringList(count, charset);
+        } else {
+            return getAvailableStrings(charset);
+        }
+    }
+
+    /**
+     * @return The remaining data as a list of strings
+     * @see #getAvailableStrings(Charset)
+     */
+    public Collection<String> getAvailableStrings() {
+        return getAvailableStrings(StandardCharsets.UTF_8);
+    }
+
+    /**
+     * @param charset The {@link Charset} to use for the strings
+     * @return The remaining data as a list of strings
+     * @see #available()
+     * @see #getString(Charset)
+     */
+    public Collection<String> getAvailableStrings(Charset charset) {
+        Collection<String> list = new LinkedList<String>();
+        while(available() > 0) {
+            String s = getString(charset);
+            list.add(s);
+        }
+        
+        return list;
+    }
+
+    /**
+     * @param count The <U>exact</V> number of strings to read - can be zero
+     * @return A {@link List} with the specified number of strings
+     * @see #getStringList(int, Charset)
+     */
+    public List<String> getStringList(int count) {
+        return getStringList(count, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * @param count The <U>exact</V> number of strings to read - can be zero
+     * @param charset The {@link Charset} of the strings
+     * @return A {@link List} with the specified number of strings
+     */
+    public List<String> getStringList(int count, Charset charset) {
+        if (count == 0) {
+            return Collections.emptyList();
+        }
+        
+        List<String> list = new ArrayList<String>(count);
+        for (int index = 0; index < count; index++) {
+            String s = getString(charset);
+            list.add(s);
+        }
+        
+        return list;
+    }
+    
     public abstract String getString(Charset charset);
 
     public BigInteger getMPInt() {
@@ -386,22 +487,33 @@ public abstract class Buffer implements Readable {
     }
 
     /**
-     * Encodes the {@link Objects#toString(Object)} value of each member
-     * @param objects The objects to be encoded in the buffer
-     * @see #putStringList(Collection, Charset)
+     * Encodes the {@link Objects#toString(Object)} value of each member.
+     * @param objects The objects to be encoded in the buffer - OK if
+     * {@code null}/empty
+     * @param prependLength If {@code true} then the list is preceded by
+     * a 32-bit count of the number of members in the list 
+     * @see #putStringList(Collection, Charset, boolean)
      */
-    public void putStringList(Collection<?> objects) {
-        putStringList(objects, StandardCharsets.UTF_8);
+    public void putStringList(Collection<?> objects, boolean prependLength) {
+        putStringList(objects, StandardCharsets.UTF_8, prependLength);
     }
 
     /**
      * Encodes the {@link Objects#toString(Object)} value of each member
-     * @param objects The objects to be encoded in the buffer
+     * @param objects The objects to be encoded in the buffer - OK if
+     * {@code null}/empty
      * @param charset The {@link Charset} to use for encoding
+     * @param prependLength If {@code true} then the list is preceded by
+     * a 32-bit count of the number of members in the list 
      * @see #putString(String, Charset)
      */
-    public void putStringList(Collection<?> objects, Charset charset) {
-        if (GenericUtils.isEmpty(objects)) {
+    public void putStringList(Collection<?> objects, Charset charset, boolean prependLength) {
+        int numObjects = GenericUtils.size(objects);
+        if (prependLength) {
+            putInt(numObjects);
+        }
+
+        if (numObjects <= 0) {
             return;
         }
         

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
index 4550433..7b37d50 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.CopyOption;
 import java.nio.file.FileSystem;
 import java.nio.file.Files;
 import java.nio.file.LinkOption;
@@ -47,6 +48,7 @@ import org.apache.sshd.common.util.OsUtils;
  */
 public final class IoUtils {
     public static final OpenOption[] EMPTY_OPEN_OPTIONS = new OpenOption[0];
+    public static final CopyOption[] EMPTY_COPY_OPTIONS = new CopyOption[0];
     public static final LinkOption[] EMPTY_LINK_OPTIONS = new LinkOption[0];
     private static final LinkOption[] NO_FOLLOW_OPTIONS = new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
index 0bd506c..0396b35 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
@@ -63,7 +63,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
             session.writePacket(buffer);
             return null;
         } else {
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             if (cmd != SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE) {
                 throw new SshException("Received unexpected message: " + cmd);
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
index 9495c34..aab20d4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
@@ -104,7 +104,7 @@ public class UserAuthGSS extends AbstractUserAuth {
         }
         else
         {
-            byte msg = buffer.getByte();
+            int msg = buffer.getUByte();
             if (!((msg == SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE)
                || (msg == SshConstants.SSH_MSG_USERAUTH_GSSAPI_MIC) && context.isEstablished())) {
                 throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR,

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/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 c3800cc..99512ac 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
@@ -95,7 +95,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
 
     @Override
     public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
 
         if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
             log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/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 75efab9..8edc61c 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
@@ -81,7 +81,7 @@ public class DHGServer extends AbstractDHServerKeyExchange {
 
     @Override
     public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
+        int cmd = buffer.getUByte();
         if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {
             throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, 
                                    "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index 0421c61..7f64dce 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -105,7 +105,7 @@ public class ServerUserAuthService extends CloseableUtils.AbstractCloseable impl
     }
 
     @Override
-    public void process(byte cmd, Buffer buffer) throws Exception {
+    public void process(int cmd, Buffer buffer) throws Exception {
         Boolean authed = Boolean.FALSE;
 
         if (cmd == SshConstants.SSH_MSG_USERAUTH_REQUEST) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index f5c8ba9..0ee0421 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -145,7 +145,8 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
                 Collections.unmodifiableSet(
                         GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER,
                                 Arrays.asList(
-                                        SftpConstants.EXT_VERSELECT
+                                        SftpConstants.EXT_VERSELECT,
+                                        SftpConstants.EXT_COPYFILE
                                 )));
 
     static {
@@ -497,7 +498,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
 
     protected void process(Buffer buffer) throws IOException {
         int length = buffer.getInt();
-        int type = buffer.getByte();
+        int type = buffer.getUByte();
         int id = buffer.getInt();
         if (log.isDebugEnabled()) {
             log.debug("process(length={}, type={}, id={})",
@@ -598,6 +599,9 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
             case SftpConstants.EXT_VERSELECT:
                 doVersionSelect(buffer, id);
                 break;
+            case SftpConstants.EXT_COPYFILE:
+                doCopyFile(buffer, id);
+                break;
             default:
                 log.info("Received unsupported SSH_FXP_EXTENDED({})", extension);
                 sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(" + extension + ") is unsupported or not implemented");
@@ -819,14 +823,14 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
                        oldPath, newPath, Integer.toHexString(flags));
         }
 
+        List<CopyOption> opts = new ArrayList<>();
+        if ((flags & SSH_FXP_RENAME_ATOMIC) != 0) {
+            opts.add(StandardCopyOption.ATOMIC_MOVE);
+        }
+        if ((flags & SSH_FXP_RENAME_OVERWRITE) != 0) {
+            opts.add(StandardCopyOption.REPLACE_EXISTING);
+        }
         try {
-            List<CopyOption> opts = new ArrayList<>();
-            if ((flags & SSH_FXP_RENAME_ATOMIC) != 0) {
-                opts.add(StandardCopyOption.ATOMIC_MOVE);
-            }
-            if ((flags & SSH_FXP_RENAME_OVERWRITE) != 0) {
-                opts.add(StandardCopyOption.REPLACE_EXISTING);
-            }
             Path o = resolveFile(oldPath);
             Path n = resolveFile(newPath);
             Files.move(o, n, opts.toArray(new CopyOption[opts.size()]));
@@ -836,6 +840,31 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
         }
     }
 
+    // see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-6
+    protected void doCopyFile(Buffer buffer, int id) throws IOException {
+        String srcFile = buffer.getString();
+        String dstFile = buffer.getString();
+        boolean overwriteDestination = buffer.getBoolean();
+        if (log.isDebugEnabled()) {
+            log.debug("SSH_FXP_EXTENDED[{}] (src={}, dst={}, overwrite=0x{})",
+                       SftpConstants.EXT_COPYFILE, srcFile, dstFile, Boolean.valueOf(overwriteDestination));
+        }
+        
+        CopyOption[] opts = overwriteDestination
+                ? new CopyOption[] { StandardCopyOption.REPLACE_EXISTING }
+                : IoUtils.EMPTY_COPY_OPTIONS
+                ;
+
+        try {
+            Path src = resolveFile(srcFile);
+            Path dst = resolveFile(dstFile);
+            Files.copy(src, dst, opts);
+            sendStatus(id, SSH_FX_OK, "");
+        } catch (IOException e) {
+            sendStatus(id, e);
+        }
+    }
+
     protected void doStat(Buffer buffer, int id) throws IOException {
         String path = buffer.getString();
         int flags = SSH_FILEXFER_ATTR_ALL;
@@ -877,7 +906,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
                 // Read control byte
                 int control = 0;
                 if (buffer.available() > 0) {
-                    control = buffer.getByte();
+                    control = buffer.getUByte();
                 }
                 List<String> paths = new ArrayList<>();
                 while (buffer.available() > 0) {
@@ -1423,7 +1452,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
         // max-read-size
         buffer.putInt(0);
         // supported extensions
-        buffer.putStringList(extras);
+        buffer.putStringList(extras, false);
         
         BufferUtils.updateLengthPlaceholder(buffer, lenPos);
     }
@@ -1436,6 +1465,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
      * @param extras The extra extensions that are available and can be reported
      * - may be {@code null}/empty
      * @see SftpConstants#EXT_SUPPORTED
+     * @see <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-10">DRAFT 13 section 5.4</A>
      */
     protected void appendSupported2Extension(Buffer buffer, Collection<String> extras) {
         buffer.putString(EXT_SUPPORTED2);
@@ -1459,12 +1489,10 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
         buffer.putShort(0);
         // supported-block-vector
         buffer.putShort(0);
-        // attrib-extension-count
-        buffer.putInt(0);
-        // extension-count
-        buffer.putInt(0);
-        // supported extensions
-        buffer.putStringList(extras);
+        // attrib-extension-count + attributes name
+        buffer.putStringList(Collections.<String>emptyList(), true);
+        // extension-count + supported extensions
+        buffer.putStringList(extras, true);
 
         BufferUtils.updateLengthPlaceholder(buffer, lenPos);
     }
@@ -2044,7 +2072,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
         Map<String, Object> attrs = new HashMap<>();
         int flags = buffer.getInt();
         if (version >= SFTP_V4) {
-            byte type = buffer.getByte();
+            int type = buffer.getUByte();
             switch (type) {
                 case SSH_FILEXFER_TYPE_REGULAR:
                     attrs.put("isRegular", Boolean.TRUE);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/WindowTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/WindowTest.java b/sshd-core/src/test/java/org/apache/sshd/WindowTest.java
index a97c8a0..251ea64 100644
--- a/sshd-core/src/test/java/org/apache/sshd/WindowTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/WindowTest.java
@@ -105,7 +105,7 @@ public class WindowTest extends BaseTestSupport {
                             return new ServerUserAuthService(session) {
                                 @SuppressWarnings("synthetic-access")
                                 @Override
-                                public void process(byte cmd, Buffer buffer) throws Exception {
+                                public void process(int cmd, Buffer buffer) throws Exception {
                                     authLatch.await();
                                     super.process(cmd, buffer);
                                 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
index 85fa7dc..4aebff8 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
@@ -143,7 +143,7 @@ public class ClientTest extends BaseTestSupport {
                         return new ServerUserAuthService(session) {
                             @SuppressWarnings("synthetic-access")
                             @Override
-                            public void process(byte cmd, Buffer buffer) throws Exception {
+                            public void process(int cmd, Buffer buffer) throws Exception {
                                 authLatch.await();
                                 super.process(cmd, buffer);
                             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index b4a1cef..62a142b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -34,10 +34,12 @@ import java.nio.file.FileSystem;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 import java.util.Vector;
 import java.util.concurrent.TimeUnit;
 
@@ -49,6 +51,9 @@ import org.apache.sshd.common.file.root.RootedFileSystemProvider;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.subsystem.sftp.extensions.ParserUtils;
+import org.apache.sshd.common.subsystem.sftp.extensions.Supported2Parser.Supported2;
+import org.apache.sshd.common.subsystem.sftp.extensions.SupportedParser.Supported;
+import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.io.IoUtils;
@@ -589,7 +594,7 @@ public class SftpTest extends BaseTestSupport {
                     Map<String,byte[]> extensions = sftp.getServerExtensions();
                     for (String name : new String[] {
                             SftpConstants.EXT_NEWLINE, SftpConstants.EXT_VERSIONS,
-                            // SftpConstants.EXT_VENDORID,
+                            SftpConstants.EXT_VENDORID,
                             SftpConstants.EXT_SUPPORTED, SftpConstants.EXT_SUPPORTED2
                         }) {
                         assertTrue("Missing extension=" + name, extensions.containsKey(name));
@@ -597,9 +602,15 @@ public class SftpTest extends BaseTestSupport {
                     
                     Map<String,?> data = ParserUtils.parse(extensions);
                     for (Map.Entry<String,?> de : data.entrySet()) {
-                        System.out.append('\t').append(de.getKey()).append(": ").println(de.getValue());
+                        String extName = de.getKey();
+                        Object extValue = de.getValue();
+                        System.out.append('\t').append(extName).append(": ").println(extValue);
+                        if (SftpConstants.EXT_SUPPORTED.equalsIgnoreCase(extName)) {
+                            assertSupportedExtensions(extName, ((Supported) extValue).extensionNames);
+                        } else if (SftpConstants.EXT_SUPPORTED2.equalsIgnoreCase(extName)) {
+                            assertSupportedExtensions(extName, ((Supported2) extValue).extensionNames);
+                        }
                     }
-                        
                 }
             } finally {
                 client.stop();
@@ -607,6 +618,21 @@ public class SftpTest extends BaseTestSupport {
         }
     }
 
+    private static Set<String> EXPECTED_EXTENSIONS = 
+            Collections.unmodifiableSet(
+                    GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER,
+                            Arrays.asList(
+                                    SftpConstants.EXT_VERSELECT,
+                                    SftpConstants.EXT_COPYFILE
+                            )));
+    private static void assertSupportedExtensions(String extName, Collection<String> extensionNames) {
+        assertEquals(extName + "[count]", EXPECTED_EXTENSIONS.size(), GenericUtils.size(extensionNames));
+
+        for (String name : EXPECTED_EXTENSIONS) {
+            assertTrue(extName + " - missing " + name, extensionNames.contains(name));
+        }
+    }
+
     @Test
     public void testCreateSymbolicLink() throws Exception {
         // Do not execute on windows as the file system does not support symlinks

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/deprecated/ClientUserAuthServiceOld.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/ClientUserAuthServiceOld.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/ClientUserAuthServiceOld.java
index 42c4a5a..98602fa 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/ClientUserAuthServiceOld.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/ClientUserAuthServiceOld.java
@@ -91,7 +91,7 @@ public class ClientUserAuthServiceOld extends CloseableUtils.AbstractCloseable i
     }
 
     @Override
-    public void process(byte cmd, Buffer buffer) throws Exception {
+    public void process(int cmd, Buffer buffer) throws Exception {
         if (this.authFuture.isSuccess()) {
             throw new IllegalStateException("UserAuth message delivered to authenticated client");
         } else if (this.authFuture.isDone()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
index 74ce63b..e0f0b12 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
@@ -96,7 +96,7 @@ public class UserAuthAgent extends AbstractUserAuth {
                 return Result.Failure;
             }
         } else {
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
                 log.info("Received SSH_MSG_USERAUTH_SUCCESS");
                 agent.close();
@@ -112,7 +112,7 @@ public class UserAuthAgent extends AbstractUserAuth {
                 }
             } else {
                 // TODO: check packets
-                log.info("Received unknown packet: {}", Byte.valueOf(cmd));
+                log.info("Received unknown packet: {}", Integer.valueOf(cmd));
                 return Result.Continued;
             }
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
index 3386428..947d125 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
@@ -59,7 +59,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
             session.writePacket(buffer);
             return Result.Continued;
         } else {
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             switch (cmd) {
                 case SSH_MSG_USERAUTH_INFO_REQUEST:
                     log.debug("Received SSH_MSG_USERAUTH_INFO_REQUEST");
@@ -72,7 +72,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
                     boolean[] echo = new boolean[num];
                     for (int i = 0; i < num; i++) {
                         prompt[i] = buffer.getString();
-                        echo[i] = (buffer.getByte() != 0);
+                        echo[i] = buffer.getBoolean();
                     }
                     log.debug("Promt: {}", Arrays.toString(prompt));
                     log.debug("Echo: {}", echo);
@@ -107,7 +107,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
                     log.debug("Received SSH_MSG_USERAUTH_FAILURE");
                     return Result.Failure;
                 default:
-                    log.debug("Received unknown packet {}", Byte.valueOf(cmd));
+                    log.debug("Received unknown packet {}", Integer.valueOf(cmd));
                     return Result.Continued;
             }
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
index 4dde6cc..53a77c8 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
@@ -50,7 +50,7 @@ public class UserAuthPassword extends AbstractUserAuth {
             session.writePacket(buffer);
             return Result.Continued;
         } else {
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
                 log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                 return Result.Success;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9d066221/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
index f303017..c3fbae7 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
@@ -92,7 +92,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
                 throw (IOException) new IOException("Error performing public key authentication").initCause(e);
             }
         } else {
-            byte cmd = buffer.getByte();
+            int cmd = buffer.getUByte();
             if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
                 log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                 return Result.Success;
@@ -100,7 +100,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
                 log.debug("Received SSH_MSG_USERAUTH_FAILURE");
                 return Result.Failure;
             } else {
-                log.debug("Received unknown packet {}", Byte.valueOf(cmd));
+                log.debug("Received unknown packet {}", Integer.valueOf(cmd));
                 // TODO: check packets
                 return Result.Continued;
             }