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 2022/02/08 16:37:37 UTC

[mina-sshd] 02/05: [SSHD-1244] Re-defined channel identifiers as long rather than int to align with protocol UINT32 definition

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 070c11ddc2fef5ad50a01709ca27598598cade85
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri Feb 4 12:56:53 2022 +0200

    [SSHD-1244] Re-defined channel identifiers as long rather than int to align with protocol UINT32 definition
---
 CHANGES.md                                         | 27 ++++++++++++++-
 .../common/config/keys/OpenSshCertificate.java     | 14 +++++---
 .../sshd/common/kex/extension/KexExtensions.java   |  2 ++
 .../apache/sshd/common/session/SessionContext.java | 11 ++++++
 .../org/apache/sshd/common/util/buffer/Buffer.java | 21 +++++++-----
 .../sshd/common/util/buffer/BufferUtils.java       |  4 +--
 ...elIdTrackingUnknownChannelReferenceHandler.java | 12 +++----
 .../sshd/client/channel/AbstractClientChannel.java | 10 +++---
 .../sshd/client/channel/ChannelDirectTcpip.java    | 10 +++---
 .../apache/sshd/client/channel/ChannelExec.java    |  2 +-
 .../apache/sshd/client/channel/ChannelShell.java   |  2 +-
 .../sshd/client/channel/ChannelSubsystem.java      |  2 +-
 .../client/channel/PtyCapableChannelSession.java   |  2 +-
 .../sshd/client/session/AbstractClientSession.java |  8 ++---
 .../sshd/common/channel/AbstractChannel.java       | 24 ++++++-------
 .../common/channel/BufferedIoOutputStream.java     | 12 ++++---
 .../org/apache/sshd/common/channel/Channel.java    | 26 +++++++--------
 .../common/channel/ChannelAsyncOutputStream.java   |  7 ++--
 .../sshd/common/channel/ChannelListener.java       |  2 +-
 .../sshd/common/channel/ChannelOutputStream.java   |  6 ++--
 .../SshChannelBufferedOutputException.java         |  6 ++--
 .../exception/SshChannelClosedException.java       |  6 ++--
 .../channel/exception/SshChannelException.java     | 12 +++----
 .../exception/SshChannelNotFoundException.java     |  6 ++--
 .../channel/exception/SshChannelOpenException.java |  4 +--
 .../sshd/common/forward/TcpipClientChannel.java    | 10 +++---
 .../DefaultServerKexExtensionHandler.java          |  2 ++
 .../sshd/common/session/ConnectionService.java     |  4 +--
 .../session/UnknownChannelReferenceHandler.java    |  2 +-
 .../session/helpers/AbstractConnectionService.java | 39 +++++++++++-----------
 .../DefaultUnknownChannelReferenceHandler.java     |  6 ++--
 .../sshd/common/session/helpers/SessionHelper.java |  2 +-
 .../sshd/server/channel/AbstractServerChannel.java |  6 ++--
 .../sshd/server/forward/TcpipServerChannel.java    |  2 +-
 .../sshd/server/x11/ChannelForwardedX11.java       |  8 ++---
 .../java/org/apache/sshd/client/ClientTest.java    | 10 +++---
 .../apache/sshd/common/channel/WindowInitTest.java |  4 +--
 .../org/apache/sshd/common/channel/WindowTest.java |  2 +-
 .../sshd/common/channel/WindowTimeoutTest.java     |  4 +--
 .../sshd/util/test/AsyncEchoShellFactory.java      |  2 +-
 .../org/apache/sshd/util/test/BogusChannel.java    |  4 +--
 .../org/apache/sshd/sftp/client/fs/SftpPath.java   |  1 +
 .../sshd/sftp/client/impl/AbstractSftpClient.java  |  1 +
 .../sshd/sftp/client/impl/DefaultSftpClient.java   |  2 +-
 .../sftp/common/extensions/Supported2Parser.java   | 10 +++---
 .../sftp/common/extensions/SupportedParser.java    |  9 ++---
 .../sftp/server/AbstractSftpSubsystemHelper.java   |  5 +--
 .../org/apache/sshd/sftp/server/SftpSubsystem.java |  6 ++--
 .../org/apache/sshd/sftp/client/ClientTest.java    |  8 ++---
 .../java/org/apache/sshd/sftp/client/SftpTest.java |  4 +--
 50 files changed, 227 insertions(+), 164 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 9063114..08c9d71 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -20,7 +20,9 @@
 
 ## Potential compatibility issues
 
-* A **new** SFTP configuration property has been introduced that limits the maximum amount of data that can be sent in a single *SSH_FXP_WRITE* packet - default=256KB
+Changes that may affect existing code
+
+### A **new** SFTP configuration property has been introduced that limits the maximum amount of data that can be sent in a single *SSH_FXP_WRITE* packet - default=256KB
 
 ```java
     /**
@@ -34,6 +36,27 @@
 This might cause SFTP write failures for clients that might have sent larger buffers and they have been accepted so far. If this happens, simply increase
 this value (though the choice of 256KB should be compatible with the vast majority of clients).
 
+### SSH channel identifiers have been changed to use *long* instead of *int* in order to align them with the standard that required them to be *UINT32* values.
+
+The relevant API(s) have been modified accordingly - which may cause a few incompatibility issues with code that extends/implements existing `Channel` classes
+and interfaces.
+
+### *long* used instead of *int* in most encoded/decoded packets that are specified as being *UINT32*
+
+There are several exceptions to this rule:
+
+* The SFTP packet *id* field - an "opaque" value anyway, not used for allocation or indexing anyway
+
+* Various flags and mask field - there is no reason to encapsulate them into a *long* value since they do not represent a cardinal number of 32 bits
+
+* Various status code fields - ditto.
+
+* Cases where the value serves as argument for allocation of other data structures based on its value - e.g., arrays, lists. This was
+done for *convenience* reasons since Java does not support unsigned array/list sizes. In such cases, special validation code was applied
+to make sure the requested value does not exceed `Integer#MAX_VALUE` (sometimes even less) in order to protected the code from malicious
+or malformed packets. It is important to bear in mind that in the vast majority of the cases we do not want to be able to allocate arrays
+or lists having billions of elements as it would almost definitely cause out-of-memory issues.
+
 ## Minor code helpers
 
 ## Behavioral changes and enhancements
