Thank you for the patches! From the first look, they look good to me. But
we will need your DCO to be able to accept your contributions:

https://gitlab.com/libssh/libssh-mirror/-/blob/master/CONTRIBUTING.md?ref_type=heads#how-to-sign-your-work

Thanks,
Jakub

On Fri, Aug 28, 2026 at 9:46 AM Daniel Golle <[email protected]> wrote:

> ssh_packet_global_request() unpacked the "tcpip-forward" and
> "cancel-tcpip-forward" bind port with the "d" format directly into the
> uint16_t bind_port field. "d" stores a full uint32_t through the given
> pointer, so the two bytes following the field were overwritten and the
> field itself received only the most significant half of the value:
> zero, on big-endian platforms, for any valid port.
>
> A server offering -R forwarding on a big-endian host therefore saw
> every requested bind port as a wildcard, bound an ephemeral port
> instead of the requested one and reported success, while the client
> kept waiting on the port it had asked for, since the chosen port is
> only reported back to the client for an actual wildcard request. The
> forwarding therefore never carried a connection.
>
> Unpack into a uint32_t local and assign it to the field, as the
> direct-tcpip and forwarded-tcpip channel-open parsers already do.
>
> Signed-off-by: Daniel Golle <[email protected]>
> ---
> Found on OpenWrt (mips_24kc, big-endian, musl), where a client's -R
> forwarding request through a libssh server bound the wrong port.
> Verified on a big-endian build: before this patch the server binds an
> ephemeral port instead of the requested one and the forwarding never
> carries a connection, with it the requested port is bound and -R
> forwarding works end to end. No changes in testsuite results.
>
>  src/messages.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/src/messages.c b/src/messages.c
> index 470d2f93..611bed18 100644
> --- a/src/messages.c
> +++ b/src/messages.c
> @@ -1869,6 +1869,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request)
>      ssh_message msg = NULL;
>      char *request = NULL;
>      uint8_t want_reply;
> +    uint32_t bind_port = 0;
>      int rc = SSH_PACKET_USED;
>      int r;
>
> @@ -1899,10 +1900,11 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request)
>          r = ssh_buffer_unpack(packet,
>                                "sd",
>                                &msg->global_request.bind_address,
> -                              &msg->global_request.bind_port);
> +                              &bind_port);
>          if (r != SSH_OK) {
>              goto reply_with_failure;
>          }
> +        msg->global_request.bind_port = (uint16_t)bind_port;
>          msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD;
>          msg->global_request.want_reply = want_reply;
>
> @@ -1940,10 +1942,11 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request)
>          r = ssh_buffer_unpack(packet,
>                                "sd",
>                                &msg->global_request.bind_address,
> -                              &msg->global_request.bind_port);
> +                              &bind_port);
>          if (r != SSH_OK) {
>              goto reply_with_failure;
>          }
> +        msg->global_request.bind_port = (uint16_t)bind_port;
>          msg->global_request.type =
> SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD;
>          msg->global_request.want_reply = want_reply;
>
> --
> 2.55.0
>
>

Reply via email to