From 68afb8c5f242ec74f48fd86137122399435dd757 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sun, 2 Oct 2011 18:59:03 +1100 Subject: - markus@cvs.openbsd.org 2011/09/23 07:45:05 [mux.c readconf.h channels.h compat.h compat.c ssh.c readconf.c channels.c version.h] unbreak remote portforwarding with dynamic allocated listen ports: 1) send the actual listen port in the open message (instead of 0). this allows multiple forwardings with a dynamic listen port 2) update the matching permit-open entry, so we can identify where to connect to report: den at skbkontur.ru and P. Szczygielski feedback and ok djm@ --- channels.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'channels.c') diff --git a/channels.c b/channels.c index 00e9af84..f6e9b4d8 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.314 2011/09/23 00:22:04 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.315 2011/09/23 07:45:05 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2814,8 +2814,12 @@ channel_setup_fwd_listener(int type, const char *listen_addr, 0, "port listener", 1); c->path = xstrdup(host); c->host_port = port_to_connect; - c->listening_port = listen_port; c->listening_addr = addr == NULL ? NULL : xstrdup(addr); + if (listen_port == 0 && allocated_listen_port != NULL && + !(datafellows & SSH_BUG_DYNAMIC_RPORT)) + c->listening_port = *allocated_listen_port; + else + c->listening_port = listen_port; success = 1; } if (success == 0) @@ -2924,12 +2928,14 @@ channel_rfwd_bind_host(const char *listen_host) /* * Initiate forwarding of connections to port "port" on remote host through * the secure channel to host:port from local side. + * Returns handle (index) for updating the dynamic listen port with + * channel_update_permitted_opens(). */ int channel_request_remote_forwarding(const char *listen_host, u_short listen_port, const char *host_to_connect, u_short port_to_connect) { - int type, success = 0; + int type, success = 0, idx = -1; /* Send the forward request to the remote side. */ if (compat20) { @@ -2968,12 +2974,12 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port, /* Record that connection to this host/port is permitted. */ permitted_opens = xrealloc(permitted_opens, num_permitted_opens + 1, sizeof(*permitted_opens)); - permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); - permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; - permitted_opens[num_permitted_opens].listen_port = listen_port; - num_permitted_opens++; + idx = num_permitted_opens++; + permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); + permitted_opens[idx].port_to_connect = port_to_connect; + permitted_opens[idx].listen_port = listen_port; } - return (success ? 0 : -1); + return (idx); } /* @@ -3078,6 +3084,35 @@ channel_add_permitted_opens(char *host, int port) all_opens_permitted = 0; } +/* + * Update the listen port for a dynamic remote forward, after + * the actual 'newport' has been allocated. If 'newport' < 0 is + * passed then they entry will be invalidated. + */ +void +channel_update_permitted_opens(int idx, int newport) +{ + if (idx < 0 || idx >= num_permitted_opens) { + debug("channel_update_permitted_opens: index out of range:" + " %d num_permitted_opens %d", idx, num_permitted_opens); + return; + } + debug("%s allowed port %d for forwarding to host %s port %d", + newport > 0 ? "Updating" : "Removing", + newport, + permitted_opens[idx].host_to_connect, + permitted_opens[idx].port_to_connect); + if (newport >= 0) { + permitted_opens[idx].listen_port = + (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; + } else { + permitted_opens[idx].listen_port = 0; + permitted_opens[idx].port_to_connect = 0; + xfree(permitted_opens[idx].host_to_connect); + permitted_opens[idx].host_to_connect = NULL; + } +} + int channel_add_adm_permitted_opens(char *host, int port) { -- cgit v1.2.3