diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 82 |
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" |
42 | RCSID("$OpenBSD: channels.c,v 1.211 2004/10/29 21:47:15 djm Exp $"); | 42 | RCSID("$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) */ |
2292 | int | 2336 | int |
2293 | channel_setup_local_fwd_listener(u_short listen_port, | 2337 | channel_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 | ||
2314 | void | 2359 | void |
2315 | channel_request_remote_forwarding(u_short listen_port, | 2360 | channel_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 | */ |
2371 | void | 2423 | void |
2372 | channel_request_rforward_cancel(u_short port) | 2424 | channel_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); |