]> andersk Git - openssh.git/commitdiff
- djm@cvs.openbsd.org 2009/02/12 03:00:56
authordjm <djm>
Sat, 14 Feb 2009 05:28:21 +0000 (05:28 +0000)
committerdjm <djm>
Sat, 14 Feb 2009 05:28:21 +0000 (05:28 +0000)
     [canohost.c canohost.h channels.c channels.h clientloop.c readconf.c]
     [readconf.h serverloop.c ssh.c]
     support remote port forwarding with a zero listen port (-R0:...) to
     dyamically allocate a listen port at runtime (this is actually
     specified in rfc4254); bz#1003 ok markus@

ChangeLog
canohost.c
canohost.h
channels.c
channels.h
clientloop.c
readconf.c
readconf.h
serverloop.c
ssh.c

index daa8194f722b4d87d4a3a4ba80272cf78664daea..b1b5c644d92398aea2e9b6cd72d12e54efdd52bb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,12 @@
      [sftp.c]
      Initialize a few variables to prevent spurious "may be used
      uninitialized" warnings from newer gcc's.  ok djm@
+   - djm@cvs.openbsd.org 2009/02/12 03:00:56
+     [canohost.c canohost.h channels.c channels.h clientloop.c readconf.c]
+     [readconf.h serverloop.c ssh.c]
+     support remote port forwarding with a zero listen port (-R0:...) to
+     dyamically allocate a listen port at runtime (this is actually
+     specified in rfc4254); bz#1003 ok markus@
 
 20090212
  - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically
index 42011fd0acf2996fe09c10b077444fbfe1aae68f..7138f48d0f418b3f8d4fa0ec7a356c75ab536472 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.c,v 1.63 2008/06/12 00:03:49 dtucker Exp $ */
+/* $OpenBSD: canohost.c,v 1.64 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -342,7 +342,7 @@ get_remote_name_or_ip(u_int utmp_len, int use_dns)
 
 /* Returns the local/remote port for the socket. */
 
-static int
+int
 get_sock_port(int sock, int local)
 {
        struct sockaddr_storage from;
index e33e8941b2cb5f0959856e2b5f2070811d57d667..d9b41ffe5449c05112a0c6639d99cdfbab0e419e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.h,v 1.9 2006/03/25 22:22:42 djm Exp $ */
+/* $OpenBSD: canohost.h,v 1.10 2009/02/12 03:00:56 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -23,5 +23,7 @@ char          *get_local_name(int);
 
 int             get_remote_port(void);
 int             get_local_port(void);
+int             get_sock_port(int, int);
+
 
 void            ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
index 0b1c34c837e7ca93dc4e3daa97baffcf19237464..dea60ba24e7740d8ecac95ab6f6db89c8574155c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.294 2009/01/22 09:49:57 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.295 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2460,7 +2460,8 @@ channel_set_af(int af)
 }
 
 static int
-channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port,
+channel_setup_fwd_listener(int type, const char *listen_addr,
+    u_short listen_port, int *allocated_listen_port,
     const char *host_to_connect, u_short port_to_connect, int gateway_ports)
 {
        Channel *c;
@@ -2468,6 +2469,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
        struct addrinfo hints, *ai, *aitop;
        const char *host, *addr;
        char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+       in_port_t *lport_p;
 
        host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
            listen_addr : host_to_connect;
@@ -2536,10 +2538,29 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                }
                return 0;
        }
-
+       if (allocated_listen_port != NULL)
+               *allocated_listen_port = 0;
        for (ai = aitop; ai; ai = ai->ai_next) {
-               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+               switch (ai->ai_family) {
+               case AF_INET:
+                       lport_p = &((struct sockaddr_in *)ai->ai_addr)->
+                           sin_port;
+                       break;
+               case AF_INET6:
+                       lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
+                           sin6_port;
+                       break;
+               default:
                        continue;
+               }
+               /*
+                * If allocating a port for -R forwards, then use the
+                * same port for all address families.
+                */
+               if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
+                   allocated_listen_port != NULL && *allocated_listen_port > 0)
+                       *lport_p = htons(*allocated_listen_port);
+
                if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
                    strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                        error("channel_setup_fwd_listener: getnameinfo failed");
@@ -2555,7 +2576,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
 
                channel_set_reuseaddr(sock);
 
-               debug("Local forwarding listening on %s port %s.", ntop, strport);
+               debug("Local forwarding listening on %s port %s.",
+                   ntop, strport);
 
                /* Bind the socket to the address. */
                if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
@@ -2574,6 +2596,19 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                        close(sock);
                        continue;
                }
+
+               /*
+                * listen_port == 0 requests a dynamically allocated port -
+                * record what we got.
+                */
+               if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
+                   allocated_listen_port != NULL &&
+                   *allocated_listen_port == 0) {
+                       *allocated_listen_port = get_sock_port(sock, 1);
+                       debug("Allocated listen port %d",
+                           *allocated_listen_port);
+               }
+
                /* Allocate a channel number for the socket. */
                c = channel_new("port listener", type, sock, sock, -1,
                    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
@@ -2616,17 +2651,18 @@ 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,
-           listen_host, listen_port, host_to_connect, port_to_connect,
+           listen_host, listen_port, NULL, host_to_connect, port_to_connect,
            gateway_ports);
 }
 
 /* protocol v2 remote port fwd, used by sshd */
 int
 channel_setup_remote_fwd_listener(const char *listen_address,
-    u_short listen_port, int gateway_ports)
+    u_short listen_port, int *allocated_listen_port, int gateway_ports)
 {
        return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
-           listen_address, listen_port, NULL, 0, gateway_ports);
+           listen_address, listen_port, allocated_listen_port,
+           NULL, 0, gateway_ports);
 }
 
 /*
index 19fee769c3616c894190b83b2ef14d50e5d29ac2..1488ed7e59ab53410a766b1630c0c591d8ea721a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.97 2009/01/22 09:46:01 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.98 2009/02/12 03:00:56 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -245,7 +245,7 @@ int  channel_request_remote_forwarding(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_setup_remote_fwd_listener(const char *, u_short, int *, int);
 int     channel_cancel_rport_listener(const char *, u_short);
 
 /* x11 forwarding */
