]> andersk Git - openssh.git/commitdiff
- djm@cvs.openbsd.org 2005/03/01 10:09:52
authordjm <djm>
Tue, 1 Mar 2005 10:24:33 +0000 (10:24 +0000)
committerdjm <djm>
Tue, 1 Mar 2005 10:24:33 +0000 (10:24 +0000)
     [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.

16 files changed:
ChangeLog
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

index a86dca22491897bca504980317e7eccccfba22fd..254cc15d3c7ec7ee5bca71ca34026526afc617b9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
      [ssh_config.5]
      bz#849: document timeout on untrusted x11 forwarding sessions. Reported by
      orion AT cora.nwra.com; ok markus@
+   - 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.
 
 20050226
  - (dtucker) [openbsd-compat/bsd-openpty.c openbsd-compat/inet_ntop.c]
index 0e146ab158644ed04c282b0ba74d574123919ae7..04d12d66e48cb359405a58cd04558f2681bc5729 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth-options.c,v 1.28 2003/06/02 09:17:34 markus Exp $");
+RCSID("$OpenBSD: auth-options.c,v 1.29 2005/03/01 10:09:52 djm Exp $");
 
 #include "xmalloc.h"
 #include "match.h"
@@ -217,7 +217,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                }
                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, char *opts, char *file, u_long linenum)
                        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 8550e51ca77e6088114f0d371999581b0180cdf3..1be213bce21ad2e69d08ed838ec2d2f07d3c55f4 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.211 2004/10/29 21:47:15 djm Exp $");
