summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c82
1 files changed, 67 insertions, 15 deletions
diff --git a/channels.c b/channels.c
index 8550e51ca..1be213bce 100644
--- a/channels.c
+++ b/channels.c
@@ -39,7 +39,7 @@
39 */ 39 */
40 40
41#include "includes.h" 41#include "includes.h"
42RCSID("$OpenBSD: channels.c,v 1.211 2004/10/29 21:47:15 djm Exp $"); 42RCSID("$OpenBSD: channels.c,v 1.212 2005/03/01 10:09:52 djm Exp $");
43 43
44#include "ssh.h" 44#include "ssh.h"
45#include "ssh1.h" 45#include "ssh1.h"
@@ -2179,14 +2179,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2179 const char *host_to_connect, u_short port_to_connect, int gateway_ports) 2179 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2180{ 2180{
2181 Channel *c; 2181 Channel *c;
2182 int success, sock, on = 1; 2182 int sock, r, success = 0, on = 1, wildcard = 0, is_client;
2183 struct addrinfo hints, *ai, *aitop; 2183 struct addrinfo hints, *ai, *aitop;
2184 const char *host; 2184 const char *host, *addr;
2185 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 2185 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2186 2186
2187 success = 0;
2188 host = (type == SSH_CHANNEL_RPORT_LISTENER) ? 2187 host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2189 listen_addr : host_to_connect; 2188 listen_addr : host_to_connect;
2189 is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2190 2190
2191 if (host == NULL) { 2191 if (host == NULL) {
2192 error("No forward host name."); 2192 error("No forward host name.");
@@ -2198,16 +2198,60 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2198 } 2198 }
2199 2199
2200 /* 2200 /*
2201 * Determine whether or not a port forward listens to loopback,
2202 * specified address or wildcard. On the client, a specified bind
2203 * address will always override gateway_ports. On the server, a
2204 * gateway_ports of 1 (``yes'') will override the client's
2205 * specification and force a wildcard bind, whereas a value of 2
2206 * (``clientspecified'') will bind to whatever address the client
2207 * asked for.
2208 *
2209 * Special-case listen_addrs are:
2210 *
2211 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2212 * "" (empty string), "*" -> wildcard v4/v6
2213 * "localhost" -> loopback v4/v6
2214 */
2215 addr = NULL;
2216 if (listen_addr == NULL) {
2217 /* No address specified: default to gateway_ports setting */
2218 if (gateway_ports)
2219 wildcard = 1;
2220 } else if (gateway_ports || is_client) {
2221 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2222 strcmp(listen_addr, "0.0.0.0") == 0) ||
2223 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2224 (!is_client && gateway_ports == 1))
2225 wildcard = 1;
2226 else if (strcmp(listen_addr, "localhost") != 0)
2227 addr = listen_addr;
2228 }
2229
2230 debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
2231 type, wildcard, (addr == NULL) ? "NULL" : addr);
2232
2233 /*
2201 * getaddrinfo returns a loopback address if the hostname is 2234 * getaddrinfo returns a loopback address if the hostname is
2202 * set to NULL and hints.ai_flags is not AI_PASSIVE 2235 * set to NULL and hints.ai_flags is not AI_PASSIVE
2203 */ 2236 */
2204 memset(&hints, 0, sizeof(hints)); 2237 memset(&hints, 0, sizeof(hints));
2205 hints.ai_family = IPv4or6; 2238 hints.ai_family = IPv4or6;
2206 hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; 2239 hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2207 hints.ai_socktype = SOCK_STREAM; 2240 hints.ai_socktype = SOCK_STREAM;
2208 snprintf(strport, sizeof strport, "%d", listen_port); 2241 snprintf(strport, sizeof strport, "%d", listen_port);
2209 if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) 2242 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2210 packet_disconnect("getaddrinfo: fatal error"); 2243 if (addr == NULL) {
2244 /* This really shouldn't happen */
2245 packet_disconnect("getaddrinfo: fatal error: %s",
2246 gai_strerror(r));
2247 } else {
2248 verbose("channel_setup_fwd_listener: "
2249 "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
2250 packet_send_debug("channel_setup_fwd_listener: "
2251 "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
2252 }
2253 aitop = NULL;
2254 }
2211 2255
2212 for (ai = aitop; ai; ai = ai->ai_next) { 2256 for (ai = aitop; ai; ai = ai->ai_next) {
2213 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 2257 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@@ -2290,11 +2334,12 @@ channel_cancel_rport_listener(const char *host, u_short port)
2290 2334
2291/* protocol local port fwd, used by ssh (and sshd in v1) */ 2335/* protocol local port fwd, used by ssh (and sshd in v1) */
2292int 2336int
2293channel_setup_local_fwd_listener(u_short listen_port, 2337channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2294 const char *host_to_connect, u_short port_to_connect, int gateway_ports) 2338 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2295{ 2339{
2296 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, 2340 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2297 NULL, listen_port, host_to_connect, port_to_connect, gateway_ports); 2341 listen_host, listen_port, host_to_connect, port_to_connect,
2342 gateway_ports);
2298} 2343}
2299 2344
2300/* protocol v2 remote port fwd, used by sshd */ 2345/* protocol v2 remote port fwd, used by sshd */
@@ -2312,7 +2357,7 @@ channel_setup_remote_fwd_listener(const char *listen_address,
2312 */ 2357 */
2313 2358
2314void 2359void
2315channel_request_remote_forwarding(u_short listen_port, 2360channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2316 const char *host_to_connect, u_short port_to_connect) 2361 const char *host_to_connect, u_short port_to_connect)
2317{ 2362{
2318 int type, success = 0; 2363 int type, success = 0;
@@ -2323,7 +2368,14 @@ channel_request_remote_forwarding(u_short listen_port,
2323 2368
2324 /* Send the forward request to the remote side. */ 2369 /* Send the forward request to the remote side. */
2325 if (compat20) { 2370 if (compat20) {
2326 const char *address_to_bind = "0.0.0.0"; 2371 const char *address_to_bind;
2372 if (listen_host == NULL)
2373 address_to_bind = "localhost";
2374 else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0)
2375 address_to_bind = "";
2376 else
2377 address_to_bind = listen_host;
2378
2327 packet_start(SSH2_MSG_GLOBAL_REQUEST); 2379 packet_start(SSH2_MSG_GLOBAL_REQUEST);
2328 packet_put_cstring("tcpip-forward"); 2380 packet_put_cstring("tcpip-forward");
2329 packet_put_char(1); /* boolean: want reply */ 2381 packet_put_char(1); /* boolean: want reply */
@@ -2369,10 +2421,9 @@ channel_request_remote_forwarding(u_short listen_port,
2369 * local side. 2421 * local side.
2370 */ 2422 */
2371void 2423void
2372channel_request_rforward_cancel(u_short port) 2424channel_request_rforward_cancel(const char *host, u_short port)
2373{ 2425{
2374 int i; 2426 int i;
2375 const char *address_to_bind = "0.0.0.0";
2376 2427
2377 if (!compat20) 2428 if (!compat20)
2378 return; 2429 return;
@@ -2389,7 +2440,7 @@ channel_request_rforward_cancel(u_short port)
2389 packet_start(SSH2_MSG_GLOBAL_REQUEST); 2440 packet_start(SSH2_MSG_GLOBAL_REQUEST);
2390 packet_put_cstring("cancel-tcpip-forward"); 2441 packet_put_cstring("cancel-tcpip-forward");
2391 packet_put_char(0); 2442 packet_put_char(0);
2392 packet_put_cstring(address_to_bind); 2443 packet_put_cstring(host == NULL ? "" : host);
2393 packet_put_int(port); 2444 packet_put_int(port);
2394 packet_send(); 2445 packet_send();
2395 2446
@@ -2430,7 +2481,8 @@ channel_input_port_forward_request(int is_root, int gateway_ports)
2430#endif 2481#endif
2431 2482
2432 /* Initiate forwarding */ 2483 /* Initiate forwarding */
2433 channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports); 2484 channel_setup_local_fwd_listener(NULL, port, hostname,
2485 host_port, gateway_ports);
2434 2486
2435 /* Free the argument string. */ 2487 /* Free the argument string. */
2436 xfree(hostname); 2488 xfree(hostname);