index 1b5badb7163d524a18545b8248a00246d68b3991..a2d2d1d07465d91f92858dba93fe7038605d6a46 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.208 2009/01/22 10:02:34 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.209 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -849,7 +849,7 @@ process_cmdline(void)
                }
                channel_request_rforward_cancel(cancel_host, cancel_port);
        } else {
-               if (!parse_forward(&fwd, s, dynamic ? 1 : 0)) {
+               if (!parse_forward(&fwd, s, dynamic, remote)) {
                        logit("Bad forwarding specification.");
                        goto out;
                }
index 0a8be140072d4d5cd0fa36e1ceef34730397074b..53fc6c7ba598c0fe5a0f4e0581320fca05b876e7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.175 2009/01/22 10:02:34 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -735,7 +735,8 @@ parse_int:
                }
 
                if (parse_forward(&fwd, fwdarg,
-                   opcode == oDynamicForward ? 1 : 0) == 0)
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
                        fatal("%.200s line %d: Bad forwarding specification.",
                            filename, linenum);
 
@@ -1220,7 +1221,7 @@ fill_default_options(Options * options)
  * returns number of arguments parsed or zero on error
  */
 int
-parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd)
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
 {
        int i;
        char *p, *cp, *fwdarg[4];
@@ -1283,12 +1284,16 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd)
                        goto fail_free;
        }
 
-       if (fwd->listen_port <= 0)
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
                goto fail_free;
 
        if (fwd->connect_host != NULL &&
            strlen(fwd->connect_host) >= NI_MAXHOST)
                goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
 
        return (i);
 
index d94d65890d291487460ea3c5ea5485017bc5744c..8fb3a852816305319a4a3201ab04492d1be2c820 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.77 2009/01/22 10:02:34 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.78 2009/02/12 03:00:56 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -134,7 +134,7 @@ 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);
+int     parse_forward(Forward *, const char *, int, int);
 
 int
 process_config_line(Options *, const char *, char *, const char *, int, int *);
index 931779e3034b08d83295fe86d7d53c5a0c6e4cce..6244ad71c8d6e0ad5c0f2fe76b00d17f2311b8d5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.155 2009/01/22 10:02:34 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.156 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1095,7 +1095,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
 {
        char *rtype;
        int want_reply;
-       int success = 0;
+       int success = 0, allocated_listen_port = 0;
 
        rtype = packet_get_string(NULL);
        want_reply = packet_get_char();
@@ -1119,7 +1119,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
                if (!options.allow_tcp_forwarding ||
                    no_port_forwarding_flag
 #ifndef NO_IPPORT_RESERVED_CONCEPT
-                   || (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)
+                   || (listen_port != 0 &&
+                   listen_port < IPPORT_RESERVED && pw->pw_uid != 0)
 #endif
                    ) {
                        success = 0;
@@ -1149,6 +1150,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
        if (want_reply) {
                packet_start(success ?
                    SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               if (success && allocated_listen_port > 0)
+                       packet_put_int(allocated_listen_port);
                packet_send();
                packet_write_wait();
        }
diff --git a/ssh.c b/ssh.c
index 26f070f3ead425e7382d7586f593dbc52ce4e799..9d43bb74fc3295d4988cdbb6924b172a69cd34ab 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.323 2009/01/22 10:02:34 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.324 2009/02/12 03:00:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -453,7 +453,7 @@ main(int ac, char **av)
                        break;
 
                case 'L':
-                       if (parse_forward(&fwd, optarg, 0))
+                       if (parse_forward(&fwd, optarg, 0, 0))
                                add_local_forward(&options, &fwd);
                        else {
                                fprintf(stderr,
@@ -464,7 +464,7 @@ main(int ac, char **av)
                        break;
 
                case 'R':
-                       if (parse_forward(&fwd, optarg, 0)) {
+                       if (parse_forward(&fwd, optarg, 0, 1)) {
                                add_remote_forward(&options, &fwd);
                        } else {
                                fprintf(stderr,
@@ -475,7 +475,7 @@ main(int ac, char **av)
                        break;
 
                case 'D':
-                       if (parse_forward(&fwd, optarg, 1)) {
+                       if (parse_forward(&fwd, optarg, 1, 0)) {
                                add_local_forward(&options, &fwd);
                        } else {
                                fprintf(stderr,
@@ -837,9 +837,16 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
 {
        Forward *rfwd = (Forward *)ctxt;
 
+       /* XXX verbose() on failure? */
        debug("remote forward %s for: listen %d, connect %s:%d",
            type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
            rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
+       if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) {
+               logit("Allocated port %u for remote forward to %s:%d",
+                       packet_get_int(),
+                       rfwd->connect_host, rfwd->connect_port);
+       }
+       
        if (type == SSH2_MSG_REQUEST_FAILURE) {
                if (options.exit_on_forward_failure)
                        fatal("Error: remote port forwarding failed for "
This page took 0.083392 seconds and 5 git commands to generate.