@@ -41,6 +64,8 @@ this value (though the choice of 256KB should be compatible with the vast majori
 * [SSHD-1231](https://issues.apache.org/jira/browse/SSHD-1231) Public key authentication: wrong signature algorithm used (ed25519 key with ssh-rsa signature)
 * [SSHD-1233](https://issues.apache.org/jira/browse/SSHD-1233) Added support for "limits@openssh.com" SFTP extension
 * [SSHD-1244](https://issues.apache.org/jira/browse/SSHD-1244) Fixed channel window adjustment handling of large UINT32 values
+* [SSHD-1244](https://issues.apache.org/jira/browse/SSHD-1244) Re-defined channel identifiers as `long` rather than `int` to align with protocol UINT32 definition
+
 
 
 
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/OpenSshCertificate.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/OpenSshCertificate.java
index 525c4f6..c794cf7 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/OpenSshCertificate.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/OpenSshCertificate.java
@@ -20,7 +20,9 @@ package org.apache.sshd.common.config.keys;
 
 import java.security.PrivateKey;
 import java.security.PublicKey;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
@@ -37,21 +39,25 @@ public interface OpenSshCertificate extends PublicKey, PrivateKey {
 
     /**
      * {@link OpenSshCertificate}s have a type indicating whether the certificate if for a host key (certifying a host
-     * identity) or for a user key (certifying a user identity).
+     * identity) or for a user key (certifying a user identity). <B>Note:</B> values order is significant
      */
     enum Type {
-
         /** User key certificate. */
         USER,
         /** Host key certificate. */
-        HOST;
+        HOST,
+        ;
+
+        public static final List<Type> VALUES = Collections.unmodifiableList(Arrays.asList(values()));
 
         public int getCode() {
             return ordinal() + 1;
         }
 
         public static Type fromCode(int code) {
-            return Type.values()[code - 1];
+            ValidateUtils.checkTrue((code > 0) && (code <= VALUES.size()),
+                    "Invalid type code: %d", code);
+            return VALUES.get(code - 1);
         }
     }
 
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
index af82982..9fac45c 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
@@ -143,6 +143,8 @@ public final class KexExtensions {
      */
     public static List<Map.Entry<String, ?>> parseExtensions(Buffer buffer) throws IOException {
         int count = buffer.getInt();
+        // Protect agains malicious packets
+        ValidateUtils.checkTrue(count >= 0, "Invalid extensions count: %d", count);
         if (count == 0) {
             return Collections.emptyList();
         }
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
index 622c5db..ad5d2c8 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import org.apache.sshd.common.AttributeStore;
 import org.apache.sshd.common.Closeable;
+import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.auth.UsernameHolder;
 import org.apache.sshd.common.cipher.BuiltinCiphers;
 import org.apache.sshd.common.cipher.CipherInformation;
@@ -31,6 +32,7 @@ import org.apache.sshd.common.kex.KexProposalOption;
 import org.apache.sshd.common.kex.KexState;
 import org.apache.sshd.common.mac.MacInformation;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.net.ConnectionEndpointsIndicator;
 
 /**
@@ -207,4 +209,13 @@ public interface SessionContext
 
         return true;
     }
+
+    static boolean isValidSessionPayloadSize(long value) {
+        return (value >= 0L) && (value < (Integer.MAX_VALUE - SshConstants.SSH_PACKET_HEADER_LEN - 8 /* some padding */));
+    }
+
+    static long validateSessionPayloadSize(long value, String format) {
+        ValidateUtils.checkTrue(isValidSessionPayloadSize(value), format, value);
+        return value;
+    }
 }
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
index c7c9df5..7a2fa6d 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
@@ -478,6 +478,11 @@ public abstract class Buffer implements Readable {
     }
 
     public byte[] getBytes() {
+        /*
+         * NOTE: technically we should support UINT32 but
+         * we cannot support them since an array of bytes
+         * can be allocated only with and integer value
+         */
         int reqLen = getInt();
         int len = ensureAvailable(reqLen);
         byte[] b = new byte[len];
@@ -698,11 +703,6 @@ public abstract class Buffer implements Readable {
         putRawBytes(workBuf, 0, Short.BYTES);
     }
 
-    /**
-     * Writes 32 bits
-     *
-     * @param i The 32-bit value
-     */
     public void putInt(long i) {
         BufferUtils.validateInt32Value(i, "Invalid INT32 value: %d");
         ensureCapacity(Integer.BYTES);
@@ -710,6 +710,11 @@ public abstract class Buffer implements Readable {
         putRawBytes(workBuf, 0, Integer.BYTES);
     }
 
+    /**
+     * Writes 32 bits
+     *
+     * @param i The 32-bit value
+     */
     public void putUInt(long i) {
         BufferUtils.validateUint32Value(i, "Invalid UINT32 value: %d");
         ensureCapacity(Integer.BYTES);
@@ -943,7 +948,7 @@ public abstract class Buffer implements Readable {
             putUInt(mpInt.length + 1 /* padding */);
             putByte((byte) 0);
         } else {
-            putInt(mpInt.length);
+            putUInt(mpInt.length);
         }
         putRawBytes(mpInt);
     }
@@ -961,7 +966,7 @@ public abstract class Buffer implements Readable {
         putRawPublicKey(key);
         int ow2 = wpos();
         wpos(ow);
-        putInt(ow2 - ow1);
+        putUInt(ow2 - ow1);
         wpos(ow2);
     }
 
@@ -1007,7 +1012,7 @@ public abstract class Buffer implements Readable {
             putBytes(cert.getNonce());
             putRawPublicKeyBytes(cert.getCertPubKey());
             putLong(cert.getSerial());
-            putInt(cert.getType().getCode());
+            putUInt(cert.getType().getCode());
             putString(cert.getId());
 
             ByteArrayBuffer tmpBuffer = new ByteArrayBuffer();
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/BufferUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/BufferUtils.java
index beaf150..77b201a 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/BufferUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/BufferUtils.java
@@ -656,9 +656,9 @@ public final class BufferUtils {
      * @param buffer     The {@link Buffer}
      * @param lenPos     The offset in the buffer where the length placeholder is to be update - <B>Note:</B> assumption
      *                   is that the encoded data starts <U>immediately</U> after the placeholder
-     * @param dataLength The length to update
+     * @param dataLength The length to update - a UINT32 value as a {@code long}
      */
-    public static void updateLengthPlaceholder(Buffer buffer, int lenPos, int dataLength) {
+    public static void updateLengthPlaceholder(Buffer buffer, int lenPos, long dataLength) {
         int curPos = buffer.wpos();
         buffer.wpos(lenPos);
         buffer.putUInt(dataLength);
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/session/helpers/ChannelIdTrackingUnknownChannelReferenceHandler.java b/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/session/helpers/ChannelIdTrackingUnknownChannelReferenceHandler.java
index e791d1c..7d282b9 100644
--- a/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/session/helpers/ChannelIdTrackingUnknownChannelReferenceHandler.java
+++ b/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/session/helpers/ChannelIdTrackingUnknownChannelReferenceHandler.java
@@ -41,7 +41,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
 public class ChannelIdTrackingUnknownChannelReferenceHandler
         extends DefaultUnknownChannelReferenceHandler
         implements ChannelListener {
-    public static final AttributeKey<Integer> LAST_CHANNEL_ID_KEY = new AttributeKey<>();
+    public static final AttributeKey<Long> LAST_CHANNEL_ID_KEY = new AttributeKey<>();
 
     public static final ChannelIdTrackingUnknownChannelReferenceHandler TRACKER
             = new ChannelIdTrackingUnknownChannelReferenceHandler();
@@ -52,9 +52,9 @@ public class ChannelIdTrackingUnknownChannelReferenceHandler
 
     @Override
     public void channelInitialized(Channel channel) {
-        int channelId = channel.getId();
+        long channelId = channel.getId();
         Session session = channel.getSession();
-        Integer lastTracked = session.setAttribute(LAST_CHANNEL_ID_KEY, channelId);
+        Long lastTracked = session.setAttribute(LAST_CHANNEL_ID_KEY, channelId);
         if (log.isDebugEnabled()) {
             log.debug("channelInitialized({}) updated last tracked channel ID {} => {}",
                     channel, lastTracked, channelId);
@@ -63,11 +63,11 @@ public class ChannelIdTrackingUnknownChannelReferenceHandler
 
     @Override
     public Channel handleUnknownChannelCommand(
-            ConnectionService service, byte cmd, int channelId, Buffer buffer)
+            ConnectionService service, byte cmd, long channelId, Buffer buffer)
             throws IOException {
         Session session = service.getSession();
-        Integer lastTracked = session.getAttribute(LAST_CHANNEL_ID_KEY);
-        if ((lastTracked != null) && (channelId <= lastTracked.intValue())) {
+        Long lastTracked = session.getAttribute(LAST_CHANNEL_ID_KEY);
+        if ((lastTracked != null) && (channelId <= lastTracked.longValue())) {
             // Use TRACE level in order to avoid messages flooding
             if (log.isTraceEnabled()) {
                 log.trace("handleUnknownChannelCommand({}) apply default handling for {} on channel={} (lastTracked={})",
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
index d960388..4124408 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
@@ -329,21 +329,21 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
         Window wLocal = getLocalWindow();
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN, type.length() + Integer.SIZE);
         buffer.putString(type);
-        buffer.putInt(getId());
-        buffer.putInt(wLocal.getSize());
-        buffer.putInt(wLocal.getPacketSize());
+        buffer.putUInt(getId());
+        buffer.putUInt(wLocal.getSize());
+        buffer.putUInt(wLocal.getPacketSize());
         writePacket(buffer);
         return openFuture;
     }
 
     @Override
-    public OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer) {
+    public OpenFuture open(long recipient, long rwSize, long packetSize, Buffer buffer) {
         throw new UnsupportedOperationException(
                 "open(" + recipient + "," + rwSize + "," + packetSize + ") N/A");
     }
 
     @Override
-    public void handleOpenSuccess(int recipient, long rwSize, long packetSize, Buffer buffer) {
+    public void handleOpenSuccess(long recipient, long rwSize, long packetSize, Buffer buffer) {
         setRecipient(recipient);
 
         Session session = getSession();
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelDirectTcpip.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelDirectTcpip.java
index 59c7b74..b8b2ab8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelDirectTcpip.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelDirectTcpip.java
@@ -84,13 +84,13 @@ public class ChannelDirectTcpip extends AbstractClientChannel {
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN,
                 type.length() + remoteName.length() + localName.length() + Long.SIZE);
         buffer.putString(type);
-        buffer.putInt(getId());
-        buffer.putInt(wLocal.getSize());
-        buffer.putInt(wLocal.getPacketSize());
+        buffer.putUInt(getId());
+        buffer.putUInt(wLocal.getSize());
+        buffer.putUInt(wLocal.getPacketSize());
         buffer.putString(remoteName);
-        buffer.putInt(remote.getPort());
+        buffer.putUInt(remote.getPort());
         buffer.putString(localName);
-        buffer.putInt(local.getPort());
+        buffer.putUInt(local.getPort());
         writePacket(buffer);
         return openFuture;
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
index 498ea29..f0608af 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
@@ -55,7 +55,7 @@ public class ChannelExec extends PtyCapableChannelSession {
         Session session = getSession();
         boolean wantReply = CoreModuleProperties.REQUEST_EXEC_REPLY.getRequired(this);
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, command.length() + Integer.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putString(Channel.CHANNEL_EXEC);
         buffer.putBoolean(wantReply);
         buffer.putString(command);
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
index 2fd7c4b..fe6d958 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
@@ -51,7 +51,7 @@ public class ChannelShell extends PtyCapableChannelSession {
         Session session = getSession();
         boolean wantReply = CoreModuleProperties.REQUEST_SHELL_REPLY.getRequired(this);
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, Integer.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putString(Channel.CHANNEL_SHELL);
         buffer.putBoolean(wantReply);
         addPendingRequest(Channel.CHANNEL_SHELL, wantReply);
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
index f779dcd..e8a7838 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
@@ -64,7 +64,7 @@ public class ChannelSubsystem extends ChannelSession {
         boolean wantReply = CoreModuleProperties.REQUEST_SUBSYSTEM_REPLY.getRequired(this);
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST,
                 Channel.CHANNEL_SUBSYSTEM.length() + systemName.length() + Integer.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putString(Channel.CHANNEL_SUBSYSTEM);
         buffer.putBoolean(wantReply);
         buffer.putString(systemName);
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
index 214a6d9..71e4dbf 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
@@ -232,7 +232,7 @@ public class PtyCapableChannelSession extends ChannelSession implements PtyChann
 
         Session session = getSession();
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putString("window-change");
         buffer.putBoolean(false); // want-reply
         buffer.putInt(getPtyColumns());
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
index 12cd13f..8b73180 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
@@ -383,7 +383,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
             throws IOException {
         ChannelExec channel = new ChannelExec(command, ptyConfig, env);
         ConnectionService service = getConnectionService();
-        int id = service.registerChannel(channel);
+        long id = service.registerChannel(channel);
         if (log.isDebugEnabled()) {
             log.debug("createExecChannel({})[{}] created id={} - PTY={}", this, command, id, ptyConfig);
         }
@@ -394,7 +394,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
     public ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException {
         ChannelSubsystem channel = new ChannelSubsystem(subsystem);
         ConnectionService service = getConnectionService();
-        int id = service.registerChannel(channel);
+        long id = service.registerChannel(channel);
         if (log.isDebugEnabled()) {
             log.debug("createSubsystemChannel({})[{}] created id={}", this, subsystem, id);
         }
@@ -406,7 +406,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
             throws IOException {
         ChannelDirectTcpip channel = new ChannelDirectTcpip(local, remote);
         ConnectionService service = getConnectionService();
-        int id = service.registerChannel(channel);
+        long id = service.registerChannel(channel);
         if (log.isDebugEnabled()) {
             log.debug("createDirectTcpipChannel({})[{} => {}] created id={}", this, local, remote, id);
         }
@@ -496,7 +496,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
 
         ChannelShell channel = new ChannelShell(ptyConfig, env);
         ConnectionService service = getConnectionService();
-        int id = service.registerChannel(channel);
+        long id = service.registerChannel(channel);
         if (log.isDebugEnabled()) {
             log.debug("createShellChannel({}) created id={} - PTY={}", this, id, ptyConfig);
         }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
index 69c6d24..3ee3fd2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
@@ -98,8 +98,8 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
     protected final Collection<ChannelListener> channelListeners = new CopyOnWriteArraySet<>();
     protected final ChannelListener channelListenerProxy;
 
-    private int id = -1;
-    private int recipient = -1;
+    private long id = -1L;
+    private long recipient = -1L;
     private Session sessionInstance;
     private CloseableExecutorService executor;
     private final List<RequestHandler<Channel>> requestHandlers = new CopyOnWriteArrayList<>();
@@ -155,16 +155,16 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
     }
 
     @Override
-    public int getId() {
+    public long getId() {
         return id;
     }
 
     @Override
-    public int getRecipient() {
+    public long getRecipient() {
         return recipient;
     }
 
-    protected void setRecipient(int recipient) {
+    protected void setRecipient(long recipient) {
         if (log.isDebugEnabled()) {
             log.debug("setRecipient({}) recipient={}", this, recipient);
         }
@@ -355,12 +355,12 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
                 : SshConstants.SSH_MSG_CHANNEL_FAILURE;
         Session session = getSession();
         Buffer rsp = session.createBuffer(cmd, Integer.BYTES);
-        rsp.putInt(recipient);
+        rsp.putUInt(recipient);
         return session.writePacket(rsp);
     }
 
     @Override
-    public void init(ConnectionService service, Session session, int id) throws IOException {
+    public void init(ConnectionService service, Session session, long id) throws IOException {
         if (log.isDebugEnabled()) {
             log.debug("init() service={} session={} id={}", service, session, id);
         }
@@ -436,7 +436,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
 
     @Override
     public void handleChannelRegistrationResult(
-            ConnectionService service, Session session, int channelId,
+            ConnectionService service, Session session, long channelId,
             boolean registered) {
         notifyStateChanged("registered=" + registered);
         if (registered) {
@@ -624,7 +624,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
 
                 Session s = getSession();
                 Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_CHANNEL_CLOSE, Short.SIZE);
-                buffer.putInt(getRecipient());
+                buffer.putUInt(getRecipient());
 
                 try {
                     Duration timeout = CoreModuleProperties.CHANNEL_CLOSE_TIMEOUT.getRequired(channel);
@@ -811,7 +811,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
             }
             Session s = getSession();
             Buffer rsp = s.createBuffer(SshConstants.SSH_MSG_CHANNEL_FAILURE, Integer.BYTES);
-            rsp.putInt(getRecipient());
+            rsp.putUInt(getRecipient());
             writePacket(rsp);
             return;
         }
@@ -944,7 +944,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
 
         Session s = getSession();
         Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_CHANNEL_EOF, Short.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         /*
          * The default "writePacket" does not send packets if state is not open
          * so we need to bypass it.
@@ -1012,7 +1012,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
         }
         Session s = getSession();
         Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_CHANNEL_WINDOW_ADJUST, Short.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putUInt(len);
         writePacket(buffer);
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
index 477852e..15cee93 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
@@ -45,7 +45,7 @@ import org.apache.sshd.core.CoreModuleProperties;
  */
 public class BufferedIoOutputStream extends AbstractInnerCloseable implements IoOutputStream {
     protected final Object id;
-    protected final int channelId;
+    protected final long channelId;
     protected final int maxPendingBytesCount;
     protected final Duration maxWaitForPendingWrites;
     protected final IoOutputStream out;
@@ -55,13 +55,13 @@ public class BufferedIoOutputStream extends AbstractInnerCloseable implements Io
     protected final AtomicReference<IoWriteFutureImpl> currentWrite = new AtomicReference<>();
     protected final AtomicReference<SshChannelBufferedOutputException> pendingException = new AtomicReference<>();
 
-    public BufferedIoOutputStream(Object id, int channelId, IoOutputStream out, PropertyResolver resolver) {
+    public BufferedIoOutputStream(Object id, long channelId, IoOutputStream out, PropertyResolver resolver) {
         this(id, channelId, out, CoreModuleProperties.BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_SIZE.getRequired(resolver),
              CoreModuleProperties.BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_WAIT.getRequired(resolver));
     }
 
     public BufferedIoOutputStream(
-                                  Object id, int channelId, IoOutputStream out, int maxPendingBytesCount,
+                                  Object id, long channelId, IoOutputStream out, int maxPendingBytesCount,
                                   Duration maxWaitForPendingWrites) {
         this.id = Objects.requireNonNull(id, "No stream identifier provided");
         this.channelId = channelId;
@@ -71,6 +71,10 @@ public class BufferedIoOutputStream extends AbstractInnerCloseable implements Io
         this.maxWaitForPendingWrites = Objects.requireNonNull(maxWaitForPendingWrites, "No max. pending time value provided");
     }
 
+    public long getChannelId() {
+        return channelId;
+    }
+
     public Object getId() {
         return id;
     }
@@ -259,6 +263,6 @@ public class BufferedIoOutputStream extends AbstractInnerCloseable implements Io
 
     @Override
     public String toString() {
-        return getClass().getSimpleName() + "(" + getId() + ")[" + out + "]";
+        return getClass().getSimpleName() + "(" + getId() + "@" + channelId + ")[" + out + "]";
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java
index 2bfd095..41a86be 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java
@@ -55,14 +55,14 @@ public interface Channel
     String CHANNEL_SUBSYSTEM = "subsystem";
 
     /**
-     * @return Local channel identifier
+     * @return Local channel UINT32 identifier
      */
-    int getId();
+    long getId();
 
     /**
-     * @return Remote channel identifier
+     * @return Remote channel UITN32 identifier
      */
-    int getRecipient();
+    long getRecipient();
 
     Window getLocalWindow();
 
@@ -147,10 +147,10 @@ public interface Channel
      *
      * @param  service     The {@link ConnectionService} through which the channel is initialized
      * @param  session     The {@link Session} associated with the channel
-     * @param  id          The locally assigned channel identifier
+     * @param  id          The locally assigned channel identifier (UINT32 represented as a {@code long})
      * @throws IOException If failed to process the initialization
      */
-    void init(ConnectionService service, Session session, int id) throws IOException;
+    void init(ConnectionService service, Session session, long id) throws IOException;
 
     /**
      * Invoked after being successfully registered by the connection service - should throw a {@link RuntimeException}
@@ -158,10 +158,10 @@ public interface Channel
      *
      * @param service    The {@link ConnectionService} through which the channel is registered
      * @param session    The {@link Session} associated with the channel
-     * @param id         The locally assigned channel identifier
+     * @param id         The locally assigned channel identifier (UINT32 represented as a {@code long})
      * @param registered Whether registration was successful or not
      */
-    void handleChannelRegistrationResult(ConnectionService service, Session session, int id, boolean registered);
+    void handleChannelRegistrationResult(ConnectionService service, Session session, long id, boolean registered);
 
     /**
      * Called by the connection service to inform the channel that it has bee unregistered.
@@ -171,7 +171,7 @@ public interface Channel
     void handleChannelUnregistration(ConnectionService service);
 
     /**
-     * @return {@code true} if call to {@link #init(ConnectionService, Session, int)} was successfully completed
+     * @return {@code true} if call to {@link #init(ConnectionService, Session, long)} was successfully completed
      */
     boolean isInitialized();
 
@@ -185,27 +185,27 @@ public interface Channel
     /**
      * For a server channel, this method will actually open the channel
      *
-     * @param  recipient  Recipient identifier
+     * @param  recipient  Recipient identifier (UINT32 represented as a {@code long})
      * @param  rwSize     Read/Write window size ({@code uint32})
      * @param  packetSize Preferred maximum packet size ({@code uint32})
      * @param  buffer     Incoming {@link Buffer} that triggered the call. <B>Note:</B> the buffer's read position is
      *                    exactly <U>after</U> the information that read to this call was decoded
      * @return            An {@link OpenFuture} for the channel open request
      */
-    OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer);
+    OpenFuture open(long recipient, long rwSize, long packetSize, Buffer buffer);
 
     /**
      * For a client channel, this method will be called internally by the session when the confirmation has been
      * received.
      *
-     * @param  recipient   Recipient identifier
+     * @param  recipient   Recipient identifier (UINT32 represented as a {@code long})
      * @param  rwSize      Read/Write window size ({@code uint32})
      * @param  packetSize  Preferred maximum packet size ({@code uint32})
      * @param  buffer      Incoming {@link Buffer} that triggered the call. <B>Note:</B> the buffer's read position is
      *                     exactly <U>after</U> the information that read to this call was decoded
      * @throws IOException If failed to handle the success
      */
-    void handleOpenSuccess(int recipient, long rwSize, long packetSize, Buffer buffer) throws IOException;
+    void handleOpenSuccess(long recipient, long rwSize, long packetSize, Buffer buffer) throws IOException;
 
     /**
      * For a client channel, this method will be called internally by the session when the server has rejected this
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelAsyncOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelAsyncOutputStream.java
index 81844a6..49838a2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelAsyncOutputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelAsyncOutputStream.java
@@ -30,6 +30,7 @@ import org.apache.sshd.common.io.IoOutputStream;
 import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.io.WritePendingException;
 import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
@@ -255,11 +256,13 @@ public class ChannelAsyncOutputStream extends AbstractCloseable implements IoOut
     }
 
     protected Buffer createSendBuffer(Buffer buffer, Channel channel, long length) {
+        SessionContext.validateSessionPayloadSize(length, "Invalid send buffer length: %d");
+
         Session s = channel.getSession();
         Buffer buf = s.createBuffer(cmd, (int) length + 12);
-        buf.putInt(channel.getRecipient());
+        buf.putUInt(channel.getRecipient());
         if (cmd == SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA) {
-            buf.putInt(SshConstants.SSH_EXTENDED_DATA_STDERR);
+            buf.putUInt(SshConstants.SSH_EXTENDED_DATA_STDERR);
         }
         buf.putUInt(length);
         buf.putRawBytes(buffer.array(), buffer.rpos(), (int) length);
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelListener.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelListener.java
index 1b57038..d48dea3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelListener.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelListener.java
@@ -38,7 +38,7 @@ public interface ChannelListener extends SshdEventListener {
 
     /**
      * Called to inform about initial setup of a channel via the
-     * {@link Channel#init(org.apache.sshd.common.session.ConnectionService, org.apache.sshd.common.session.Session, int)}
+     * {@link Channel#init(org.apache.sshd.common.session.ConnectionService, org.apache.sshd.common.session.Session, long)}
      * method. <B>Note:</B> this method is guaranteed to be called before either of the
      * {@link #channelOpenSuccess(Channel)} or {@link #channelOpenFailure(Channel, Throwable)} will be called
      *
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
index ec08f8a..188fb78 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
@@ -302,11 +302,11 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
         Channel channel = getChannel();
         Session session = channel.getSession();
         buffer = session.createBuffer(cmd, size <= 0 ? 12 : 12 + size);
-        buffer.putInt(channel.getRecipient());
+        buffer.putUInt(channel.getRecipient());
         if (cmd == SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA) {
-            buffer.putInt(SshConstants.SSH_EXTENDED_DATA_STDERR);
+            buffer.putUInt(SshConstants.SSH_EXTENDED_DATA_STDERR);
         }
-        buffer.putInt(0);
+        buffer.putUInt(0L);
         bufferLength = 0;
     }
 
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java
index 97e6105..bd41e54 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java
@@ -27,15 +27,15 @@ package org.apache.sshd.common.channel.exception;
 public class SshChannelBufferedOutputException extends SshChannelException {
     private static final long serialVersionUID = -8663890657820958046L;
 
-    public SshChannelBufferedOutputException(int channelId, String message) {
+    public SshChannelBufferedOutputException(long channelId, String message) {
         this(channelId, message, null);
     }
 
-    public SshChannelBufferedOutputException(int channelId, Throwable cause) {
+    public SshChannelBufferedOutputException(long channelId, Throwable cause) {
         this(channelId, cause.getMessage(), cause);
     }
 
-    public SshChannelBufferedOutputException(int channelId, String message, Throwable cause) {
+    public SshChannelBufferedOutputException(long channelId, String message, Throwable cause) {
         super(channelId, message, cause);
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelClosedException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelClosedException.java
index ee4b6ff..4e2f2a8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelClosedException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelClosedException.java
@@ -25,15 +25,15 @@ package org.apache.sshd.common.channel.exception;
 public class SshChannelClosedException extends SshChannelException {
     private static final long serialVersionUID = 4201656251593797929L;
 
-    public SshChannelClosedException(int channelId, String message) {
+    public SshChannelClosedException(long channelId, String message) {
         this(channelId, message, null);
     }
 
-    public SshChannelClosedException(int channelId, Throwable cause) {
+    public SshChannelClosedException(long channelId, Throwable cause) {
         this(channelId, cause.getMessage(), cause);
     }
 
-    public SshChannelClosedException(int channelId, String message, Throwable cause) {
+    public SshChannelClosedException(long channelId, String message, Throwable cause) {
         super(channelId, message, cause);
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java
index 57c9669..13d9f6e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java
@@ -24,25 +24,25 @@ import java.io.IOException;
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class SshChannelException extends IOException {
+public abstract class SshChannelException extends IOException {
     private static final long serialVersionUID = 7355720478400167933L;
 
-    private final int channelId;
+    private final long channelId;
 
-    public SshChannelException(int channelId, String message) {
+    protected SshChannelException(long channelId, String message) {
         this(channelId, message, null);
     }
 
-    public SshChannelException(int channelId, Throwable cause) {
+    protected SshChannelException(long channelId, Throwable cause) {
         this(channelId, cause.getMessage(), cause);
     }
 
-    public SshChannelException(int channelId, String message, Throwable cause) {
+    protected SshChannelException(long channelId, String message, Throwable cause) {
         super(message, cause);
         this.channelId = channelId;
     }
 
-    public int getChannelId() {
+    public long getChannelId() {
         return channelId;
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java
index 26fb9ab..3494390 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java
@@ -25,15 +25,15 @@ package org.apache.sshd.common.channel.exception;
 public class SshChannelNotFoundException extends SshChannelException {
     private static final long serialVersionUID = 6235323779982884257L;
 
-    public SshChannelNotFoundException(int channelId, String message) {
+    public SshChannelNotFoundException(long channelId, String message) {
         this(channelId, message, null);
     }
 
-    public SshChannelNotFoundException(int channelId, Throwable cause) {
+    public SshChannelNotFoundException(long channelId, Throwable cause) {
         this(channelId, cause.getMessage(), cause);
     }
 
-    public SshChannelNotFoundException(int channelId, String message, Throwable cause) {
+    public SshChannelNotFoundException(long channelId, String message, Throwable cause) {
         super(channelId, message, cause);
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java
index e272d2b..6daa73c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java
@@ -28,11 +28,11 @@ public class SshChannelOpenException extends SshChannelException {
 
     private final int code;
 
-    public SshChannelOpenException(int channelId, int code, String message) {
+    public SshChannelOpenException(long channelId, int code, String message) {
         this(channelId, code, message, null);
     }
 
-    public SshChannelOpenException(int channelId, int code, String message, Throwable cause) {
+    public SshChannelOpenException(long channelId, int code, String message, Throwable cause) {
         super(channelId, message, cause);
         this.code = code;
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
index 853581b..17c6003 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
@@ -150,13 +150,13 @@ public class TcpipClientChannel extends AbstractClientChannel implements Forward
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN,
                 type.length() + srcHost.length() + dstHost.length() + Long.SIZE);
         buffer.putString(type);
-        buffer.putInt(getId());
-        buffer.putInt(wLocal.getSize());
-        buffer.putInt(wLocal.getPacketSize());
+        buffer.putUInt(getId());
+        buffer.putUInt(wLocal.getSize());
+        buffer.putUInt(wLocal.getPacketSize());
         buffer.putString(dstHost);
-        buffer.putInt(dst.getPort());
+        buffer.putUInt(dst.getPort());
         buffer.putString(srcHost);
-        buffer.putInt(src.getPort());
+        buffer.putUInt(src.getPort());
         writePacket(buffer);
         return openFuture;
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/extension/DefaultServerKexExtensionHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/extension/DefaultServerKexExtensionHandler.java
index ef48290..7d59246 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/extension/DefaultServerKexExtensionHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/extension/DefaultServerKexExtensionHandler.java
@@ -69,6 +69,7 @@ public class DefaultServerKexExtensionHandler extends AbstractLoggingBean implem
      * <dd>The EXT_INFO message at {@link KexPhase#NEWKEYS} was done.</dd>
      * </dl>
      */
+    @SuppressWarnings("javadoc")
     public static final AttributeKey<Boolean> EXT_INFO_SENT_AT_NEWKEYS = new AttributeKey<>();
 
     public DefaultServerKexExtensionHandler() {
@@ -141,6 +142,7 @@ public class DefaultServerKexExtensionHandler extends AbstractLoggingBean implem
      * @param phase      {@link KexPhase} of the SSH protocol
      * @param marshaller {@link BiConsumer} writing the extensions into an SSH message
      */
+    @SuppressWarnings("javadoc")
     public void collectExtensions(Session session, KexPhase phase, BiConsumer<String, Object> marshaller) {
         if (phase == KexPhase.NEWKEYS) {
             Collection<String> algorithms = session.getSignatureFactoriesNames();
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
index 9e6a8e6..4340da3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
@@ -44,10 +44,10 @@ public interface ConnectionService
      * Register a newly created channel with a new unique identifier
      *
      * @param  channel     The {@link Channel} to register
-     * @return             The assigned id of this channel
+     * @return             The assigned id of this channel - a UINT32 represented as a {@code long}
      * @throws IOException If failed to initialize and register the channel
      */
-    int registerChannel(Channel channel) throws IOException;
+    long registerChannel(Channel channel) throws IOException;
 
     /**
      * Remove this channel from the list of managed channels
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/UnknownChannelReferenceHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/session/UnknownChannelReferenceHandler.java
index 11f749d..debee20 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/UnknownChannelReferenceHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/UnknownChannelReferenceHandler.java
@@ -41,5 +41,5 @@ public interface UnknownChannelReferenceHandler {
      *                     ignored.
      * @throws IOException If failed to handle the request
      */
-    Channel handleUnknownChannelCommand(ConnectionService service, byte cmd, int channelId, Buffer buffer) throws IOException;
+    Channel handleUnknownChannelCommand(ConnectionService service, byte cmd, long channelId, Buffer buffer) throws IOException;
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
index 147ef16..d390fd5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
@@ -31,7 +31,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.IntUnaryOperator;
@@ -90,11 +89,11 @@ public abstract class AbstractConnectionService
     /**
      * Map of channels keyed by the identifier
      */
-    protected final Map<Integer, Channel> channels = new ConcurrentHashMap<>();
+    protected final Map<Long, Channel> channels = new ConcurrentHashMap<>();
     /**
-     * Next channel identifier
+     * Next channel identifier - a UINT32 represented as a long
      */
-    protected final AtomicInteger nextChannelId = new AtomicInteger(0);
+    protected final AtomicLong nextChannelId = new AtomicLong(0L);
     protected final AtomicLong heartbeatCount = new AtomicLong(0L);
     private ScheduledFuture<?> heartBeat;
 
@@ -392,12 +391,12 @@ public abstract class AbstractConnectionService
                 .build();
     }
 
-    protected int getNextChannelId() {
+    protected long getNextChannelId() {
         return nextChannelId.getAndIncrement();
     }
 
     @Override
-    public int registerChannel(Channel channel) throws IOException {
+    public long registerChannel(Channel channel) throws IOException {
         Session session = getSession();
         int maxChannels = CoreModuleProperties.MAX_CONCURRENT_CHANNELS.getRequired(this);
         int curSize = channels.size();
@@ -405,7 +404,7 @@ public abstract class AbstractConnectionService
             throw new IllegalStateException("Currently active channels (" + curSize + ") at max.: " + maxChannels);
         }
 
-        int channelId = getNextChannelId();
+        long channelId = getNextChannelId();
         channel.init(this, session, channelId);
 
         boolean registered = false;
@@ -431,7 +430,7 @@ public abstract class AbstractConnectionService
      */
     @Override
     public void unregisterChannel(Channel channel) {
-        int channelId = channel.getId();
+        long channelId = channel.getId();
         Channel result;
         synchronized (channels) {
             result = channels.remove(channelId);
@@ -551,7 +550,7 @@ public abstract class AbstractConnectionService
             return; // debug breakpoint
         }
 
-        int id = channel.getId();
+        long id = channel.getId();
         boolean debugEnabled = log.isDebugEnabled();
         if (debugEnabled) {
             log.debug("channelOpenFailure({}) Received SSH_MSG_CHANNEL_OPEN_FAILURE", channel);
@@ -698,10 +697,10 @@ public abstract class AbstractConnectionService
      * @throws IOException if the channel does not exists
      */
     protected Channel getChannel(byte cmd, Buffer buffer) throws IOException {
-        return getChannel(cmd, buffer.getInt(), buffer);
+        return getChannel(cmd, buffer.getUInt(), buffer);
     }
 
-    protected Channel getChannel(byte cmd, int recipient, Buffer buffer) throws IOException {
+    protected Channel getChannel(byte cmd, long recipient, Buffer buffer) throws IOException {
         Channel channel = channels.get(recipient);
         if (channel != null) {
             return channel;
@@ -732,7 +731,7 @@ public abstract class AbstractConnectionService
 
     protected void channelOpen(Buffer buffer) throws Exception {
         String type = buffer.getString();
-        int sender = buffer.getInt();
+        long sender = buffer.getUInt();
         long rwsize = buffer.getUInt();
         long rmpsize = buffer.getUInt();
         /*
@@ -767,7 +766,7 @@ public abstract class AbstractConnectionService
             return;
         }
 
-        int channelId = registerChannel(channel);
+        long channelId = registerChannel(channel);
         OpenFuture openFuture = channel.open(sender, rwsize, rmpsize, buffer);
         openFuture.addListener(future -> {
             try {
@@ -779,10 +778,10 @@ public abstract class AbstractConnectionService
                                 channel, sender, channelId, window.getSize(), window.getPacketSize());
                     }
                     Buffer buf = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, Integer.SIZE);
-                    buf.putInt(sender); // remote (server side) identifier
-                    buf.putInt(channelId); // local (client side) identifier
-                    buf.putInt(window.getSize());
-                    buf.putInt(window.getPacketSize());
+                    buf.putUInt(sender); // remote (server side) identifier
+                    buf.putUInt(channelId); // local (client side) identifier
+                    buf.putUInt(window.getSize());
+                    buf.putUInt(window.getPacketSize());
                     session.writePacket(buf);
                 } else {
                     int reasonCode = 0;
@@ -811,7 +810,7 @@ public abstract class AbstractConnectionService
     }
 
     protected IoWriteFuture sendChannelOpenFailure(
-            Buffer buffer, int sender, int reasonCode, String message, String lang)
+            Buffer buffer, long sender, int reasonCode, String message, String lang)
             throws IOException {
         if (log.isDebugEnabled()) {
             log.debug("sendChannelOpenFailure({}) sender={}, reason={}, lang={}, message='{}'",
@@ -821,8 +820,8 @@ public abstract class AbstractConnectionService
         Session session = getSession();
         Buffer buf = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN_FAILURE,
                 Long.SIZE + GenericUtils.length(message) + GenericUtils.length(lang));
-        buf.putInt(sender);
-        buf.putInt(reasonCode);
+        buf.putUInt(sender);
+        buf.putUInt(reasonCode);
         buf.putString(message);
         buf.putString(lang);
         return session.writePacket(buf);
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/DefaultUnknownChannelReferenceHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/DefaultUnknownChannelReferenceHandler.java
index e5723b9..c5e9318 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/DefaultUnknownChannelReferenceHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/DefaultUnknownChannelReferenceHandler.java
@@ -46,7 +46,7 @@ public class DefaultUnknownChannelReferenceHandler
 
     @Override
     public Channel handleUnknownChannelCommand(
-            ConnectionService service, byte cmd, int channelId, Buffer buffer)
+            ConnectionService service, byte cmd, long channelId, Buffer buffer)
             throws IOException {
         Session session = service.getSession();
         // Use DEBUG level to avoid log overflow due to invalid messages flood
@@ -97,7 +97,7 @@ public class DefaultUnknownChannelReferenceHandler
     }
 
     protected IoWriteFuture sendFailureResponse(
-            ConnectionService service, byte cmd, int channelId)
+            ConnectionService service, byte cmd, long channelId)
             throws IOException {
         Session session = service.getSession();
         // Use DEBUG level to avoid log overflow due to invalid messages flood
@@ -107,7 +107,7 @@ public class DefaultUnknownChannelReferenceHandler
         }
 
         Buffer rsp = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_FAILURE, Integer.BYTES);
-        rsp.putInt(channelId);
+        rsp.putUInt(channelId);
         return session.writePacket(rsp);
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
index a08d37e..2efccca 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
@@ -429,7 +429,7 @@ public abstract class SessionHelper extends AbstractKexFactoryManager implements
      */
     protected IoWriteFuture sendNotImplemented(long seqNoValue) throws IOException {
         Buffer buffer = createBuffer(SshConstants.SSH_MSG_UNIMPLEMENTED, Byte.SIZE);
-        buffer.putInt(seqNoValue);
+        buffer.putUInt(seqNoValue);
         return writePacket(buffer);
     }
 
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
index 788ac55..7fd7d68 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
@@ -56,7 +56,7 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
     }
 
     @Override
-    public OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer) {
+    public OpenFuture open(long recipient, long rwSize, long packetSize, Buffer buffer) {
         setRecipient(recipient);
 
         Session s = getSession();
@@ -69,7 +69,7 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
 
     @Override
     public void handleOpenSuccess(
-            int recipient, long rwSize, long packetSize, Buffer buffer)
+            long recipient, long rwSize, long packetSize, Buffer buffer)
             throws IOException {
         throw new UnsupportedOperationException(
                 "handleOpenSuccess(" + recipient + "," + rwSize + "," + packetSize + ") N/A");
@@ -114,7 +114,7 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
         Session session = getSession();
         Buffer buffer = session.createBuffer(
                 SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE);
-        buffer.putInt(getRecipient());
+        buffer.putUInt(getRecipient());
         buffer.putString("exit-status");
         // want-reply - must be FALSE - see https://tools.ietf.org/html/rfc4254 section 6.10
         buffer.putBoolean(false);
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
index 7ea6c72..2a14a35 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
@@ -215,7 +215,7 @@ public class TcpipServerChannel extends AbstractServerChannel implements Streami
         }
 
         if (streaming == Streaming.Async) {
-            int channelId = getId();
+            long channelId = getId();
             out = new BufferedIoOutputStream(
                     "aysnc-tcpip-channel@" + channelId, channelId,
                     new ChannelAsyncOutputStream(this, SshConstants.SSH_MSG_CHANNEL_DATA) {
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/x11/ChannelForwardedX11.java b/sshd-core/src/main/java/org/apache/sshd/server/x11/ChannelForwardedX11.java
index 9dd046a..cde200b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/x11/ChannelForwardedX11.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/x11/ChannelForwardedX11.java
@@ -67,11 +67,11 @@ public class ChannelForwardedX11 extends AbstractClientChannel {
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN,
                 remoteHost.length() + type.length() + Integer.SIZE);
         buffer.putString(type);
-        buffer.putInt(getId());
-        buffer.putInt(wLocal.getSize());
-        buffer.putInt(wLocal.getPacketSize());
+        buffer.putUInt(getId());
+        buffer.putUInt(wLocal.getSize());
+        buffer.putUInt(wLocal.getPacketSize());
         buffer.putString(remoteHost);
-        buffer.putInt(remote.getPort());
+        buffer.putUInt(remote.getPort());
         writePacket(buffer);
         return openFuture;
     }
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 b1ae9b1..bc466e2 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
@@ -208,7 +208,7 @@ public class ClientTest extends BaseTestSupport {
                         return new ChannelSession() {
                             @SuppressWarnings("synthetic-access")
                             @Override
-                            public OpenFuture open(int recipient, long rwsize, long rmpsize, Buffer buffer) {
+                            public OpenFuture open(long recipient, long rwsize, long rmpsize, Buffer buffer) {
                                 try {
                                     channelLatch.await();
                                 } catch (InterruptedException e) {
@@ -342,7 +342,7 @@ public class ClientTest extends BaseTestSupport {
 
     @Test
     public void testClientStillActiveIfListenerExceptions() throws Exception {
-        Map<String, Integer> eventsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        Map<String, Long> eventsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         Collection<String> failuresSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
         Logger log = LoggerFactory.getLogger(getClass());
         client.addChannelListener(new ChannelListener() {
@@ -377,7 +377,7 @@ public class ClientTest extends BaseTestSupport {
             }
 
             private void handleChannelEvent(String name, Channel channel) {
-                int id = channel.getId();
+                long id = channel.getId();
                 synchronized (eventsMap) {
                     if (eventsMap.put(name, id) != null) {
                         return; // already generated an exception for this event
@@ -1475,9 +1475,9 @@ public class ClientTest extends BaseTestSupport {
             channels.add(session.createChannel(Channel.CHANNEL_EXEC, getCurrentTestName()));
             channels.add(session.createChannel(Channel.CHANNEL_SHELL, getClass().getSimpleName()));
 
-            Set<Integer> ids = new HashSet<>(channels.size());
+            Set<Long> ids = new HashSet<>(channels.size());
             for (ClientChannel c : channels) {
-                int id = c.getId();
+                long id = c.getId();
                 assertTrue("Channel ID repeated: " + id, ids.add(id));
             }
         } finally {
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowInitTest.java b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowInitTest.java
index 81f0362..64a64a6 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowInitTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowInitTest.java
@@ -49,12 +49,12 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 public class WindowInitTest extends BaseTestSupport {
     private static final AbstractChannel MOCK_CHANNEL = new AbstractChannel(true) {
         @Override
-        public OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer) {
+        public OpenFuture open(long recipient, long rwSize, long packetSize, Buffer buffer) {
             return null;
         }
 
         @Override
-        public void handleOpenSuccess(int recipient, long rwSize, long packetSize, Buffer buffer) throws IOException {
+        public void handleOpenSuccess(long recipient, long rwSize, long packetSize, Buffer buffer) throws IOException {
             // ignored
         }
 
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
index f42ad61..77965f2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
@@ -110,7 +110,7 @@ public class WindowTest extends BaseTestSupport {
                         return new ChannelSession() {
                             @SuppressWarnings("synthetic-access")
                             @Override
-                            public OpenFuture open(int recipient, long rwsize, long rmpsize, Buffer buffer) {
+                            public OpenFuture open(long recipient, long rwsize, long rmpsize, Buffer buffer) {
                                 try {
                                     channelLatch.await();
                                 } catch (InterruptedException e) {
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTimeoutTest.java b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTimeoutTest.java
index cbb4865..d312bbd 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTimeoutTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTimeoutTest.java
@@ -56,12 +56,12 @@ public class WindowTimeoutTest extends BaseTestSupport {
     public void setUp() throws Exception {
         channel = new AbstractChannel(getCurrentTestName(), true) {
             @Override
-            public OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer) {
+            public OpenFuture open(long recipient, long rwSize, long packetSize, Buffer buffer) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public void handleOpenSuccess(int recipient, long rwSize, long packetSize, Buffer buffer) throws IOException {
+            public void handleOpenSuccess(long recipient, long rwSize, long packetSize, Buffer buffer) throws IOException {
                 throw new UnsupportedOperationException();
             }
 
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java b/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java
index 2373539..22f7fec 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java
@@ -112,7 +112,7 @@ public class AsyncEchoShellFactory implements ShellFactory {
                 return (BufferedIoOutputStream) stream;
             }
 
-            int channelId = session.getId();
+            long channelId = session.getId();
             return new BufferedIoOutputStream(prefix + "@" + channelId, channelId, stream, session);
         }
 
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusChannel.java b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusChannel.java
index 80e576c..7138ded 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusChannel.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusChannel.java
@@ -50,12 +50,12 @@ public class BogusChannel extends AbstractChannel {
     }
 
     @Override
-    public OpenFuture open(int recipient, long rwsize, long rmpsize, Buffer buffer) {
+    public OpenFuture open(long recipient, long rwsize, long rmpsize, Buffer buffer) {
         return new DefaultOpenFuture(this, this.futureLock);
     }
 
     @Override
-    public void handleOpenSuccess(int recipient, long rwsize, long rmpsize, Buffer buffer) throws IOException {
+    public void handleOpenSuccess(long recipient, long rwsize, long rmpsize, Buffer buffer) throws IOException {
         // ignored
     }
 
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpPath.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpPath.java
index a8c6468..807c062 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpPath.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpPath.java
@@ -41,6 +41,7 @@ public class SftpPath extends BasePath<SftpPath, SftpFileSystem> {
      *
      * @return the cached {@link SftpClient.Attributes} or {@code null} if there are none cached
      */
+    @SuppressWarnings("javadoc")
     public SftpClient.Attributes getAttributes() {
         // Subclasses may override
         return null;
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
index 78f0b2f..373fdf3 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
@@ -682,6 +682,7 @@ public abstract class AbstractSftpClient
 
         if (type == SftpConstants.SSH_FXP_DATA) {
             int len = buffer.getInt();
+            ValidateUtils.checkTrue(len >= 0, "Invalid response data len: %d", len);
             buffer.getRawBytes(dst, dstoff, len);
             Boolean indicator = SftpHelper.getEndOfFileIndicatorValue(buffer, getVersion());
             if (log.isTraceEnabled()) {
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
index a543a61..cf4518b 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
@@ -551,7 +551,7 @@ public class DefaultSftpClient extends AbstractSftpClient {
             boolean wantReply = CoreModuleProperties.REQUEST_SUBSYSTEM_REPLY.getRequired(this);
             Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST,
                     Channel.CHANNEL_SUBSYSTEM.length() + systemName.length() + Integer.SIZE);
-            buffer.putInt(getRecipient());
+            buffer.putUInt(getRecipient());
             buffer.putString(Channel.CHANNEL_SUBSYSTEM);
             buffer.putBoolean(wantReply);
             buffer.putString(systemName);
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/Supported2Parser.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/Supported2Parser.java
index c2e3b3a..4e0cbe6 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/Supported2Parser.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/Supported2Parser.java
@@ -28,14 +28,15 @@ import org.apache.sshd.sftp.common.extensions.Supported2Parser.Supported2;
 
 /**
  * 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>
+ * <A HREF="https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-5.4">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>
+     * @see    <A HREF="https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-5.4">DRAFT 13 section
+     *         5.4</A>
      */
     public static class Supported2 {
         // CHECKSTYLE:OFF
@@ -43,7 +44,8 @@ public class Supported2Parser extends AbstractParser<Supported2> {
         public int supportedAttributeBits;
         public int supportedOpenFlags;
         public int supportedAccessMask;
-        public int maxReadSize;
+        // Actually UINT32
+        public long maxReadSize;
         public short supportedOpenBlockVector;
         public short supportedBlock;
         //        uint32 attrib-extension-count
@@ -87,7 +89,7 @@ public class Supported2Parser extends AbstractParser<Supported2> {
         sup2.supportedAttributeBits = buffer.getInt();
         sup2.supportedOpenFlags = buffer.getInt();
         sup2.supportedAccessMask = buffer.getInt();
-        sup2.maxReadSize = buffer.getInt();
+        sup2.maxReadSize = buffer.getUInt();
         sup2.supportedOpenBlockVector = buffer.getShort();
         sup2.supportedBlock = buffer.getShort();
         sup2.attribExtensionNames = buffer.getStringList(true);
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/SupportedParser.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/SupportedParser.java
index dde1da1..28ebe4b 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/SupportedParser.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/SupportedParser.java
@@ -36,8 +36,8 @@ import org.apache.sshd.sftp.common.extensions.SupportedParser.Supported;
 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>
+     * @see    <A HREF="http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05">DRAFT 05
+     *         - section 4.4</A>
      */
     public static class Supported {
         // CHECKSTYLE:OFF
@@ -45,7 +45,8 @@ public class SupportedParser extends AbstractParser<Supported> {
         public int supportedAttributeBits;
         public int supportedOpenFlags;
         public int supportedAccessMask;
-        public int maxReadSize;
+        // Actually UINT32
+        public long maxReadSize;
         public Collection<String> extensionNames;
         // CHECKSTYLE:ON
 
@@ -81,7 +82,7 @@ public class SupportedParser extends AbstractParser<Supported> {
         sup.supportedAttributeBits = buffer.getInt();
         sup.supportedOpenFlags = buffer.getInt();
         sup.supportedAccessMask = buffer.getInt();
-        sup.maxReadSize = buffer.getInt();
+        sup.maxReadSize = buffer.getUInt();
         sup.extensionNames = buffer.getStringList(false);
         return sup;
     }
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
index ba8ca69..f87eb6a 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
@@ -556,6 +556,7 @@ public abstract class AbstractSftpSubsystemHelper
         }
 
         try {
+            // protected against malicious packets
             ValidateUtils.checkTrue(readLen >= 0, "Illegal requested read length: %d", readLen);
 
             buffer = prepareReply(buffer);
@@ -564,7 +565,7 @@ public abstract class AbstractSftpSubsystemHelper
             buffer.putByte((byte) SftpConstants.SSH_FXP_DATA);
             buffer.putInt(id);
             int lenPos = buffer.wpos();
-            buffer.putInt(0);
+            buffer.putUInt(0L); // save room for length
 
             AtomicReference<Boolean> eofRef = new AtomicReference<>();
             int startPos = buffer.wpos();
@@ -2180,7 +2181,7 @@ public abstract class AbstractSftpSubsystemHelper
             throws IOException {
         buffer.putByte((byte) SftpConstants.SSH_FXP_NAME);
         buffer.putInt(id);
-        buffer.putInt(1); // one reply
+        buffer.putUInt(1L); // one reply
 
         String originalPath = f.toString();
         // in case we are running on Windows
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
index fdd4bae..ae48894 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
@@ -241,7 +241,7 @@ public class SftpSubsystem
     @Override
     public void setIoOutputStream(IoOutputStream out) {
         ChannelSession channel = getServerChannelSession();
-        int channelId = channel.getId();
+        long channelId = channel.getId();
         this.out = new BufferedIoOutputStream("sftp-out@" + channelId, channelId, out, channel);
     }
 
@@ -274,7 +274,7 @@ public class SftpSubsystem
             int msglen = buffer.getInt();
             if (buffer.available() >= msglen) {
                 Buffer b = new ByteArrayBuffer(msglen + Integer.BYTES + Long.SIZE /* a bit extra */, false);
-                b.putInt(msglen);
+                b.putUInt(msglen);
                 b.putRawBytes(buffer.array(), buffer.rpos(), msglen);
                 requests.add(b);
                 buffer.rpos(rpos + msglen + Integer.BYTES);
@@ -719,7 +719,7 @@ public class SftpSubsystem
                 reply.putInt(id);
 
                 int lenPos = reply.wpos();
-                reply.putInt(0);
+                reply.putUInt(0L);  // save room for actual length
 
                 int maxDataSize = SftpModuleProperties.MAX_READDIR_DATA_SIZE.getRequired(session);
                 int count = doReadDir(id, handle, dh, reply, maxDataSize, false);
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/ClientTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/ClientTest.java
index a99e566..b2c3dad 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/ClientTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/ClientTest.java
@@ -147,7 +147,7 @@ public class ClientTest extends BaseTestSupport {
                         return new ChannelSession() {
                             @SuppressWarnings("synthetic-access")
                             @Override
-                            public OpenFuture open(int recipient, long rwsize, long rmpsize, Buffer buffer) {
+                            public OpenFuture open(long recipient, long rwsize, long rmpsize, Buffer buffer) {
                                 try {
                                     channelLatch.await();
                                 } catch (InterruptedException e) {
@@ -278,9 +278,9 @@ public class ClientTest extends BaseTestSupport {
             channels.add(session.createChannel(Channel.CHANNEL_EXEC, getCurrentTestName()));
             channels.add(session.createChannel(Channel.CHANNEL_SHELL, getClass().getSimpleName()));
 
-            Set<Integer> ids = new HashSet<>(channels.size());
+            Set<Long> ids = new HashSet<>(channels.size());
             for (ClientChannel c : channels) {
-                int id = c.getId();
+                long id = c.getId();
                 assertTrue("Channel ID repeated: " + id, ids.add(id));
             }
         } finally {
@@ -300,7 +300,7 @@ public class ClientTest extends BaseTestSupport {
     /**
      * Makes sure that the {@link ChannelListener}s added to the client, session and channel are <U>cumulative</U> -
      * i.e., all of them invoked
-     * 
+     *
      * @throws Exception If failed
      */
     @Test
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
index ce4904d..f247ed5 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
@@ -519,7 +519,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         buffer.putInt(SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS);
         buffer.putByte((byte) SftpConstants.SSH_FILEXFER_TYPE_REGULAR);
 
-        buffer.putInt(0);
+        buffer.putUInt(0L);
 
         int reqId = sftp.send(SftpConstants.SSH_FXP_OPEN, buffer);
         Buffer response = sftp.receive(reqId);
@@ -528,7 +528,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
     }
 
     private byte[] getRawFileHandle(Buffer buffer) {
-        buffer.getInt(); // length
+        buffer.getUInt(); // length
         int type = buffer.getUByte();
         assertEquals("Mismatched response type", SftpConstants.SSH_FXP_HANDLE, type);
         buffer.getInt(); // id