summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2005-03-01 21:24:33 +1100
committerDamien Miller <djm@mindrot.org>2005-03-01 21:24:33 +1100
commitf91ee4c3def4de8b4b9409f07ab26a61e535e1e6 (patch)
tree92d9f883c3c34f0d80b49a7855dcc2514798cf02
parent1717fd422f2c5691d745a7daf6908df9a6458904 (diff)
- djm@cvs.openbsd.org 2005/03/01 10:09:52
[auth-options.c channels.c channels.h clientloop.c compat.c compat.h] [misc.c misc.h readconf.c readconf.h servconf.c ssh.1 ssh.c ssh_config.5] [sshd_config.5] bz#413: allow optional specification of bind address for port forwardings. Patch originally by Dan Astorian, but worked on by several people Adds GatewayPorts=clientspecified option on server to allow remote forwards to bind to client-specified ports.
-rw-r--r--ChangeLog10
-rw-r--r--auth-options.c28
-rw-r--r--channels.c82
-rw-r--r--channels.h10
-rw-r--r--clientloop.c49
-rw-r--r--compat.c20
-rw-r--r--compat.h3
-rw-r--r--misc.c44
-rw-r--r--misc.h3
-rw-r--r--readconf.c157
-rw-r--r--readconf.h14
-rw-r--r--servconf.c65
-rw-r--r--ssh.159
-rw-r--r--ssh.c110
-rw-r--r--ssh_config.570
-rw-r--r--sshd_config.515
16 files changed, 525 insertions, 214 deletions
diff --git a/ChangeLog b/ChangeLog
index e4ec748f0..f31a52665 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,14 @@
19 [ssh_config.5] 19 [ssh_config.5]
20 bz#849: document timeout on untrusted x11 forwarding sessions. Reported by 20 bz#849: document timeout on untrusted x11 forwarding sessions. Reported by
21 orion AT cora.nwra.com; ok markus@ 21 orion AT cora.nwra.com; ok markus@
22 - djm@cvs.openbsd.org 2005/03/01 10:09:52
23 [auth-options.c channels.c channels.h clientloop.c compat.c compat.h]
24 [misc.c misc.h readconf.c readconf.h servconf.c ssh.1 ssh.c ssh_config.5]
25 [sshd_config.5]
26 bz#413: allow optional specification of bind address for port forwardings.
27 Patch originally by Dan Astorian, but worked on by several people
28 Adds GatewayPorts=clientspecified option on server to allow remote
29 forwards to bind to client-specified ports.
22 30
2320050226 3120050226
24 - (dtucker) [openbsd-compat/bsd-openpty.c openbsd-compat/inet_ntop.c] 32 - (dtucker) [openbsd-compat/bsd-openpty.c openbsd-compat/inet_ntop.c]
@@ -2195,4 +2203,4 @@
2195 - (djm) Trim deprecated options from INSTALL. Mention UsePAM 2203 - (djm) Trim deprecated options from INSTALL. Mention UsePAM
2196 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 2204 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
2197 2205
2198$Id: ChangeLog,v 1.3671 2005/03/01 10:17:31 djm Exp $ 2206$Id: ChangeLog,v 1.3672 2005/03/01 10:24:33 djm Exp $
diff --git a/auth-options.c b/auth-options.c
index 0e146ab15..04d12d66e 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth-options.c,v 1.28 2003/06/02 09:17:34 markus Exp $"); 13RCSID("$OpenBSD: auth-options.c,v 1.29 2005/03/01 10:09:52 djm Exp $");
14 14
15#include "xmalloc.h" 15#include "xmalloc.h"
16#include "match.h" 16#include "match.h"
@@ -217,7 +217,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
217 } 217 }
218 cp = "permitopen=\""; 218 cp = "permitopen=\"";
219 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 219 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
220 char host[256], sport[6]; 220 char *host, *p;
221 u_short port; 221 u_short port;
222 char *patterns = xmalloc(strlen(opts) + 1); 222 char *patterns = xmalloc(strlen(opts) + 1);
223 223
@@ -236,25 +236,29 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
236 if (!*opts) { 236 if (!*opts) {
237 debug("%.100s, line %lu: missing end quote", 237 debug("%.100s, line %lu: missing end quote",
238 file, linenum); 238 file, linenum);
239 auth_debug_add("%.100s, line %lu: missing end quote", 239 auth_debug_add("%.100s, line %lu: missing "
240 file, linenum); 240 "end quote", file, linenum);
241 xfree(patterns); 241 xfree(patterns);
242 goto bad_option; 242 goto bad_option;
243 } 243 }
244 patterns[i] = 0; 244 patterns[i] = 0;
245 opts++; 245 opts++;
246 if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && 246 p = patterns;
247 sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { 247 host = hpdelim(&p);
248 debug("%.100s, line %lu: Bad permitopen specification " 248 if (host == NULL || strlen(host) >= NI_MAXHOST) {
249 "<%.100s>", file, linenum, patterns); 249 debug("%.100s, line %lu: Bad permitopen "
250 "specification <%.100s>", file, linenum,
251 patterns);
250 auth_debug_add("%.100s, line %lu: " 252 auth_debug_add("%.100s, line %lu: "
251 "Bad permitopen specification", file, linenum); 253 "Bad permitopen specification", file,
254 linenum);
252 xfree(patterns); 255 xfree(patterns);
253 goto bad_option; 256 goto bad_option;
254 } 257 }
255 if ((port = a2port(sport)) == 0) { 258 host = cleanhostname(host);
256 debug("%.100s, line %lu: Bad permitopen port <%.100s>", 259 if (p == NULL || (port = a2port(p)) == 0) {
257 file, linenum, sport); 260 debug("%.100s, line %lu: Bad permitopen port "
261 "<%.100s>", file, linenum, p ? p : "");
258 auth_debug_add("%.100s, line %lu: " 262 auth_debug_add("%.100s, line %lu: "
259 "Bad permitopen port", file, linenum); 263 "Bad permitopen port", file, linenum);
260 xfree(patterns); 264 xfree(patterns);
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);
diff --git a/channels.h b/channels.h
index c47de55c0..fc20fb2c3 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.75 2004/10/29 21:47:15 djm Exp $ */ 1/* $OpenBSD: channels.h,v 1.76 2005/03/01 10:09:52 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -203,9 +203,11 @@ void channel_clear_permitted_opens(void);
203void channel_input_port_forward_request(int, int); 203void channel_input_port_forward_request(int, int);
204int channel_connect_to(const char *, u_short); 204int channel_connect_to(const char *, u_short);
205int channel_connect_by_listen_address(u_short); 205int channel_connect_by_listen_address(u_short);
206void channel_request_remote_forwarding(u_short, const char *, u_short); 206void channel_request_remote_forwarding(const char *, u_short,
207void channel_request_rforward_cancel(u_short port); 207 const char *, u_short);
208int channel_setup_local_fwd_listener(u_short, const char *, u_short, int); 208int channel_setup_local_fwd_listener(const char *, u_short,
209 const char *, u_short, int);
210void channel_request_rforward_cancel(const char *host, u_short port);
209int channel_setup_remote_fwd_listener(const char *, u_short, int); 211int channel_setup_remote_fwd_listener(const char *, u_short, int);
210int channel_cancel_rport_listener(const char *, u_short); 212int channel_cancel_rport_listener(const char *, u_short);
211 213
diff --git a/clientloop.c b/clientloop.c
index 033a98a5b..1e250883f 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.134 2004/11/07 00:01:46 djm Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -763,11 +763,11 @@ static void
763process_cmdline(void) 763process_cmdline(void)
764{ 764{
765 void (*handler)(int); 765 void (*handler)(int);
766 char *s, *cmd; 766 char *s, *cmd, *cancel_host;
767 u_short fwd_port, fwd_host_port;
768 char buf[1024], sfwd_port[6], sfwd_host_port[6];
769 int delete = 0; 767 int delete = 0;
770 int local = 0; 768 int local = 0;
769 u_short cancel_port;
770 Forward fwd;
771 771
772 leave_raw_mode(); 772 leave_raw_mode();
773 handler = signal(SIGINT, SIG_IGN); 773 handler = signal(SIGINT, SIG_IGN);
@@ -813,37 +813,38 @@ process_cmdline(void)
813 s++; 813 s++;
814 814
815 if (delete) { 815 if (delete) {
816 if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) { 816 cancel_port = 0;
817 logit("Bad forwarding specification."); 817 cancel_host = hpdelim(&s); /* may be NULL */
818 goto out; 818 if (s != NULL) {
819 cancel_port = a2port(s);
820 cancel_host = cleanhostname(cancel_host);
821 } else {
822 cancel_port = a2port(cancel_host);
823 cancel_host = NULL;
819 } 824 }
820 if ((fwd_host_port = a2port(sfwd_host_port)) == 0) { 825 if (cancel_port == 0) {
821 logit("Bad forwarding port(s)."); 826 logit("Bad forwarding close port");
822 goto out; 827 goto out;
823 } 828 }
824 channel_request_rforward_cancel(fwd_host_port); 829 channel_request_rforward_cancel(cancel_host, cancel_port);
825 } else { 830 } else {
826 if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", 831 if (!parse_forward(&fwd, s)) {
827 sfwd_port, buf, sfwd_host_port) != 3 &&
828 sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
829 sfwd_port, buf, sfwd_host_port) != 3) {
830 logit("Bad forwarding specification."); 832 logit("Bad forwarding specification.");
831 goto out; 833 goto out;
832 } 834 }
833 if ((fwd_port = a2port(sfwd_port)) == 0 ||
834 (fwd_host_port = a2port(sfwd_host_port)) == 0) {
835 logit("Bad forwarding port(s).");
836 goto out;
837 }
838 if (local) { 835 if (local) {
839 if (channel_setup_local_fwd_listener(fwd_port, buf, 836 if (channel_setup_local_fwd_listener(fwd.listen_host,
840 fwd_host_port, options.gateway_ports) < 0) { 837 fwd.listen_port, fwd.connect_host,
838 fwd.connect_port, options.gateway_ports) < 0) {
841 logit("Port forwarding failed."); 839 logit("Port forwarding failed.");
842 goto out; 840 goto out;
843 } 841 }
844 } else 842 } else {
845 channel_request_remote_forwarding(fwd_port, buf, 843 channel_request_remote_forwarding(fwd.listen_host,
846 fwd_host_port); 844 fwd.listen_port, fwd.connect_host,
845 fwd.connect_port);
846 }
847
847 logit("Forwarding port."); 848 logit("Forwarding port.");
848 } 849 }
849 850
diff --git a/compat.c b/compat.c
index 2fdebe7fa..4086e853e 100644
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: compat.c,v 1.70 2003/11/02 11:01:03 markus Exp $"); 26RCSID("$OpenBSD: compat.c,v 1.71 2005/03/01 10:09:52 djm Exp $");
27 27
28#include "buffer.h" 28#include "buffer.h"
29#include "packet.h" 29#include "packet.h"
@@ -62,24 +62,28 @@ compat_datafellows(const char *version)
62 "OpenSSH_2.1*," 62 "OpenSSH_2.1*,"
63 "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| 63 "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
64 SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 64 SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
65 SSH_BUG_EXTEOF}, 65 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
66 { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| 66 { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
67 SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 67 SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
68 SSH_BUG_EXTEOF}, 68 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
69 { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 69 { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
70 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 70 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
71 SSH_OLD_FORWARD_ADDR},
71 { "OpenSSH_2.5.0p1*," 72 { "OpenSSH_2.5.0p1*,"
72 "OpenSSH_2.5.1p1*", 73 "OpenSSH_2.5.1p1*",
73 SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 74 SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
74 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 75 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
76 SSH_OLD_FORWARD_ADDR},
75 { "OpenSSH_2.5.0*," 77 { "OpenSSH_2.5.0*,"
76 "OpenSSH_2.5.1*," 78 "OpenSSH_2.5.1*,"
77 "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 79 "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
78 SSH_BUG_EXTEOF}, 80 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
79 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 81 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
82 SSH_OLD_FORWARD_ADDR},
80 { "OpenSSH_2.*," 83 { "OpenSSH_2.*,"
81 "OpenSSH_3.0*," 84 "OpenSSH_3.0*,"
82 "OpenSSH_3.1*", SSH_BUG_EXTEOF}, 85 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
86 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR },
83 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 87 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
84 { "OpenSSH*", 0 }, 88 { "OpenSSH*", 0 },
85 { "*MindTerm*", 0 }, 89 { "*MindTerm*", 0 },
diff --git a/compat.h b/compat.h
index 5efb5c29e..cf92dbdee 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.h,v 1.38 2004/07/11 17:48:47 deraadt Exp $ */ 1/* $OpenBSD: compat.h,v 1.39 2005/03/01 10:09:52 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -55,6 +55,7 @@
55#define SSH_BUG_EXTEOF 0x00200000 55#define SSH_BUG_EXTEOF 0x00200000
56#define SSH_BUG_PROBE 0x00400000 56#define SSH_BUG_PROBE 0x00400000
57#define SSH_BUG_FIRSTKEX 0x00800000 57#define SSH_BUG_FIRSTKEX 0x00800000
58#define SSH_OLD_FORWARD_ADDR 0x01000000
58 59
59void enable_compat13(void); 60void enable_compat13(void);
60void enable_compat20(void); 61void enable_compat20(void);
diff --git a/misc.c b/misc.c
index a90125505..2e366f81b 100644
--- a/misc.c
+++ b/misc.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: misc.c,v 1.27 2004/12/11 01:48:56 dtucker Exp $"); 26RCSID("$OpenBSD: misc.c,v 1.28 2005/03/01 10:09:52 djm Exp $");
27 27
28#include "misc.h" 28#include "misc.h"
29#include "log.h" 29#include "log.h"
@@ -275,6 +275,48 @@ convtime(const char *s)
275 return total; 275 return total;
276} 276}
277 277
278/*
279 * Search for next delimiter between hostnames/addresses and ports.
280 * Argument may be modified (for termination).
281 * Returns *cp if parsing succeeds.
282 * *cp is set to the start of the next delimiter, if one was found.
283 * If this is the last field, *cp is set to NULL.
284 */
285char *
286hpdelim(char **cp)
287{
288 char *s, *old;
289
290 if (cp == NULL || *cp == NULL)
291 return NULL;
292
293 old = s = *cp;
294 if (*s == '[') {
295 if ((s = strchr(s, ']')) == NULL)
296 return NULL;
297 else
298 s++;
299 } else if ((s = strpbrk(s, ":/")) == NULL)
300 s = *cp + strlen(*cp); /* skip to end (see first case below) */
301
302 switch (*s) {
303 case '\0':
304 *cp = NULL; /* no more fields*/
305 break;
306
307 case ':':
308 case '/':
309 *s = '\0'; /* terminate */
310 *cp = s + 1;
311 break;
312
313 default:
314 return NULL;
315 }
316
317 return old;
318}
319
278char * 320char *
279cleanhostname(char *host) 321cleanhostname(char *host)
280{ 322{
diff --git a/misc.h b/misc.h
index 193216fa9..8bbc87f0d 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.h,v 1.20 2004/12/11 01:48:56 dtucker Exp $ */ 1/* $OpenBSD: misc.h,v 1.21 2005/03/01 10:09:52 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -20,6 +20,7 @@ int set_nonblock(int);
20int unset_nonblock(int); 20int unset_nonblock(int);
21void set_nodelay(int); 21void set_nodelay(int);
22int a2port(const char *); 22int a2port(const char *);
23char *hpdelim(char **);
23char *cleanhostname(char *); 24char *cleanhostname(char *);
24char *colon(char *); 25char *colon(char *);
25long convtime(const char *); 26long convtime(const char *);
diff --git a/readconf.c b/readconf.c
index a4fe1fe02..c3dc71e66 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: readconf.c,v 1.134 2004/07/11 17:48:47 deraadt Exp $"); 15RCSID("$OpenBSD: readconf.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "xmalloc.h" 18#include "xmalloc.h"
@@ -206,21 +206,23 @@ static struct {
206 */ 206 */
207 207
208void 208void
209add_local_forward(Options *options, u_short port, const char *host, 209add_local_forward(Options *options, const Forward *newfwd)
210 u_short host_port)
211{ 210{
212 Forward *fwd; 211 Forward *fwd;
213#ifndef NO_IPPORT_RESERVED_CONCEPT 212#ifndef NO_IPPORT_RESERVED_CONCEPT
214 extern uid_t original_real_uid; 213 extern uid_t original_real_uid;
215 if (port < IPPORT_RESERVED && original_real_uid != 0) 214 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
216 fatal("Privileged ports can only be forwarded by root."); 215 fatal("Privileged ports can only be forwarded by root.");
217#endif 216#endif
218 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 217 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
219 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 218 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
220 fwd = &options->local_forwards[options->num_local_forwards++]; 219 fwd = &options->local_forwards[options->num_local_forwards++];
221 fwd->port = port; 220
222 fwd->host = xstrdup(host); 221 fwd->listen_host = (newfwd->listen_host == NULL) ?
223 fwd->host_port = host_port; 222 NULL : xstrdup(newfwd->listen_host);
223 fwd->listen_port = newfwd->listen_port;
224 fwd->connect_host = xstrdup(newfwd->connect_host);
225 fwd->connect_port = newfwd->connect_port;
224} 226}
225 227
226/* 228/*
@@ -229,17 +231,19 @@ add_local_forward(Options *options, u_short port, const char *host,
229 */ 231 */
230 232
231void 233void
232add_remote_forward(Options *options, u_short port, const char *host, 234add_remote_forward(Options *options, const Forward *newfwd)
233 u_short host_port)
234{ 235{
235 Forward *fwd; 236 Forward *fwd;
236 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 237 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
237 fatal("Too many remote forwards (max %d).", 238 fatal("Too many remote forwards (max %d).",
238 SSH_MAX_FORWARDS_PER_DIRECTION); 239 SSH_MAX_FORWARDS_PER_DIRECTION);
239 fwd = &options->remote_forwards[options->num_remote_forwards++]; 240 fwd = &options->remote_forwards[options->num_remote_forwards++];
240 fwd->port = port; 241
241 fwd->host = xstrdup(host); 242 fwd->listen_host = (newfwd->listen_host == NULL) ?
242 fwd->host_port = host_port; 243 NULL : xstrdup(newfwd->listen_host);
244 fwd->listen_port = newfwd->listen_port;
245 fwd->connect_host = xstrdup(newfwd->connect_host);
246 fwd->connect_port = newfwd->connect_port;
243} 247}
244 248
245static void 249static void
@@ -247,11 +251,15 @@ clear_forwardings(Options *options)
247{ 251{
248 int i; 252 int i;
249 253
250 for (i = 0; i < options->num_local_forwards; i++) 254 for (i = 0; i < options->num_local_forwards; i++) {
251 xfree(options->local_forwards[i].host); 255 xfree(options->local_forwards[i].listen_host);
256 xfree(options->local_forwards[i].connect_host);
257 }
252 options->num_local_forwards = 0; 258 options->num_local_forwards = 0;
253 for (i = 0; i < options->num_remote_forwards; i++) 259 for (i = 0; i < options->num_remote_forwards; i++) {
254 xfree(options->remote_forwards[i].host); 260 xfree(options->remote_forwards[i].listen_host);
261 xfree(options->remote_forwards[i].connect_host);
262 }
255 options->num_remote_forwards = 0; 263 options->num_remote_forwards = 0;
256} 264}
257 265
@@ -284,11 +292,10 @@ process_config_line(Options *options, const char *host,
284 char *line, const char *filename, int linenum, 292 char *line, const char *filename, int linenum,
285 int *activep) 293 int *activep)
286{ 294{
287 char buf[256], *s, **charptr, *endofnumber, *keyword, *arg; 295 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
288 int opcode, *intptr, value; 296 int opcode, *intptr, value;
289 size_t len; 297 size_t len;
290 u_short fwd_port, fwd_host_port; 298 Forward fwd;
291 char sfwd_host_port[6];
292 299
293 /* Strip trailing whitespace */ 300 /* Strip trailing whitespace */
294 for(len = strlen(line) - 1; len > 0; len--) { 301 for(len = strlen(line) - 1; len > 0; len--) {
@@ -645,30 +652,26 @@ parse_int:
645 case oLocalForward: 652 case oLocalForward:
646 case oRemoteForward: 653 case oRemoteForward:
647 arg = strdelim(&s); 654 arg = strdelim(&s);
648 if (!arg || *arg == '\0') 655 if (arg == NULL || *arg == '\0')
649 fatal("%.200s line %d: Missing port argument.", 656 fatal("%.200s line %d: Missing port argument.",
650 filename, linenum); 657 filename, linenum);
651 if ((fwd_port = a2port(arg)) == 0) 658 arg2 = strdelim(&s);
652 fatal("%.200s line %d: Bad listen port.", 659 if (arg2 == NULL || *arg2 == '\0')
660 fatal("%.200s line %d: Missing target argument.",
653 filename, linenum); 661 filename, linenum);
654 arg = strdelim(&s); 662
655 if (!arg || *arg == '\0') 663 /* construct a string for parse_forward */
656 fatal("%.200s line %d: Missing second argument.", 664 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
657 filename, linenum); 665
658 if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && 666 if (parse_forward(&fwd, fwdarg) == 0)
659 sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
660 fatal("%.200s line %d: Bad forwarding specification.", 667 fatal("%.200s line %d: Bad forwarding specification.",
661 filename, linenum); 668 filename, linenum);
662 if ((fwd_host_port = a2port(sfwd_host_port)) == 0) 669
663 fatal("%.200s line %d: Bad forwarding port.",
664 filename, linenum);
665 if (*activep) { 670 if (*activep) {
666 if (opcode == oLocalForward) 671 if (opcode == oLocalForward)
667 add_local_forward(options, fwd_port, buf, 672 add_local_forward(options, &fwd);
668 fwd_host_port);
669 else if (opcode == oRemoteForward) 673 else if (opcode == oRemoteForward)
670 add_remote_forward(options, fwd_port, buf, 674 add_remote_forward(options, &fwd);
671 fwd_host_port);
672 } 675 }
673 break; 676 break;
674 677
@@ -677,12 +680,25 @@ parse_int:
677 if (!arg || *arg == '\0') 680 if (!arg || *arg == '\0')
678 fatal("%.200s line %d: Missing port argument.", 681 fatal("%.200s line %d: Missing port argument.",
679 filename, linenum); 682 filename, linenum);
680 fwd_port = a2port(arg); 683 memset(&fwd, '\0', sizeof(fwd));
681 if (fwd_port == 0) 684 fwd.connect_host = "socks";
685 fwd.listen_host = hpdelim(&arg);
686 if (fwd.listen_host == NULL ||
687 strlen(fwd.listen_host) >= NI_MAXHOST)
688 fatal("%.200s line %d: Bad forwarding specification.",
689 filename, linenum);
690 if (arg) {
691 fwd.listen_port = a2port(arg);
692 fwd.listen_host = cleanhostname(fwd.listen_host);
693 } else {
694 fwd.listen_port = a2port(fwd.listen_host);
695 fwd.listen_host = "";
696 }
697 if (fwd.listen_port == 0)
682 fatal("%.200s line %d: Badly formatted port number.", 698 fatal("%.200s line %d: Badly formatted port number.",
683 filename, linenum); 699 filename, linenum);
684 if (*activep) 700 if (*activep)
685 add_local_forward(options, fwd_port, "socks", 0); 701 add_local_forward(options, &fwd);
686 break; 702 break;
687 703
688 case oClearAllForwardings: 704 case oClearAllForwardings:
@@ -1045,3 +1061,68 @@ fill_default_options(Options * options)
1045 /* options->host_key_alias should not be set by default */ 1061 /* options->host_key_alias should not be set by default */
1046 /* options->preferred_authentications will be set in ssh */ 1062 /* options->preferred_authentications will be set in ssh */
1047} 1063}
1064
1065/*
1066 * parse_forward
1067 * parses a string containing a port forwarding specification of the form:
1068 * [listenhost:]listenport:connecthost:connectport
1069 * returns number of arguments parsed or zero on error
1070 */
1071int
1072parse_forward(Forward *fwd, const char *fwdspec)
1073{
1074 int i;
1075 char *p, *cp, *fwdarg[4];
1076
1077 memset(fwd, '\0', sizeof(*fwd));
1078
1079 cp = p = xstrdup(fwdspec);
1080
1081 /* skip leading spaces */
1082 while (*cp && isspace(*cp))
1083 cp++;
1084
1085 for (i = 0; i < 4; ++i)
1086 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1087 break;
1088
1089 /* Check for trailing garbage in 4-arg case*/
1090 if (cp != NULL)
1091 i = 0; /* failure */
1092
1093 switch (i) {
1094 case 3:
1095 fwd->listen_host = NULL;
1096 fwd->listen_port = a2port(fwdarg[0]);
1097 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1098 fwd->connect_port = a2port(fwdarg[2]);
1099 break;
1100
1101 case 4:
1102 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1103 fwd->listen_port = a2port(fwdarg[1]);
1104 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1105 fwd->connect_port = a2port(fwdarg[3]);
1106 break;
1107 default:
1108 i = 0; /* failure */
1109 }
1110
1111 xfree(p);
1112
1113 if (fwd->listen_port == 0 && fwd->connect_port == 0)
1114 goto fail_free;
1115
1116 if (fwd->connect_host != NULL &&
1117 strlen(fwd->connect_host) >= NI_MAXHOST)
1118 goto fail_free;
1119
1120 return (i);
1121
1122 fail_free:
1123 if (fwd->connect_host != NULL)
1124 xfree(fwd->connect_host);
1125 if (fwd->listen_host != NULL)
1126 xfree(fwd->listen_host);
1127 return (0);
1128}
diff --git a/readconf.h b/readconf.h
index ded422585..03b772a2d 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.64 2004/07/11 17:48:47 deraadt Exp $ */ 1/* $OpenBSD: readconf.h,v 1.65 2005/03/01 10:09:52 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -21,9 +21,10 @@
21/* Data structure for representing a forwarding request. */ 21/* Data structure for representing a forwarding request. */
22 22
23typedef struct { 23typedef struct {
24 u_short port; /* Port to forward. */ 24 char *listen_host; /* Host (address) to listen on. */
25 char *host; /* Host to connect. */ 25 u_short listen_port; /* Port to forward. */
26 u_short host_port; /* Port to connect on host. */ 26 char *connect_host; /* Host to connect. */
27 u_short connect_port; /* Port to connect on connect_host. */
27} Forward; 28} Forward;
28/* Data structure for representing option data. */ 29/* Data structure for representing option data. */
29 30
@@ -117,11 +118,12 @@ typedef struct {
117void initialize_options(Options *); 118void initialize_options(Options *);
118void fill_default_options(Options *); 119void fill_default_options(Options *);
119int read_config_file(const char *, const char *, Options *, int); 120int read_config_file(const char *, const char *, Options *, int);
121int parse_forward(Forward *, const char *);
120 122
121int 123int
122process_config_line(Options *, const char *, char *, const char *, int, int *); 124process_config_line(Options *, const char *, char *, const char *, int, int *);
123 125
124void add_local_forward(Options *, u_short, const char *, u_short); 126void add_local_forward(Options *, const Forward *);
125void add_remote_forward(Options *, u_short, const char *, u_short); 127void add_remote_forward(Options *, const Forward *);
126 128
127#endif /* READCONF_H */ 129#endif /* READCONF_H */
diff --git a/servconf.c b/servconf.c
index 541a9c85b..2d1a0c362 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.138 2004/12/23 23:11:00 djm Exp $"); 13RCSID("$OpenBSD: servconf.c,v 1.139 2005/03/01 10:09:52 djm Exp $");
14 14
15#include "ssh.h" 15#include "ssh.h"
16#include "log.h" 16#include "log.h"
@@ -440,6 +440,7 @@ process_server_config_line(ServerOptions *options, char *line,
440 char *cp, **charptr, *arg, *p; 440 char *cp, **charptr, *arg, *p;
441 int *intptr, value, i, n; 441 int *intptr, value, i, n;
442 ServerOpCodes opcode; 442 ServerOpCodes opcode;
443 u_short port;
443 444
444 cp = line; 445 cp = line;
445 arg = strdelim(&cp); 446 arg = strdelim(&cp);
@@ -512,39 +513,21 @@ parse_time:
512 513
513 case sListenAddress: 514 case sListenAddress:
514 arg = strdelim(&cp); 515 arg = strdelim(&cp);
515 if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) 516 if (arg == NULL || *arg == '\0')
516 fatal("%s line %d: missing inet addr.", 517 fatal("%s line %d: missing address",
517 filename, linenum); 518 filename, linenum);
518 if (*arg == '[') { 519 p = hpdelim(&arg);
519 if ((p = strchr(arg, ']')) == NULL) 520 if (p == NULL)
520 fatal("%s line %d: bad ipv6 inet addr usage.", 521 fatal("%s line %d: bad address:port usage",
521 filename, linenum);
522 arg++;
523 memmove(p, p+1, strlen(p+1)+1);
524 } else if (((p = strchr(arg, ':')) == NULL) ||
525 (strchr(p+1, ':') != NULL)) {
526 add_listen_addr(options, arg, 0);
527 break;
528 }
529 if (*p == ':') {
530 u_short port;
531
532 p++;
533 if (*p == '\0')
534 fatal("%s line %d: bad inet addr:port usage.",
535 filename, linenum);
536 else {
537 *(p-1) = '\0';
538 if ((port = a2port(p)) == 0)
539 fatal("%s line %d: bad port number.",
540 filename, linenum);
541 add_listen_addr(options, arg, port);
542 }
543 } else if (*p == '\0')
544 add_listen_addr(options, arg, 0);
545 else
546 fatal("%s line %d: bad inet addr usage.",
547 filename, linenum); 522 filename, linenum);
523 p = cleanhostname(p);
524 if (arg == NULL)
525 port = 0;
526 else if ((port = a2port(arg)) == 0)
527 fatal("%s line %d: bad port number", filename, linenum);
528
529 add_listen_addr(options, p, port);
530
548 break; 531 break;
549 532
550 case sAddressFamily: 533 case sAddressFamily:
@@ -742,7 +725,23 @@ parse_flag:
742 725
743 case sGatewayPorts: 726 case sGatewayPorts:
744 intptr = &options->gateway_ports; 727 intptr = &options->gateway_ports;
745 goto parse_flag; 728 arg = strdelim(&cp);
729 if (!arg || *arg == '\0')
730 fatal("%s line %d: missing yes/no/clientspecified "
731 "argument.", filename, linenum);
732 value = 0; /* silence compiler */
733 if (strcmp(arg, "clientspecified") == 0)
734 value = 2;
735 else if (strcmp(arg, "yes") == 0)
736 value = 1;
737 else if (strcmp(arg, "no") == 0)
738 value = 0;
739 else
740 fatal("%s line %d: Bad yes/no/clientspecified "
741 "argument: %s", filename, linenum, arg);
742 if (*intptr == -1)
743 *intptr = value;
744 break;
746 745
747 case sUseDNS: 746 case sUseDNS:
748 intptr = &options->use_dns; 747 intptr = &options->use_dns;
diff --git a/ssh.1 b/ssh.1
index b8a91a160..27da08c69 100644
--- a/ssh.1
+++ b/ssh.1
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: ssh.1,v 1.199 2004/11/07 17:42:36 jmc Exp $ 37.\" $OpenBSD: ssh.1,v 1.200 2005/03/01 10:09:52 djm Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSH 1 39.Dt SSH 1
40.Os 40.Os
@@ -53,13 +53,13 @@
53.Op Fl i Ar identity_file 53.Op Fl i Ar identity_file
54.Oo Fl L Xo 54.Oo Fl L Xo
55.Sm off 55.Sm off
56.Oo Ar bind_address : Oc
56.Ar port : 57.Ar port :
57.Ar host : 58.Ar host :
58.Ar hostport 59.Ar hostport
59.Sm on 60.Sm on
60.Xc 61.Xc
61.Oc 62.Oc
62.Ek
63.Op Fl l Ar login_name 63.Op Fl l Ar login_name
64.Op Fl m Ar mac_spec 64.Op Fl m Ar mac_spec
65.Op Fl O Ar ctl_cmd 65.Op Fl O Ar ctl_cmd
@@ -69,6 +69,7 @@
69.Ek 69.Ek
70.Oo Fl R Xo 70.Oo Fl R Xo
71.Sm off 71.Sm off
72.Oo Ar bind_address : Oc
72.Ar port : 73.Ar port :
73.Ar host : 74.Ar host :
74.Ar hostport 75.Ar hostport
@@ -570,6 +571,7 @@ configuration files).
570Disables forwarding (delegation) of GSSAPI credentials to the server. 571Disables forwarding (delegation) of GSSAPI credentials to the server.
571.It Fl L Xo 572.It Fl L Xo
572.Sm off 573.Sm off
574.Oo Ar bind_address : Oc
573.Ar port : host : hostport 575.Ar port : host : hostport
574.Sm on 576.Sm on
575.Xc 577.Xc
@@ -577,7 +579,9 @@ Specifies that the given port on the local (client) host is to be
577forwarded to the given host and port on the remote side. 579forwarded to the given host and port on the remote side.
578This works by allocating a socket to listen to 580This works by allocating a socket to listen to
579.Ar port 581.Ar port
580on the local side, and whenever a connection is made to this port, the 582on the local side, optionally bound to the specified
583.Ar bind_address .
584Whenever a connection is made to this port, the
581connection is forwarded over the secure channel, and a connection is 585connection is forwarded over the secure channel, and a connection is
582made to 586made to
583.Ar host 587.Ar host
@@ -585,14 +589,30 @@ port
585.Ar hostport 589.Ar hostport
586from the remote machine. 590from the remote machine.
587Port forwardings can also be specified in the configuration file. 591Port forwardings can also be specified in the configuration file.
588Only root can forward privileged ports.
589IPv6 addresses can be specified with an alternative syntax: 592IPv6 addresses can be specified with an alternative syntax:
590.Sm off 593.Sm off
591.Xo 594.Xo
595.Oo Ar bind_address / Oc
592.Ar port No / Ar host No / 596.Ar port No / Ar host No /
593.Ar hostport . 597.Ar hostport
594.Xc 598.Xc
595.Sm on 599.Sm on
600or by enclosing the address in square brackets.
601Only the superuser can forward privileged ports.
602By default, the local port is bound in accordance with the
603.Cm GatewayPorts
604setting.
605However, an explicit
606.Ar bind_address
607may be used to bind the connection to a specific address.
608The
609.Ar bind_address
610of
611.Dq localhost
612indicates that the listening port be bound for local use only, while an
613empty address or
614.Dq *
615indicates that the port should be available from all interfaces.
596.It Fl l Ar login_name 616.It Fl l Ar login_name
597Specifies the user to log in as on the remote machine. 617Specifies the user to log in as on the remote machine.
598This also may be specified on a per-host basis in the configuration file. 618This also may be specified on a per-host basis in the configuration file.
@@ -724,6 +744,7 @@ Quiet mode.
724Causes all warning and diagnostic messages to be suppressed. 744Causes all warning and diagnostic messages to be suppressed.
725.It Fl R Xo 745.It Fl R Xo
726.Sm off 746.Sm off
747.Oo Ar bind_address : Oc
727.Ar port : host : hostport 748.Ar port : host : hostport
728.Sm on 749.Sm on
729.Xc 750.Xc
@@ -738,16 +759,34 @@ made to
738port 759port
739.Ar hostport 760.Ar hostport
740from the local machine. 761from the local machine.
762.Pp
741Port forwardings can also be specified in the configuration file. 763Port forwardings can also be specified in the configuration file.
742Privileged ports can be forwarded only when 764Privileged ports can be forwarded only when
743logging in as root on the remote machine. 765logging in as root on the remote machine.
744IPv6 addresses can be specified with an alternative syntax: 766IPv6 addresses can be specified by enclosing the address in square braces or
745.Sm off 767using an alternative syntax:
746.Xo 768.Xo
747.Ar port No / Ar host No / 769.Sm off
748.Ar hostport . 770.Oo Ar bind_address / Oc
749.Xc 771.Ar host/port/hostport
750.Sm on 772.Sm on
773.Xc .
774.Pp
775By default, the listening socket on the server will be bound to the loopback
776interface only.
777This may be overriden by specifying a
778.Ar bind_address .
779An empty
780.Ar bind_address ,
781or the address
782.Ql *
783indicates that the remote socket should listen on all interfaces.
784Specifying a remote
785.Ar bind_address
786will only succeed if the server's
787.Cm GatewayPorts
788option is enabled (see
789.Xr sshd_config 5 ).
751.It Fl S Ar ctl_path 790.It Fl S Ar ctl_path
752Specifies the location of a control socket for connection sharing. 791Specifies the location of a control socket for connection sharing.
753Refer to the description of 792Refer to the description of
diff --git a/ssh.c b/ssh.c
index 1f50727e9..99b25afcc 100644
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: ssh.c,v 1.231 2005/02/16 09:56:44 otto Exp $"); 43RCSID("$OpenBSD: ssh.c,v 1.232 2005/03/01 10:09:52 djm Exp $");
44 44
45#include <openssl/evp.h> 45#include <openssl/evp.h>
46#include <openssl/err.h> 46#include <openssl/err.h>
@@ -158,9 +158,10 @@ usage(void)
158{ 158{
159 fprintf(stderr, 159 fprintf(stderr,
160"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" 160"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
161" [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n" 161" [-D [listen-host:]port] [-e escape_char] [-F configfile]\n"
162" [-L port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd]\n" 162" [-i identity_file] [-L [listen-host:]port:host:hostport]\n"
163" [-o option] [-p port] [-R port:host:hostport] [-S ctl_path]\n" 163" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
164" [-R [listen-host:]port:host:hostport] [-S ctl_path]\n"
164" [user@]hostname [command]\n" 165" [user@]hostname [command]\n"
165 ); 166 );
166 exit(1); 167 exit(1);
@@ -178,14 +179,13 @@ int
178main(int ac, char **av) 179main(int ac, char **av)
179{ 180{
180 int i, opt, exit_status; 181 int i, opt, exit_status;
181 u_short fwd_port, fwd_host_port;
182 char sfwd_port[6], sfwd_host_port[6];
183 char *p, *cp, *line, buf[256]; 182 char *p, *cp, *line, buf[256];
184 struct stat st; 183 struct stat st;
185 struct passwd *pw; 184 struct passwd *pw;
186 int dummy; 185 int dummy;
187 extern int optind, optreset; 186 extern int optind, optreset;
188 extern char *optarg; 187 extern char *optarg;
188 Forward fwd;
189 189
190 __progname = ssh_get_progname(av[0]); 190 __progname = ssh_get_progname(av[0]);
191 init_rng(); 191 init_rng();
@@ -401,39 +401,51 @@ again:
401 break; 401 break;
402 402
403 case 'L': 403 case 'L':
404 case 'R': 404 if (parse_forward(&fwd, optarg))
405 if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]", 405 add_local_forward(&options, &fwd);
406 sfwd_port, buf, sfwd_host_port) != 3 && 406 else {
407 sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
408 sfwd_port, buf, sfwd_host_port) != 3) {
409 fprintf(stderr, 407 fprintf(stderr,
410 "Bad forwarding specification '%s'\n", 408 "Bad local forwarding specification '%s'\n",
411 optarg); 409 optarg);
412 usage(); 410 exit(1);
413 /* NOTREACHED */
414 } 411 }
415 if ((fwd_port = a2port(sfwd_port)) == 0 || 412 break;
416 (fwd_host_port = a2port(sfwd_host_port)) == 0) { 413
414 case 'R':
415 if (parse_forward(&fwd, optarg)) {
416 add_remote_forward(&options, &fwd);
417 } else {
417 fprintf(stderr, 418 fprintf(stderr,
418 "Bad forwarding port(s) '%s'\n", optarg); 419 "Bad remote forwarding specification "
420 "'%s'\n", optarg);
419 exit(1); 421 exit(1);
420 } 422 }
421 if (opt == 'L')
422 add_local_forward(&options, fwd_port, buf,
423 fwd_host_port);
424 else if (opt == 'R')
425 add_remote_forward(&options, fwd_port, buf,
426 fwd_host_port);
427 break; 423 break;
428 424
429 case 'D': 425 case 'D':
430 fwd_port = a2port(optarg); 426 cp = p = xstrdup(optarg);
431 if (fwd_port == 0) { 427 memset(&fwd, '\0', sizeof(fwd));
428 fwd.connect_host = "socks";
429 if ((fwd.listen_host = hpdelim(&cp)) == NULL) {
430 fprintf(stderr, "Bad dynamic forwarding "
431 "specification '%.100s'\n", optarg);
432 exit(1);
433 }
434 if (cp != NULL) {
435 fwd.listen_port = a2port(cp);
436 fwd.listen_host = cleanhostname(fwd.listen_host);
437 } else {
438 fwd.listen_port = a2port(fwd.listen_host);
439 fwd.listen_host = "";
440 }
441
442 if (fwd.listen_port == 0) {
432 fprintf(stderr, "Bad dynamic port '%s'\n", 443 fprintf(stderr, "Bad dynamic port '%s'\n",
433 optarg); 444 optarg);
434 exit(1); 445 exit(1);
435 } 446 }
436 add_local_forward(&options, fwd_port, "socks", 0); 447 add_local_forward(&options, &fwd);
448 xfree(p);
437 break; 449 break;
438 450
439 case 'C': 451 case 'C':
@@ -842,14 +854,19 @@ ssh_init_forwarding(void)
842 854
843 /* Initiate local TCP/IP port forwardings. */ 855 /* Initiate local TCP/IP port forwardings. */
844 for (i = 0; i < options.num_local_forwards; i++) { 856 for (i = 0; i < options.num_local_forwards; i++) {
845 debug("Connections to local port %d forwarded to remote address %.200s:%d", 857 debug("Local connections to %.200s:%d forwarded to remote "
846 options.local_forwards[i].port, 858 "address %.200s:%d",
847 options.local_forwards[i].host, 859 (options.local_forwards[i].listen_host == NULL) ?
848 options.local_forwards[i].host_port); 860 (options.gateway_ports ? "*" : "LOCALHOST") :
861 options.local_forwards[i].listen_host,
862 options.local_forwards[i].listen_port,
863 options.local_forwards[i].connect_host,
864 options.local_forwards[i].connect_port);
849 success += channel_setup_local_fwd_listener( 865 success += channel_setup_local_fwd_listener(
850 options.local_forwards[i].port, 866 options.local_forwards[i].listen_host,
851 options.local_forwards[i].host, 867 options.local_forwards[i].listen_port,
852 options.local_forwards[i].host_port, 868 options.local_forwards[i].connect_host,
869 options.local_forwards[i].connect_port,
853 options.gateway_ports); 870 options.gateway_ports);
854 } 871 }
855 if (i > 0 && success == 0) 872 if (i > 0 && success == 0)
@@ -857,14 +874,17 @@ ssh_init_forwarding(void)
857 874
858 /* Initiate remote TCP/IP port forwardings. */ 875 /* Initiate remote TCP/IP port forwardings. */
859 for (i = 0; i < options.num_remote_forwards; i++) { 876 for (i = 0; i < options.num_remote_forwards; i++) {
860 debug("Connections to remote port %d forwarded to local address %.200s:%d", 877 debug("Remote connections from %.200s:%d forwarded to "
861 options.remote_forwards[i].port, 878 "local address %.200s:%d",
862 options.remote_forwards[i].host, 879 options.remote_forwards[i].listen_host,
863 options.remote_forwards[i].host_port); 880 options.remote_forwards[i].listen_port,
881 options.remote_forwards[i].connect_host,
882 options.remote_forwards[i].connect_port);
864 channel_request_remote_forwarding( 883 channel_request_remote_forwarding(
865 options.remote_forwards[i].port, 884 options.remote_forwards[i].listen_host,
866 options.remote_forwards[i].host, 885 options.remote_forwards[i].listen_port,
867 options.remote_forwards[i].host_port); 886 options.remote_forwards[i].connect_host,
887 options.remote_forwards[i].connect_port);
868 } 888 }
869} 889}
870 890
@@ -1040,12 +1060,12 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1040 return; 1060 return;
1041 debug("remote forward %s for: listen %d, connect %s:%d", 1061 debug("remote forward %s for: listen %d, connect %s:%d",
1042 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1062 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1043 options.remote_forwards[i].port, 1063 options.remote_forwards[i].listen_port,
1044 options.remote_forwards[i].host, 1064 options.remote_forwards[i].connect_host,
1045 options.remote_forwards[i].host_port); 1065 options.remote_forwards[i].connect_port);
1046 if (type == SSH2_MSG_REQUEST_FAILURE) 1066 if (type == SSH2_MSG_REQUEST_FAILURE)
1047 logit("Warning: remote port forwarding failed for listen port %d", 1067 logit("Warning: remote port forwarding failed for listen "
1048 options.remote_forwards[i].port); 1068 "port %d", options.remote_forwards[i].listen_port);
1049} 1069}
1050 1070
1051static void 1071static void
diff --git a/ssh_config.5 b/ssh_config.5
index 8f6d851b4..6b6cfc5e9 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: ssh_config.5,v 1.42 2005/02/28 00:54:10 djm Exp $ 37.\" $OpenBSD: ssh_config.5,v 1.43 2005/03/01 10:09:52 djm Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSH_CONFIG 5 39.Dt SSH_CONFIG 5
40.Os 40.Os
@@ -480,12 +480,37 @@ The default is to use the server specified list.
480Specifies that a TCP/IP port on the local machine be forwarded over 480Specifies that a TCP/IP port on the local machine be forwarded over
481the secure channel to the specified host and port from the remote machine. 481the secure channel to the specified host and port from the remote machine.
482The first argument must be a port number, and the second must be 482The first argument must be a port number, and the second must be
483.Ar host:port . 483.Xo
484IPv6 addresses can be specified with an alternative syntax: 484.Sm off
485.Ar host/port . 485.Oo Ar bind_address : Oc
486Multiple forwardings may be specified, and additional 486.Ar host:port
487forwardings can be given on the command line. 487.Sm on
488.Xc .
489IPv6 addresses can be specified by enclosing addresses in square brackets or
490by using an alternative syntax:
491.Xo
492.Sm off
493.Oo Ar bind_address / Oc
494.Ar host/port
495.Sm on
496.Xc .
497Multiple forwardings may be specified, and additional forwardings can be
498given on the command line.
488Only the superuser can forward privileged ports. 499Only the superuser can forward privileged ports.
500By default, the local port is bound in accordance with the
501.Cm GatewayPorts
502setting.
503However, an explicit
504.Ar bind_address
505may be used to bind the connection to a specific address.
506The
507.Ar bind_address
508of
509.Dq localhost
510indicates that the listening port be bound for local use only, while an
511empty address or
512.Dq *
513indicates that the port should be available from all interfaces.
489.It Cm LogLevel 514.It Cm LogLevel
490Gives the verbosity level that is used when logging messages from 515Gives the verbosity level that is used when logging messages from
491.Nm ssh . 516.Nm ssh .
@@ -592,12 +617,39 @@ This option applies to protocol version 2 only.
592Specifies that a TCP/IP port on the remote machine be forwarded over 617Specifies that a TCP/IP port on the remote machine be forwarded over
593the secure channel to the specified host and port from the local machine. 618the secure channel to the specified host and port from the local machine.
594The first argument must be a port number, and the second must be 619The first argument must be a port number, and the second must be
595.Ar host:port . 620.Xo
596IPv6 addresses can be specified with an alternative syntax: 621.Sm off
597.Ar host/port . 622.Oo Ar bind_address : Oc
623.Ar host:port
624.Sm on
625.Xc .
626IPv6 addresses can be specified by enclosing any addresses in square brackets
627or by using the alternative syntax:
628.Xo
629.Sm off
630.Oo Ar bind_address / Oc
631.Ar host/port
632.Sm on
633.Xc .
598Multiple forwardings may be specified, and additional 634Multiple forwardings may be specified, and additional
599forwardings can be given on the command line. 635forwardings can be given on the command line.
600Only the superuser can forward privileged ports. 636Only the superuser can forward privileged ports.
637.Pp
638If the
639.Ar bind_address
640is not specified, the default is to only bind to loopback addresses.
641If the
642.Ar bind_address
643is
644.Ql *
645or an empty string, then the forwarding is requested to listen on all
646interfaces.
647Specifying a remote
648.Ar bind_address
649will only succeed if the server's
650.Cm GatewayPorts
651option is enabled (see
652.Xr sshd_config 5 ).
601.It Cm RhostsRSAAuthentication 653.It Cm RhostsRSAAuthentication
602Specifies whether to try rhosts based authentication with RSA host 654Specifies whether to try rhosts based authentication with RSA host
603authentication. 655authentication.
diff --git a/sshd_config.5 b/sshd_config.5
index da6d97c68..8d291e61d 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: sshd_config.5,v 1.38 2005/01/08 00:41:19 jmc Exp $ 37.\" $OpenBSD: sshd_config.5,v 1.39 2005/03/01 10:09:52 djm Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSHD_CONFIG 5 39.Dt SSHD_CONFIG 5
40.Os 40.Os
@@ -256,12 +256,15 @@ This prevents other remote hosts from connecting to forwarded ports.
256.Cm GatewayPorts 256.Cm GatewayPorts
257can be used to specify that 257can be used to specify that
258.Nm sshd 258.Nm sshd
259should bind remote port forwardings to the wildcard address, 259should allow remote port forwardings to bind to non-loopback addresses, thus
260thus allowing remote hosts to connect to forwarded ports. 260allowing other hosts to connect.
261The argument must be 261The argument may be
262.Dq no
263to force remote port forwardings to be available to the local host only,
262.Dq yes 264.Dq yes
263or 265to force remote port forwardings to bind to the wildcard address, or
264.Dq no . 266.Dq clientspecified
267to allow the client to select the address to which the forwarding is bound.
265The default is 268The default is
266.Dq no . 269.Dq no .
267.It Cm GSSAPIAuthentication 270.It Cm GSSAPIAuthentication