]> andersk Git - openssh.git/blobdiff - channels.c
- djm@cvs.openbsd.org 2005/03/02 01:00:06
[openssh.git] / channels.c
index cf46ce09f379ea1176c9998940418e2a0dc25f64..1be213bce21ad2e69d08ed838ec2d2f07d3c55f4 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.208 2004/07/11 17:48:47 deraadt Exp $");
+RCSID("$OpenBSD: channels.c,v 1.212 2005/03/01 10:09:52 djm Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -68,7 +68,7 @@ static Channel **channels = NULL;
  * Size of the channel array.  All slots of the array must always be
  * initialized (at least the type field); unused slots set to NULL
  */
-static int channels_alloc = 0;
+static u_int channels_alloc = 0;
 
 /*
  * Maximum file descriptor value used in any of the channels.  This is
@@ -141,7 +141,7 @@ channel_lookup(int id)
 {
        Channel *c;
 
-       if (id < 0 || id >= channels_alloc) {
+       if (id < 0 || (u_int)id >= channels_alloc) {
                logit("channel_lookup: %d: bad id", id);
                return NULL;
        }
@@ -209,7 +209,8 @@ Channel *
 channel_new(char *ctype, int type, int rfd, int wfd, int efd,
     u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
 {
-       int i, found;
+       int found;
+       u_int i;
        Channel *c;
 
        /* Do initial allocation if this is the first call. */
@@ -223,10 +224,10 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
        for (found = -1, i = 0; i < channels_alloc; i++)
                if (channels[i] == NULL) {
                        /* Found a free slot. */
-                       found = i;
+                       found = (int)i;
                        break;
                }
-       if (found == -1) {
+       if (found < 0) {
                /* There are no free slots.  Take last+1 slot and expand the array.  */
                found = channels_alloc;
                if (channels_alloc > 10000)
@@ -273,7 +274,8 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
 static int
 channel_find_maxfd(void)
 {
-       int i, max = 0;
+       u_int i;
+       int max = 0;
        Channel *c;
 
        for (i = 0; i < channels_alloc; i++) {
@@ -322,12 +324,12 @@ void
 channel_free(Channel *c)
 {
        char *s;
-       int i, n;
+       u_int i, n;
 
        for (n = 0, i = 0; i < channels_alloc; i++)
                if (channels[i])
                        n++;
-       debug("channel %d: free: %s, nchannels %d", c->self,
+       debug("channel %d: free: %s, nchannels %u", c->self,
            c->remote_name ? c->remote_name : "???", n);
 
        s = channel_open_message();
@@ -353,7 +355,7 @@ channel_free(Channel *c)
 void
 channel_free_all(void)
 {
-       int i;
+       u_int i;
 
        for (i = 0; i < channels_alloc; i++)
                if (channels[i] != NULL)
@@ -368,7 +370,7 @@ channel_free_all(void)
 void
 channel_close_all(void)
 {
-       int i;
+       u_int i;
 
        for (i = 0; i < channels_alloc; i++)
                if (channels[i] != NULL)
@@ -382,7 +384,7 @@ channel_close_all(void)
 void
 channel_stop_listening(void)
 {
-       int i;
+       u_int i;
        Channel *c;
 
        for (i = 0; i < channels_alloc; i++) {
@@ -439,7 +441,7 @@ channel_not_very_much_buffered_data(void)
 int
 channel_still_open(void)
 {
-       int i;
+       u_int i;
        Channel *c;
 
        for (i = 0; i < channels_alloc; i++) {
@@ -482,7 +484,7 @@ channel_still_open(void)
 int
 channel_find_open(void)
 {
-       int i;
+       u_int i;
        Channel *c;
 
        for (i = 0; i < channels_alloc; i++) {
@@ -530,7 +532,7 @@ channel_open_message(void)
        Buffer buffer;
        Channel *c;
        char buf[1024], *cp;
-       int i;
+       u_int i;
 
        buffer_init(&buffer);
        snprintf(buf, sizeof buf, "The following connections are open:\r\n");
@@ -1674,7 +1676,7 @@ static void
 channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
 {
        static int did_init = 0;
-       int i;
+       u_int i;
        Channel *c;
 
        if (!did_init) {
@@ -1697,10 +1699,9 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
  */
 void
 channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
-    int *nallocp, int rekeying)
+    u_int *nallocp, int rekeying)
 {
-       int n;
-       u_int sz;
+       u_int n, sz;
 
        n = MAX(*maxfdp, channel_max_fd);
 
@@ -1736,8 +1737,7 @@ void
 channel_output_poll(void)
 {
        Channel *c;
-       int i;
-       u_int len;
+       u_int i, len;
 
        for (i = 0; i < channels_alloc; i++) {
                c = channels[i];
@@ -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)
@@ -2270,7 +2314,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
 int
 channel_cancel_rport_listener(const char *host, u_short port)
 {
-       int i, found = 0;
+       u_int i;
+       int found = 0;
 
        for(i = 0; i < channels_alloc; i++) {
                Channel *c = channels[i];
@@ -2278,7 +2323,7 @@ channel_cancel_rport_listener(const char *host, u_short port)
                if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&
                    strncmp(c->path, host, sizeof(c->path)) == 0 &&
                    c->listening_port == port) {
-                       debug2("%s: close clannel %d", __func__, i);
+                       debug2("%s: close channel %d", __func__, i);
                        channel_free(c);
                        found = 1;
                }
@@ -2289,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 */
@@ -2311,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;
@@ -2322,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 */
@@ -2368,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;
@@ -2388,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();
 
@@ -2429,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);
@@ -2572,11 +2625,11 @@ channel_connect_to(const char *host, u_short port)
 void
 channel_send_window_changes(void)
 {
-       int i;
+       u_int i;
        struct winsize ws;
 
        for (i = 0; i < channels_alloc; i++) {
-               if (channels[i] == NULL ||
+               if (channels[i] == NULL || !channels[i]->client_tty || 
                    channels[i]->type != SSH_CHANNEL_OPEN)
                        continue;
                if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
This page took 0.05106 seconds and 4 git commands to generate.