+RCSID("$OpenBSD: channels.c,v 1.212 2005/03/01 10:09:52 djm Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -2179,14 +2179,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
     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, is_client;
        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;
+       is_client = (type == SSH_CHANNEL_PORT_LISTENER);
 
        if (host == NULL) {
                error("No forward host name.");
@@ -2197,17 +2197,61 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                return success;
        }
 
+       /*
+        * Determine whether or not a port forward listens to loopback,
+        * specified address or wildcard. On the client, a specified bind 
+        * address will always override gateway_ports. On the server, a 
+        * gateway_ports of 1 (``yes'') will override the client's 
+        * specification and force a wildcard bind, whereas a value of 2 
+        * (``clientspecified'') will bind to whatever address the client 
+        * asked for.
+        *
+        * 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 || is_client) {
+               if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
+                   strcmp(listen_addr, "0.0.0.0") == 0) ||
+                   *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
+                   (!is_client && gateway_ports == 1))
+                       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)
@@ -2290,11 +2334,12 @@ channel_cancel_rport_listener(const char *host, u_short port)
 
 /* 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 */
@@ -2312,7 +2357,7 @@ channel_setup_remote_fwd_listener(const char *listen_address,
  */
 
 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;
@@ -2323,7 +2368,14 @@ channel_request_remote_forwarding(u_short listen_port,
 
        /* 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 */
@@ -2369,10 +2421,9 @@ channel_request_remote_forwarding(u_short listen_port,
  * 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;
@@ -2389,7 +2440,7 @@ channel_request_rforward_cancel(u_short port)
        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();
 
@@ -2430,7 +2481,8 @@ channel_input_port_forward_request(int is_root, int gateway_ports)
 #endif
 
        /* 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 c47de55c0049b00716a6cd05733427375caacf79..fc20fb2c331ebcb99998255308efdc3b932425ab 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: channels.h,v 1.75 2004/10/29 21:47:15 djm Exp $       */
+/*     $OpenBSD: channels.h,v 1.76 2005/03/01 10:09:52 djm Exp $       */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -203,9 +203,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 033a98a5b97fccfbe7479861b36ad723bddff60c..1e250883f1821a0366982953ce2d7eca9b795513 100644 (file)
@@ -59,7 +59,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.134 2004/11/07 00:01:46 djm Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -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 2fdebe7fa21dc35c925348eb565fd86d7070ada2..4086e853ed6e48bb8b5973709620261a5ebc808e 100644 (file)
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: compat.c,v 1.70 2003/11/02 11:01:03 markus Exp $");
+RCSID("$OpenBSD: compat.c,v 1.71 2005/03/01 10:09:52 djm Exp $");
 
 #include "buffer.h"
 #include "packet.h"
@@ -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 5efb5c29e395dcd0662abbc8b6bef5d2358389ab..cf92dbdeefcc04b558f6c75f4328c39985014a96 100644 (file)
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: compat.h,v 1.38 2004/07/11 17:48:47 deraadt Exp $     */
+/*     $OpenBSD: compat.h,v 1.39 2005/03/01 10:09:52 djm Exp $ */
 
 /*
  * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
@@ -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);
diff --git a/misc.c b/misc.c
index a9012550598dedf9513ca235ab3c93dc27ce868e..2e366f81b270055cd99a291cfa9795f6d59fa898 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.27 2004/12/11 01:48:56 dtucker Exp $");
+RCSID("$OpenBSD: misc.c,v 1.28 2005/03/01 10:09:52 djm Exp $");
 
 #include "misc.h"
 #include "log.h"
@@ -275,6 +275,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)
 {
diff --git a/misc.h b/misc.h
index 193216fa942a9a7da9903abc101b842cfe71a9a7..8bbc87f0dbda4086d21c403b3f4002c64c6ed48f 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: misc.h,v 1.20 2004/12/11 01:48:56 dtucker Exp $       */
+/*     $OpenBSD: misc.h,v 1.21 2005/03/01 10:09:52 djm Exp $   */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -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 a4fe1fe028c49f081135f5753399a0e8ffcd2502..c3dc71e66c9d9a560382ecb5660d19d74c7f675d 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.134 2004/07/11 17:48:47 deraadt Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
 
 #include "ssh.h"
 #include "xmalloc.h"
@@ -206,21 +206,23 @@ 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;
 #ifndef NO_IPPORT_RESERVED_CONCEPT
        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.");
 #endif
        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;
 }
 
 /*
@@ -229,17 +231,19 @@ add_local_forward(Options *options, u_short port, const char *host,
  */
 
 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
@@ -247,11 +251,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;
 }
 
@@ -284,11 +292,10 @@ process_config_line(Options *options, const char *host,
                    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--) {
@@ -645,30 +652,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;
 
@@ -677,12 +680,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:
@@ -1045,3 +1061,68 @@ fill_default_options(Options * options)
        /* 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 ded4225857bf75029d19d518d55e25388706e7d1..03b772a2d5dcf45c6f348af4eb99458ad3e4b2db 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: readconf.h,v 1.64 2004/07/11 17:48:47 deraadt Exp $   */
+/*     $OpenBSD: readconf.h,v 1.65 2005/03/01 10:09:52 djm Exp $       */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
 /* 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 541a9c85b0dfc27a8c21164cd9434b62ebd4756a..2d1a0c3627feae31cda1d208ece71f07082d8941 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.138 2004/12/23 23:11:00 djm Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.139 2005/03/01 10:09:52 djm Exp $");
 
 #include "ssh.h"
 #include "log.h"
@@ -440,6 +440,7 @@ process_server_config_line(ServerOptions *options, char *line,
        char *cp, **charptr, *arg, *p;
        int *intptr, value, i, n;
        ServerOpCodes opcode;
+       u_short port;
 
        cp = line;
        arg = strdelim(&cp);
@@ -512,39 +513,21 @@ parse_time:
 
        case sListenAddress:
                arg = strdelim(&cp);
-               if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
-                       fatal("%s line %d: missing inet addr.",
+               if (arg == NULL || *arg == '\0')
+                       fatal("%s line %d: missing address",
                            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.",
+               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:
@@ -742,7 +725,23 @@ parse_flag:
 
        case sGatewayPorts:
                intptr = &options->gateway_ports;
-               goto parse_flag;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing yes/no/clientspecified "
+                           "argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcmp(arg, "clientspecified") == 0)
+                       value = 2;
+               else if (strcmp(arg, "yes") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0)
+                       value = 0;
+               else
+                       fatal("%s line %d: Bad yes/no/clientspecified "
+                           "argument: %s", filename, linenum, arg);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
 
        case sUseDNS:
                intptr = &options->use_dns;
diff --git a/ssh.1 b/ssh.1
index b8a91a160ca68b86c84868647b0755c298884902..27da08c696a260043dc838ae0a098b449335640a 100644 (file)
--- a/ssh.1
+++ b/ssh.1
@@ -34,7 +34,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh.1,v 1.199 2004/11/07 17:42:36 jmc Exp $
+.\" $OpenBSD: ssh.1,v 1.200 2005/03/01 10:09:52 djm Exp $
 .Dd September 25, 1999
 .Dt SSH 1
 .Os
 .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 local (client) host is to be
 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
diff --git a/ssh.c b/ssh.c
index 1f50727e934a839dd192edd9043666a30a964361..99b25afcc4b54083b28ef8685e4aba4dde302e86 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.231 2005/02/16 09:56:44 otto Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.232 2005/03/01 10:09:52 djm Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -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;
 
        __progname = ssh_get_progname(av[0]);
        init_rng();
@@ -401,39 +401,51 @@ again:
                        break;
 
                case 'L':
-               case 'R':
-                       if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]",
-                           sfwd_port, buf, sfwd_host_port) != 3 &&
-                           sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
-                           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':
@@ -842,14 +854,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)
@@ -857,14 +874,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);
        }
 }
 
@@ -1040,12 +1060,12 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
                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 8f6d851b4daaa66ad559aa9b51eed8b789f68923..6b6cfc5e949d30f990765639a111eb255e01155e 100644 (file)
@@ -34,7 +34,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh_config.5,v 1.42 2005/02/28 00:54:10 djm Exp $
+.\" $OpenBSD: ssh_config.5,v 1.43 2005/03/01 10:09:52 djm Exp $
 .Dd September 25, 1999
 .Dt SSH_CONFIG 5
 .Os
@@ -480,12 +480,37 @@ The default is to use the server specified list.
 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 .
@@ -592,12 +617,39 @@ This option applies to protocol version 2 only.
 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 da6d97c685c06e4423e92fd6c86413fd066420d9..8d291e61d4410cbebbd84fb3404d9e5ce9f33daf 100644 (file)
@@ -34,7 +34,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: sshd_config.5,v 1.38 2005/01/08 00:41:19 jmc Exp $
+.\" $OpenBSD: sshd_config.5,v 1.39 2005/03/01 10:09:52 djm Exp $
 .Dd September 25, 1999
 .Dt SSHD_CONFIG 5
 .Os
@@ -256,12 +256,15 @@ This prevents other remote hosts from connecting to forwarded ports.
 .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.
-The argument must be
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
 .Dq yes
-or
-.Dq no .
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
 The default is
 .Dq no .
 .It Cm GSSAPIAuthentication
This page took 0.110302 seconds and 5 git commands to generate.