[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] messages: Parse the forwarding bind port as the uint32 it is on the wire


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 <daniel@xxxxxxxxxxxxxx> 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 <daniel@xxxxxxxxxxxxxx>
> ---
> 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
>
>

Archive administrator: postmaster@lists.cynapses.org