Bugzilla – Attachment 834 Details for
Bug 413
Port forwarding: [localhost:]localport:remotehost:remoteport
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Revised patch
4forward-20050222.diff (text/plain), 37.64 KB, created by
Damien Miller
on 2005-02-22 10:45:46 AEDT
(
hide
)
Description:
Revised patch
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2005-02-22 10:45:46 AEDT
Size:
37.64 KB
patch
obsolete
>Index: auth-options.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/auth-options.c,v >retrieving revision 1.28 >diff -u -p -r1.28 auth-options.c >--- auth-options.c 2 Jun 2003 09:17:34 -0000 1.28 >+++ auth-options.c 21 Feb 2005 23:44:49 -0000 >@@ -217,7 +217,7 @@ auth_parse_options(struct passwd *pw, ch > } > cp = "permitopen=\""; > if (strncasecmp(opts, cp, strlen(cp)) == 0) { >- char host[256], sport[6]; >+ char *host, *p; > u_short port; > char *patterns = xmalloc(strlen(opts) + 1); > >@@ -236,25 +236,29 @@ auth_parse_options(struct passwd *pw, ch > if (!*opts) { > debug("%.100s, line %lu: missing end quote", > file, linenum); >- auth_debug_add("%.100s, line %lu: missing end quote", >- file, linenum); >+ auth_debug_add("%.100s, line %lu: missing " >+ "end quote", file, linenum); > xfree(patterns); > goto bad_option; > } > patterns[i] = 0; > opts++; >- if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && >- sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { >- debug("%.100s, line %lu: Bad permitopen specification " >- "<%.100s>", file, linenum, patterns); >+ p = patterns; >+ host = hpdelim(&p); >+ if (host == NULL || strlen(host) >= NI_MAXHOST) { >+ debug("%.100s, line %lu: Bad permitopen " >+ "specification <%.100s>", file, linenum, >+ patterns); > auth_debug_add("%.100s, line %lu: " >- "Bad permitopen specification", file, linenum); >+ "Bad permitopen specification", file, >+ linenum); > xfree(patterns); > goto bad_option; > } >- if ((port = a2port(sport)) == 0) { >- debug("%.100s, line %lu: Bad permitopen port <%.100s>", >- file, linenum, sport); >+ host = cleanhostname(host); >+ if (p == NULL || (port = a2port(p)) == 0) { >+ debug("%.100s, line %lu: Bad permitopen port " >+ "<%.100s>", file, linenum, p ? p : ""); > auth_debug_add("%.100s, line %lu: " > "Bad permitopen port", file, linenum); > xfree(patterns); >Index: channels.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/channels.c,v >retrieving revision 1.211 >diff -u -p -r1.211 channels.c >--- channels.c 29 Oct 2004 21:47:15 -0000 1.211 >+++ channels.c 21 Feb 2005 23:44:49 -0000 >@@ -2173,12 +2173,11 @@ channel_setup_fwd_listener(int type, con > const char *host_to_connect, u_short port_to_connect, int gateway_ports) > { > Channel *c; >- int success, sock, on = 1; >+ int sock, r, success = 0, on = 1, wildcard = 0; > struct addrinfo hints, *ai, *aitop; >- const char *host; >+ const char *host, *addr; > char ntop[NI_MAXHOST], strport[NI_MAXSERV]; > >- success = 0; > host = (type == SSH_CHANNEL_RPORT_LISTENER) ? > listen_addr : host_to_connect; > >@@ -2192,16 +2191,55 @@ channel_setup_fwd_listener(int type, con > } > > /* >+ * Determine whether or not a port forward listens to loopback, >+ * specified address or wildcard. These cases are only considered >+ * if gateway_ports is activated. >+ * >+ * Special-case listen_addrs are: >+ * >+ * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR >+ * "" (empty string), "*" -> wildcard v4/v6 >+ * "localhost" -> loopback v4/v6 >+ */ >+ addr = NULL; >+ if (listen_addr == NULL) { >+ /* No address specified: default to gateway_ports setting */ >+ if (gateway_ports) >+ wildcard = 1; >+ } else if (gateway_ports || type == SSH_CHANNEL_PORT_LISTENER) { >+ if (((datafellows & SSH_OLD_FORWARD_ADDR) && >+ strcmp(listen_addr, "0.0.0.0") == 0) || >+ *listen_addr == '\0' || strcmp(listen_addr, "*") == 0) >+ wildcard = 1; >+ else if (strcmp(listen_addr, "localhost") != 0) >+ addr = listen_addr; >+ } >+ >+ debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", >+ type, wildcard, (addr == NULL) ? "NULL" : addr); >+ >+ /* > * getaddrinfo returns a loopback address if the hostname is > * set to NULL and hints.ai_flags is not AI_PASSIVE > */ > memset(&hints, 0, sizeof(hints)); > hints.ai_family = IPv4or6; >- hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; >+ hints.ai_flags = wildcard ? AI_PASSIVE : 0; > hints.ai_socktype = SOCK_STREAM; > snprintf(strport, sizeof strport, "%d", listen_port); >- if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) >- packet_disconnect("getaddrinfo: fatal error"); >+ if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { >+ if (addr == NULL) { >+ /* This really shouldn't happen */ >+ packet_disconnect("getaddrinfo: fatal error: %s", >+ gai_strerror(r)); >+ } else { >+ verbose("channel_setup_fwd_listener: " >+ "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); >+ packet_send_debug("channel_setup_fwd_listener: " >+ "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); >+ } >+ aitop = NULL; >+ } > > for (ai = aitop; ai; ai = ai->ai_next) { > if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) >@@ -2280,11 +2318,12 @@ channel_cancel_rport_listener(const char > > /* protocol local port fwd, used by ssh (and sshd in v1) */ > int >-channel_setup_local_fwd_listener(u_short listen_port, >+channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, > const char *host_to_connect, u_short port_to_connect, int gateway_ports) > { > return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, >- NULL, listen_port, host_to_connect, port_to_connect, gateway_ports); >+ listen_host, listen_port, host_to_connect, port_to_connect, >+ gateway_ports); > } > > /* protocol v2 remote port fwd, used by sshd */ >@@ -2302,7 +2341,7 @@ channel_setup_remote_fwd_listener(const > */ > > void >-channel_request_remote_forwarding(u_short listen_port, >+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; >@@ -2313,7 +2352,14 @@ channel_request_remote_forwarding(u_shor > > /* Send the forward request to the remote side. */ > if (compat20) { >- const char *address_to_bind = "0.0.0.0"; >+ const char *address_to_bind; >+ if (listen_host == NULL) >+ address_to_bind = "localhost"; >+ else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) >+ address_to_bind = ""; >+ else >+ address_to_bind = listen_host; >+ > packet_start(SSH2_MSG_GLOBAL_REQUEST); > packet_put_cstring("tcpip-forward"); > packet_put_char(1); /* boolean: want reply */ >@@ -2359,10 +2405,9 @@ channel_request_remote_forwarding(u_shor > * local side. > */ > void >-channel_request_rforward_cancel(u_short port) >+channel_request_rforward_cancel(const char *host, u_short port) > { > int i; >- const char *address_to_bind = "0.0.0.0"; > > if (!compat20) > return; >@@ -2379,7 +2424,7 @@ channel_request_rforward_cancel(u_short > packet_start(SSH2_MSG_GLOBAL_REQUEST); > packet_put_cstring("cancel-tcpip-forward"); > packet_put_char(0); >- packet_put_cstring(address_to_bind); >+ packet_put_cstring(host == NULL ? "" : host); > packet_put_int(port); > packet_send(); > >@@ -2418,7 +2463,8 @@ channel_input_port_forward_request(int i > packet_disconnect("Dynamic forwarding denied."); > > /* Initiate forwarding */ >- channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports); >+ channel_setup_local_fwd_listener(NULL, port, hostname, >+ host_port, gateway_ports); > > /* Free the argument string. */ > xfree(hostname); >Index: channels.h >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/channels.h,v >retrieving revision 1.75 >diff -u -p -r1.75 channels.h >--- channels.h 29 Oct 2004 21:47:15 -0000 1.75 >+++ channels.h 21 Feb 2005 23:44:49 -0000 >@@ -202,9 +202,11 @@ void channel_clear_permitted_opens(void > void channel_input_port_forward_request(int, int); > int channel_connect_to(const char *, u_short); > int channel_connect_by_listen_address(u_short); >-void channel_request_remote_forwarding(u_short, const char *, u_short); >-void channel_request_rforward_cancel(u_short port); >-int channel_setup_local_fwd_listener(u_short, const char *, u_short, int); >+void channel_request_remote_forwarding(const char *, u_short, >+ const char *, u_short); >+int channel_setup_local_fwd_listener(const char *, u_short, >+ const char *, u_short, int); >+void channel_request_rforward_cancel(const char *host, u_short port); > int channel_setup_remote_fwd_listener(const char *, u_short, int); > int channel_cancel_rport_listener(const char *, u_short); > >Index: clientloop.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/clientloop.c,v >retrieving revision 1.134 >diff -u -p -r1.134 clientloop.c >--- clientloop.c 7 Nov 2004 00:01:46 -0000 1.134 >+++ clientloop.c 21 Feb 2005 23:44:49 -0000 >@@ -763,11 +763,11 @@ static void > process_cmdline(void) > { > void (*handler)(int); >- char *s, *cmd; >- u_short fwd_port, fwd_host_port; >- char buf[1024], sfwd_port[6], sfwd_host_port[6]; >+ char *s, *cmd, *cancel_host; > int delete = 0; > int local = 0; >+ u_short cancel_port; >+ Forward fwd; > > leave_raw_mode(); > handler = signal(SIGINT, SIG_IGN); >@@ -813,37 +813,38 @@ process_cmdline(void) > s++; > > if (delete) { >- if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) { >- logit("Bad forwarding specification."); >- goto out; >+ cancel_port = 0; >+ cancel_host = hpdelim(&s); /* may be NULL */ >+ if (s != NULL) { >+ cancel_port = a2port(s); >+ cancel_host = cleanhostname(cancel_host); >+ } else { >+ cancel_port = a2port(cancel_host); >+ cancel_host = NULL; > } >- if ((fwd_host_port = a2port(sfwd_host_port)) == 0) { >- logit("Bad forwarding port(s)."); >+ if (cancel_port == 0) { >+ logit("Bad forwarding close port"); > goto out; > } >- channel_request_rforward_cancel(fwd_host_port); >+ channel_request_rforward_cancel(cancel_host, cancel_port); > } else { >- if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", >- sfwd_port, buf, sfwd_host_port) != 3 && >- sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", >- sfwd_port, buf, sfwd_host_port) != 3) { >+ if (!parse_forward(&fwd, s)) { > logit("Bad forwarding specification."); > goto out; > } >- if ((fwd_port = a2port(sfwd_port)) == 0 || >- (fwd_host_port = a2port(sfwd_host_port)) == 0) { >- logit("Bad forwarding port(s)."); >- goto out; >- } > if (local) { >- if (channel_setup_local_fwd_listener(fwd_port, buf, >- fwd_host_port, options.gateway_ports) < 0) { >+ if (channel_setup_local_fwd_listener(fwd.listen_host, >+ fwd.listen_port, fwd.connect_host, >+ fwd.connect_port, options.gateway_ports) < 0) { > logit("Port forwarding failed."); > goto out; > } >- } else >- channel_request_remote_forwarding(fwd_port, buf, >- fwd_host_port); >+ } else { >+ channel_request_remote_forwarding(fwd.listen_host, >+ fwd.listen_port, fwd.connect_host, >+ fwd.connect_port); >+ } >+ > logit("Forwarding port."); > } > >Index: compat.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/compat.c,v >retrieving revision 1.70 >diff -u -p -r1.70 compat.c >--- compat.c 2 Nov 2003 11:01:03 -0000 1.70 >+++ compat.c 21 Feb 2005 23:44:49 -0000 >@@ -62,24 +62,28 @@ compat_datafellows(const char *version) > "OpenSSH_2.1*," > "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| > SSH_OLD_DHGEX|SSH_BUG_NOREKEY| >- SSH_BUG_EXTEOF}, >+ SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, > { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| > SSH_OLD_DHGEX|SSH_BUG_NOREKEY| >- SSH_BUG_EXTEOF}, >+ SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, > { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| >- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, >+ SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| >+ SSH_OLD_FORWARD_ADDR}, > { "OpenSSH_2.5.0p1*," > "OpenSSH_2.5.1p1*", > SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| >- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, >+ SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| >+ SSH_OLD_FORWARD_ADDR}, > { "OpenSSH_2.5.0*," > "OpenSSH_2.5.1*," > "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| >- SSH_BUG_EXTEOF}, >- { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, >+ SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, >+ { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| >+ SSH_OLD_FORWARD_ADDR}, > { "OpenSSH_2.*," > "OpenSSH_3.0*," >- "OpenSSH_3.1*", SSH_BUG_EXTEOF}, >+ "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, >+ { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR }, > { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, > { "OpenSSH*", 0 }, > { "*MindTerm*", 0 }, >Index: compat.h >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/compat.h,v >retrieving revision 1.38 >diff -u -p -r1.38 compat.h >--- compat.h 11 Jul 2004 17:48:47 -0000 1.38 >+++ compat.h 21 Feb 2005 23:44:49 -0000 >@@ -55,6 +55,7 @@ > #define SSH_BUG_EXTEOF 0x00200000 > #define SSH_BUG_PROBE 0x00400000 > #define SSH_BUG_FIRSTKEX 0x00800000 >+#define SSH_OLD_FORWARD_ADDR 0x01000000 > > void enable_compat13(void); > void enable_compat20(void); >Index: misc.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/misc.c,v >retrieving revision 1.27 >diff -u -p -r1.27 misc.c >--- misc.c 11 Dec 2004 01:48:56 -0000 1.27 >+++ misc.c 21 Feb 2005 23:44:49 -0000 >@@ -269,6 +269,48 @@ convtime(const char *s) > return total; > } > >+/* >+ * Search for next delimiter between hostnames/addresses and ports. >+ * Argument may be modified (for termination). >+ * Returns *cp if parsing succeeds. >+ * *cp is set to the start of the next delimiter, if one was found. >+ * If this is the last field, *cp is set to NULL. >+ */ >+char * >+hpdelim(char **cp) >+{ >+ char *s, *old; >+ >+ if (cp == NULL || *cp == NULL) >+ return NULL; >+ >+ old = s = *cp; >+ if (*s == '[') { >+ if ((s = strchr(s, ']')) == NULL) >+ return NULL; >+ else >+ s++; >+ } else if ((s = strpbrk(s, ":/")) == NULL) >+ s = *cp + strlen(*cp); /* skip to end (see first case below) */ >+ >+ switch (*s) { >+ case '\0': >+ *cp = NULL; /* no more fields*/ >+ break; >+ >+ case ':': >+ case '/': >+ *s = '\0'; /* terminate */ >+ *cp = s + 1; >+ break; >+ >+ default: >+ return NULL; >+ } >+ >+ return old; >+} >+ > char * > cleanhostname(char *host) > { >Index: misc.h >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/misc.h,v >retrieving revision 1.20 >diff -u -p -r1.20 misc.h >--- misc.h 11 Dec 2004 01:48:56 -0000 1.20 >+++ misc.h 21 Feb 2005 23:44:49 -0000 >@@ -20,6 +20,7 @@ int set_nonblock(int); > int unset_nonblock(int); > void set_nodelay(int); > int a2port(const char *); >+char *hpdelim(char **); > char *cleanhostname(char *); > char *colon(char *); > long convtime(const char *); >Index: readconf.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/readconf.c,v >retrieving revision 1.134 >diff -u -p -r1.134 readconf.c >--- readconf.c 11 Jul 2004 17:48:47 -0000 1.134 >+++ readconf.c 21 Feb 2005 23:44:50 -0000 >@@ -206,19 +206,21 @@ static struct { > */ > > void >-add_local_forward(Options *options, u_short port, const char *host, >- u_short host_port) >+add_local_forward(Options *options, const Forward *newfwd) > { > Forward *fwd; > extern uid_t original_real_uid; >- if (port < IPPORT_RESERVED && original_real_uid != 0) >+ if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) > fatal("Privileged ports can only be forwarded by root."); > if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) > fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); > fwd = &options->local_forwards[options->num_local_forwards++]; >- fwd->port = port; >- fwd->host = xstrdup(host); >- fwd->host_port = host_port; >+ >+ fwd->listen_host = (newfwd->listen_host == NULL) ? >+ NULL : xstrdup(newfwd->listen_host); >+ fwd->listen_port = newfwd->listen_port; >+ fwd->connect_host = xstrdup(newfwd->connect_host); >+ fwd->connect_port = newfwd->connect_port; > } > > /* >@@ -227,17 +229,19 @@ add_local_forward(Options *options, u_sh > */ > > void >-add_remote_forward(Options *options, u_short port, const char *host, >- u_short host_port) >+add_remote_forward(Options *options, const Forward *newfwd) > { > Forward *fwd; > if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) > fatal("Too many remote forwards (max %d).", > SSH_MAX_FORWARDS_PER_DIRECTION); > fwd = &options->remote_forwards[options->num_remote_forwards++]; >- fwd->port = port; >- fwd->host = xstrdup(host); >- fwd->host_port = host_port; >+ >+ fwd->listen_host = (newfwd->listen_host == NULL) ? >+ NULL : xstrdup(newfwd->listen_host); >+ fwd->listen_port = newfwd->listen_port; >+ fwd->connect_host = xstrdup(newfwd->connect_host); >+ fwd->connect_port = newfwd->connect_port; > } > > static void >@@ -245,11 +249,15 @@ clear_forwardings(Options *options) > { > int i; > >- for (i = 0; i < options->num_local_forwards; i++) >- xfree(options->local_forwards[i].host); >+ for (i = 0; i < options->num_local_forwards; i++) { >+ xfree(options->local_forwards[i].listen_host); >+ xfree(options->local_forwards[i].connect_host); >+ } > options->num_local_forwards = 0; >- for (i = 0; i < options->num_remote_forwards; i++) >- xfree(options->remote_forwards[i].host); >+ for (i = 0; i < options->num_remote_forwards; i++) { >+ xfree(options->remote_forwards[i].listen_host); >+ xfree(options->remote_forwards[i].connect_host); >+ } > options->num_remote_forwards = 0; > } > >@@ -282,11 +290,10 @@ process_config_line(Options *options, co > char *line, const char *filename, int linenum, > int *activep) > { >- char buf[256], *s, **charptr, *endofnumber, *keyword, *arg; >+ char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; > int opcode, *intptr, value; > size_t len; >- u_short fwd_port, fwd_host_port; >- char sfwd_host_port[6]; >+ Forward fwd; > > /* Strip trailing whitespace */ > for(len = strlen(line) - 1; len > 0; len--) { >@@ -643,30 +650,26 @@ parse_int: > case oLocalForward: > case oRemoteForward: > arg = strdelim(&s); >- if (!arg || *arg == '\0') >+ if (arg == NULL || *arg == '\0') > fatal("%.200s line %d: Missing port argument.", > filename, linenum); >- if ((fwd_port = a2port(arg)) == 0) >- fatal("%.200s line %d: Bad listen port.", >+ arg2 = strdelim(&s); >+ if (arg2 == NULL || *arg2 == '\0') >+ fatal("%.200s line %d: Missing target argument.", > filename, linenum); >- arg = strdelim(&s); >- if (!arg || *arg == '\0') >- fatal("%.200s line %d: Missing second argument.", >- filename, linenum); >- if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && >- sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) >+ >+ /* construct a string for parse_forward */ >+ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); >+ >+ if (parse_forward(&fwd, fwdarg) == 0) > fatal("%.200s line %d: Bad forwarding specification.", > filename, linenum); >- if ((fwd_host_port = a2port(sfwd_host_port)) == 0) >- fatal("%.200s line %d: Bad forwarding port.", >- filename, linenum); >+ > if (*activep) { > if (opcode == oLocalForward) >- add_local_forward(options, fwd_port, buf, >- fwd_host_port); >+ add_local_forward(options, &fwd); > else if (opcode == oRemoteForward) >- add_remote_forward(options, fwd_port, buf, >- fwd_host_port); >+ add_remote_forward(options, &fwd); > } > break; > >@@ -675,12 +678,25 @@ parse_int: > if (!arg || *arg == '\0') > fatal("%.200s line %d: Missing port argument.", > filename, linenum); >- fwd_port = a2port(arg); >- if (fwd_port == 0) >+ memset(&fwd, '\0', sizeof(fwd)); >+ fwd.connect_host = "socks"; >+ fwd.listen_host = hpdelim(&arg); >+ if (fwd.listen_host == NULL || >+ strlen(fwd.listen_host) >= NI_MAXHOST) >+ fatal("%.200s line %d: Bad forwarding specification.", >+ filename, linenum); >+ if (arg) { >+ fwd.listen_port = a2port(arg); >+ fwd.listen_host = cleanhostname(fwd.listen_host); >+ } else { >+ fwd.listen_port = a2port(fwd.listen_host); >+ fwd.listen_host = ""; >+ } >+ if (fwd.listen_port == 0) > fatal("%.200s line %d: Badly formatted port number.", > filename, linenum); > if (*activep) >- add_local_forward(options, fwd_port, "socks", 0); >+ add_local_forward(options, &fwd); > break; > > case oClearAllForwardings: >@@ -1042,4 +1058,69 @@ fill_default_options(Options * options) > /* options->hostname will be set in the main program if appropriate */ > /* options->host_key_alias should not be set by default */ > /* options->preferred_authentications will be set in ssh */ >+} >+ >+/* >+ * parse_forward >+ * parses a string containing a port forwarding specification of the form: >+ * [listenhost:]listenport:connecthost:connectport >+ * returns number of arguments parsed or zero on error >+ */ >+int >+parse_forward(Forward *fwd, const char *fwdspec) >+{ >+ int i; >+ char *p, *cp, *fwdarg[4]; >+ >+ memset(fwd, '\0', sizeof(*fwd)); >+ >+ cp = p = xstrdup(fwdspec); >+ >+ /* skip leading spaces */ >+ while (*cp && isspace(*cp)) >+ cp++; >+ >+ for (i = 0; i < 4; ++i) >+ if ((fwdarg[i] = hpdelim(&cp)) == NULL) >+ break; >+ >+ /* Check for trailing garbage in 4-arg case*/ >+ if (cp != NULL) >+ i = 0; /* failure */ >+ >+ switch (i) { >+ case 3: >+ fwd->listen_host = NULL; >+ fwd->listen_port = a2port(fwdarg[0]); >+ fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); >+ fwd->connect_port = a2port(fwdarg[2]); >+ break; >+ >+ case 4: >+ fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); >+ fwd->listen_port = a2port(fwdarg[1]); >+ fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); >+ fwd->connect_port = a2port(fwdarg[3]); >+ break; >+ default: >+ i = 0; /* failure */ >+ } >+ >+ xfree(p); >+ >+ if (fwd->listen_port == 0 && fwd->connect_port == 0) >+ goto fail_free; >+ >+ if (fwd->connect_host != NULL && >+ strlen(fwd->connect_host) >= NI_MAXHOST) >+ goto fail_free; >+ >+ return (i); >+ >+ fail_free: >+ if (fwd->connect_host != NULL) >+ xfree(fwd->connect_host); >+ if (fwd->listen_host != NULL) >+ xfree(fwd->listen_host); >+ return (0); > } >Index: readconf.h >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/readconf.h,v >retrieving revision 1.64 >diff -u -p -r1.64 readconf.h >--- readconf.h 11 Jul 2004 17:48:47 -0000 1.64 >+++ readconf.h 21 Feb 2005 23:44:50 -0000 >@@ -21,9 +21,10 @@ > /* Data structure for representing a forwarding request. */ > > typedef struct { >- u_short port; /* Port to forward. */ >- char *host; /* Host to connect. */ >- u_short host_port; /* Port to connect on host. */ >+ char *listen_host; /* Host (address) to listen on. */ >+ u_short listen_port; /* Port to forward. */ >+ char *connect_host; /* Host to connect. */ >+ u_short connect_port; /* Port to connect on connect_host. */ > } Forward; > /* Data structure for representing option data. */ > >@@ -117,11 +118,12 @@ typedef struct { > void initialize_options(Options *); > void fill_default_options(Options *); > int read_config_file(const char *, const char *, Options *, int); >+int parse_forward(Forward *, const char *); > > int > process_config_line(Options *, const char *, char *, const char *, int, int *); > >-void add_local_forward(Options *, u_short, const char *, u_short); >-void add_remote_forward(Options *, u_short, const char *, u_short); >+void add_local_forward(Options *, const Forward *); >+void add_remote_forward(Options *, const Forward *); > > #endif /* READCONF_H */ >Index: servconf.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/servconf.c,v >retrieving revision 1.138 >diff -u -p -r1.138 servconf.c >--- servconf.c 23 Dec 2004 23:11:00 -0000 1.138 >+++ servconf.c 21 Feb 2005 23:44:50 -0000 >@@ -405,6 +405,7 @@ process_server_config_line(ServerOptions > char *cp, **charptr, *arg, *p; > int *intptr, value, i, n; > ServerOpCodes opcode; >+ u_short port; > > cp = line; > arg = strdelim(&cp); >@@ -471,39 +472,21 @@ parse_time: > > case sListenAddress: > arg = strdelim(&cp); >- if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) >- fatal("%s line %d: missing inet addr.", >- filename, linenum); >- if (*arg == '[') { >- if ((p = strchr(arg, ']')) == NULL) >- fatal("%s line %d: bad ipv6 inet addr usage.", >- filename, linenum); >- arg++; >- memmove(p, p+1, strlen(p+1)+1); >- } else if (((p = strchr(arg, ':')) == NULL) || >- (strchr(p+1, ':') != NULL)) { >- add_listen_addr(options, arg, 0); >- break; >- } >- if (*p == ':') { >- u_short port; >- >- p++; >- if (*p == '\0') >- fatal("%s line %d: bad inet addr:port usage.", >- filename, linenum); >- else { >- *(p-1) = '\0'; >- if ((port = a2port(p)) == 0) >- fatal("%s line %d: bad port number.", >- filename, linenum); >- add_listen_addr(options, arg, port); >- } >- } else if (*p == '\0') >- add_listen_addr(options, arg, 0); >- else >- fatal("%s line %d: bad inet addr usage.", >+ if (arg == NULL || *arg == '\0') >+ fatal("%s line %d: missing address", > filename, linenum); >+ p = hpdelim(&arg); >+ if (p == NULL) >+ fatal("%s line %d: bad address:port usage", >+ filename, linenum); >+ p = cleanhostname(p); >+ if (arg == NULL) >+ port = 0; >+ else if ((port = a2port(arg)) == 0) >+ fatal("%s line %d: bad port number", filename, linenum); >+ >+ add_listen_addr(options, p, port); >+ > break; > > case sAddressFamily: >Index: ssh.1 >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/ssh.1,v >retrieving revision 1.199 >diff -u -p -r1.199 ssh.1 >--- ssh.1 7 Nov 2004 17:42:36 -0000 1.199 >+++ ssh.1 21 Feb 2005 23:44:50 -0000 >@@ -53,13 +53,13 @@ > .Op Fl i Ar identity_file > .Oo Fl L Xo > .Sm off >+.Oo Ar bind_address : Oc > .Ar port : > .Ar host : > .Ar hostport > .Sm on > .Xc > .Oc >-.Ek > .Op Fl l Ar login_name > .Op Fl m Ar mac_spec > .Op Fl O Ar ctl_cmd >@@ -69,6 +69,7 @@ > .Ek > .Oo Fl R Xo > .Sm off >+.Oo Ar bind_address : Oc > .Ar port : > .Ar host : > .Ar hostport >@@ -570,6 +571,7 @@ configuration files). > Disables forwarding (delegation) of GSSAPI credentials to the server. > .It Fl L Xo > .Sm off >+.Oo Ar bind_address : Oc > .Ar port : host : hostport > .Sm on > .Xc >@@ -577,7 +579,9 @@ Specifies that the given port on the loc > forwarded to the given host and port on the remote side. > This works by allocating a socket to listen to > .Ar port >-on the local side, and whenever a connection is made to this port, the >+on the local side, optionally bound to the specified >+.Ar bind_address . >+Whenever a connection is made to this port, the > connection is forwarded over the secure channel, and a connection is > made to > .Ar host >@@ -585,14 +589,30 @@ port > .Ar hostport > from the remote machine. > Port forwardings can also be specified in the configuration file. >-Only root can forward privileged ports. > IPv6 addresses can be specified with an alternative syntax: > .Sm off > .Xo >+.Oo Ar bind_address / Oc > .Ar port No / Ar host No / >-.Ar hostport . >+.Ar hostport > .Xc > .Sm on >+or by enclosing the address in square brackets. >+Only the superuser can forward privileged ports. >+By default, the local port is bound in accordance with the >+.Cm GatewayPorts >+setting. >+However, an explicit >+.Ar bind_address >+may be used to bind the connection to a specific address. >+The >+.Ar bind_address >+of >+.Dq localhost >+indicates that the listening port be bound for local use only, while an >+empty address or >+.Dq * >+indicates that the port should be available from all interfaces. > .It Fl l Ar login_name > Specifies the user to log in as on the remote machine. > This also may be specified on a per-host basis in the configuration file. >@@ -724,6 +744,7 @@ Quiet mode. > Causes all warning and diagnostic messages to be suppressed. > .It Fl R Xo > .Sm off >+.Oo Ar bind_address : Oc > .Ar port : host : hostport > .Sm on > .Xc >@@ -738,16 +759,34 @@ made to > port > .Ar hostport > from the local machine. >+.Pp > Port forwardings can also be specified in the configuration file. > Privileged ports can be forwarded only when > logging in as root on the remote machine. >-IPv6 addresses can be specified with an alternative syntax: >-.Sm off >+IPv6 addresses can be specified by enclosing the address in square braces or >+using an alternative syntax: > .Xo >-.Ar port No / Ar host No / >-.Ar hostport . >-.Xc >+.Sm off >+.Oo Ar bind_address / Oc >+.Ar host/port/hostport > .Sm on >+.Xc . >+.Pp >+By default, the listening socket on the server will be bound to the loopback >+interface only. >+This may be overriden by specifying a >+.Ar bind_address . >+An empty >+.Ar bind_address , >+or the address >+.Ql * >+indicates that the remote socket should listen on all interfaces. >+Specifying a remote >+.Ar bind_address >+will only succeed if the server's >+.Cm GatewayPorts >+option is enabled (see >+.Xr sshd_config 5 ). > .It Fl S Ar ctl_path > Specifies the location of a control socket for connection sharing. > Refer to the description of >Index: ssh.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/ssh.c,v >retrieving revision 1.231 >diff -u -p -r1.231 ssh.c >--- ssh.c 16 Feb 2005 09:56:44 -0000 1.231 >+++ ssh.c 21 Feb 2005 23:44:50 -0000 >@@ -158,9 +158,10 @@ usage(void) > { > fprintf(stderr, > "usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" >-" [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n" >-" [-L port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd]\n" >-" [-o option] [-p port] [-R port:host:hostport] [-S ctl_path]\n" >+" [-D [listen-host:]port] [-e escape_char] [-F configfile]\n" >+" [-i identity_file] [-L [listen-host:]port:host:hostport]\n" >+" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" >+" [-R [listen-host:]port:host:hostport] [-S ctl_path]\n" > " [user@]hostname [command]\n" > ); > exit(1); >@@ -178,14 +179,13 @@ int > main(int ac, char **av) > { > int i, opt, exit_status; >- u_short fwd_port, fwd_host_port; >- char sfwd_port[6], sfwd_host_port[6]; > char *p, *cp, *line, buf[256]; > struct stat st; > struct passwd *pw; > int dummy; > extern int optind, optreset; > extern char *optarg; >+ Forward fwd; > > /* > * Save the original real uid. It will be needed later (uid-swapping >@@ -396,39 +396,51 @@ again: > break; > > case 'L': >- case 'R': >- if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]", >- sfwd_port, buf, sfwd_host_port) != 3 && >- sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]", >- sfwd_port, buf, sfwd_host_port) != 3) { >+ if (parse_forward(&fwd, optarg)) >+ add_local_forward(&options, &fwd); >+ else { > fprintf(stderr, >- "Bad forwarding specification '%s'\n", >+ "Bad local forwarding specification '%s'\n", > optarg); >- usage(); >- /* NOTREACHED */ >+ exit(1); > } >- if ((fwd_port = a2port(sfwd_port)) == 0 || >- (fwd_host_port = a2port(sfwd_host_port)) == 0) { >+ break; >+ >+ case 'R': >+ if (parse_forward(&fwd, optarg)) { >+ add_remote_forward(&options, &fwd); >+ } else { > fprintf(stderr, >- "Bad forwarding port(s) '%s'\n", optarg); >+ "Bad remote forwarding specification " >+ "'%s'\n", optarg); > exit(1); > } >- if (opt == 'L') >- add_local_forward(&options, fwd_port, buf, >- fwd_host_port); >- else if (opt == 'R') >- add_remote_forward(&options, fwd_port, buf, >- fwd_host_port); > break; > > case 'D': >- fwd_port = a2port(optarg); >- if (fwd_port == 0) { >+ cp = p = xstrdup(optarg); >+ memset(&fwd, '\0', sizeof(fwd)); >+ fwd.connect_host = "socks"; >+ if ((fwd.listen_host = hpdelim(&cp)) == NULL) { >+ fprintf(stderr, "Bad dynamic forwarding " >+ "specification '%.100s'\n", optarg); >+ exit(1); >+ } >+ if (cp != NULL) { >+ fwd.listen_port = a2port(cp); >+ fwd.listen_host = cleanhostname(fwd.listen_host); >+ } else { >+ fwd.listen_port = a2port(fwd.listen_host); >+ fwd.listen_host = ""; >+ } >+ >+ if (fwd.listen_port == 0) { > fprintf(stderr, "Bad dynamic port '%s'\n", > optarg); > exit(1); > } >- add_local_forward(&options, fwd_port, "socks", 0); >+ add_local_forward(&options, &fwd); >+ xfree(p); > break; > > case 'C': >@@ -831,14 +843,19 @@ ssh_init_forwarding(void) > > /* Initiate local TCP/IP port forwardings. */ > for (i = 0; i < options.num_local_forwards; i++) { >- debug("Connections to local port %d forwarded to remote address %.200s:%d", >- options.local_forwards[i].port, >- options.local_forwards[i].host, >- options.local_forwards[i].host_port); >+ debug("Local connections to %.200s:%d forwarded to remote " >+ "address %.200s:%d", >+ (options.local_forwards[i].listen_host == NULL) ? >+ (options.gateway_ports ? "*" : "LOCALHOST") : >+ options.local_forwards[i].listen_host, >+ options.local_forwards[i].listen_port, >+ options.local_forwards[i].connect_host, >+ options.local_forwards[i].connect_port); > success += channel_setup_local_fwd_listener( >- options.local_forwards[i].port, >- options.local_forwards[i].host, >- options.local_forwards[i].host_port, >+ options.local_forwards[i].listen_host, >+ options.local_forwards[i].listen_port, >+ options.local_forwards[i].connect_host, >+ options.local_forwards[i].connect_port, > options.gateway_ports); > } > if (i > 0 && success == 0) >@@ -846,14 +863,17 @@ ssh_init_forwarding(void) > > /* Initiate remote TCP/IP port forwardings. */ > for (i = 0; i < options.num_remote_forwards; i++) { >- debug("Connections to remote port %d forwarded to local address %.200s:%d", >- options.remote_forwards[i].port, >- options.remote_forwards[i].host, >- options.remote_forwards[i].host_port); >+ debug("Remote connections from %.200s:%d forwarded to " >+ "local address %.200s:%d", >+ options.remote_forwards[i].listen_host, >+ options.remote_forwards[i].listen_port, >+ options.remote_forwards[i].connect_host, >+ options.remote_forwards[i].connect_port); > channel_request_remote_forwarding( >- options.remote_forwards[i].port, >- options.remote_forwards[i].host, >- options.remote_forwards[i].host_port); >+ options.remote_forwards[i].listen_host, >+ options.remote_forwards[i].listen_port, >+ options.remote_forwards[i].connect_host, >+ options.remote_forwards[i].connect_port); > } > } > >@@ -1029,12 +1049,12 @@ client_global_request_reply_fwd(int type > return; > debug("remote forward %s for: listen %d, connect %s:%d", > type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", >- options.remote_forwards[i].port, >- options.remote_forwards[i].host, >- options.remote_forwards[i].host_port); >+ options.remote_forwards[i].listen_port, >+ options.remote_forwards[i].connect_host, >+ options.remote_forwards[i].connect_port); > if (type == SSH2_MSG_REQUEST_FAILURE) >- logit("Warning: remote port forwarding failed for listen port %d", >- options.remote_forwards[i].port); >+ logit("Warning: remote port forwarding failed for listen " >+ "port %d", options.remote_forwards[i].listen_port); > } > > static void >Index: ssh_config.5 >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/ssh_config.5,v >retrieving revision 1.41 >diff -u -p -r1.41 ssh_config.5 >--- ssh_config.5 28 Jan 2005 18:14:09 -0000 1.41 >+++ ssh_config.5 21 Feb 2005 23:44:50 -0000 >@@ -475,12 +475,37 @@ The default is to use the server specifi > Specifies that a TCP/IP port on the local machine be forwarded over > the secure channel to the specified host and port from the remote machine. > The first argument must be a port number, and the second must be >-.Ar host:port . >-IPv6 addresses can be specified with an alternative syntax: >-.Ar host/port . >-Multiple forwardings may be specified, and additional >-forwardings can be given on the command line. >+.Xo >+.Sm off >+.Oo Ar bind_address : Oc >+.Ar host:port >+.Sm on >+.Xc . >+IPv6 addresses can be specified by enclosing addresses in square brackets or >+by using an alternative syntax: >+.Xo >+.Sm off >+.Oo Ar bind_address / Oc >+.Ar host/port >+.Sm on >+.Xc . >+Multiple forwardings may be specified, and additional forwardings can be >+given on the command line. > Only the superuser can forward privileged ports. >+By default, the local port is bound in accordance with the >+.Cm GatewayPorts >+setting. >+However, an explicit >+.Ar bind_address >+may be used to bind the connection to a specific address. >+The >+.Ar bind_address >+of >+.Dq localhost >+indicates that the listening port be bound for local use only, while an >+empty address or >+.Dq * >+indicates that the port should be available from all interfaces. > .It Cm LogLevel > Gives the verbosity level that is used when logging messages from > .Nm ssh . >@@ -587,12 +612,39 @@ This option applies to protocol version > Specifies that a TCP/IP port on the remote machine be forwarded over > the secure channel to the specified host and port from the local machine. > The first argument must be a port number, and the second must be >-.Ar host:port . >-IPv6 addresses can be specified with an alternative syntax: >-.Ar host/port . >+.Xo >+.Sm off >+.Oo Ar bind_address : Oc >+.Ar host:port >+.Sm on >+.Xc . >+IPv6 addresses can be specified by enclosing any addresses in square brackets >+or by using the alternative syntax: >+.Xo >+.Sm off >+.Oo Ar bind_address / Oc >+.Ar host/port >+.Sm on >+.Xc . > Multiple forwardings may be specified, and additional > forwardings can be given on the command line. > Only the superuser can forward privileged ports. >+.Pp >+If the >+.Ar bind_address >+is not specified, the default is to only bind to loopback addresses. >+If the >+.Ar bind_address >+is >+.Ql * >+or an empty string, then the forwarding is requested to listen on all >+interfaces. >+Specifying a remote >+.Ar bind_address >+will only succeed if the server's >+.Cm GatewayPorts >+option is enabled (see >+.Xr sshd_config 5 ). > .It Cm RhostsRSAAuthentication > Specifies whether to try rhosts based authentication with RSA host > authentication. >Index: sshd_config.5 >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/sshd_config.5,v >retrieving revision 1.38 >diff -u -p -r1.38 sshd_config.5 >--- sshd_config.5 8 Jan 2005 00:41:19 -0000 1.38 >+++ sshd_config.5 21 Feb 2005 23:44:50 -0000 >@@ -256,8 +256,8 @@ This prevents other remote hosts from co > .Cm GatewayPorts > can be used to specify that > .Nm sshd >-should bind remote port forwardings to the wildcard address, >-thus allowing remote hosts to connect to forwarded ports. >+should allow remote port forwardings to bind to non-loopback addresses, thus >+allowing other hosts to connect. > The argument must be > .Dq yes > or
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 413
:
179
|
180
|
182
|
217
|
219
|
229
|
321
|
666
|
782
|
783
|
784
|
791
|
792
|
806
| 834