[BACK]Return to channels.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / external / bsd / openssh / dist

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/crypto/external/bsd/openssh/dist/channels.c between version 1.15 and 1.15.2.2

version 1.15, 2016/03/11 01:55:00 version 1.15.2.2, 2017/01/07 08:53:41
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /* $OpenBSD: channels.c,v 1.349 2016/02/05 13:28:19 naddy Exp $ */  /* $OpenBSD: channels.c,v 1.356 2016/10/18 17:32:54 dtucker Exp $ */
   
 /*  /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Author: Tatu Ylonen <ylo@cs.hut.fi>
Line 45 
Line 45 
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  /* MIN MAX */  
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
 #include <sys/un.h>  #include <sys/un.h>
Line 71  __RCSID("$NetBSD$");
Line 70  __RCSID("$NetBSD$");
 #include "ssh.h"  #include "ssh.h"
 #include "ssh1.h"  #include "ssh1.h"
 #include "ssh2.h"  #include "ssh2.h"
   #include "ssherr.h"
 #include "packet.h"  #include "packet.h"
 #include "log.h"  #include "log.h"
 #include "misc.h"  #include "misc.h"
Line 124  typedef struct {
Line 124  typedef struct {
         char *listen_host;              /* Remote side should listen address. */          char *listen_host;              /* Remote side should listen address. */
         char *listen_path;              /* Remote side should listen path. */          char *listen_path;              /* Remote side should listen path. */
         int listen_port;                /* Remote side should listen port. */          int listen_port;                /* Remote side should listen port. */
           Channel *downstream;            /* Downstream mux*/
 } ForwardPermission;  } ForwardPermission;
   
 /* List of all permitted host/port pairs to connect by the user. */  /* List of all permitted host/port pairs to connect by the user. */
Line 141  static int num_adm_permitted_opens = 0;
Line 142  static int num_adm_permitted_opens = 0;
 /* special-case port number meaning allow any port */  /* special-case port number meaning allow any port */
 #define FWD_PERMIT_ANY_PORT     0  #define FWD_PERMIT_ANY_PORT     0
   
   /* special-case wildcard meaning allow any host */
   #define FWD_PERMIT_ANY_HOST     "*"
   
 /*  /*
  * If this is true, all opens are permitted.  This is the case on the server   * If this is true, all opens are permitted.  This is the case on the server
  * on which we have to trust the client anyway, and the user could do   * on which we have to trust the client anyway, and the user could do
Line 184  static int IPv4or6 = AF_UNSPEC;
Line 188  static int IPv4or6 = AF_UNSPEC;
   
 /* helper */  /* helper */
 static void port_open_helper(Channel *c, const char *rtype);  static void port_open_helper(Channel *c, const char *rtype);
   static const char *channel_rfwd_bind_host(const char *listen_host);
   
 /* non-blocking connect helpers */  /* non-blocking connect helpers */
 static int connect_next(struct channel_connect *);  static int connect_next(struct channel_connect *);
Line 208  channel_by_id(int id)
Line 213  channel_by_id(int id)
         return c;          return c;
 }  }
   
   Channel *
   channel_by_remote_id(int remote_id)
   {
           Channel *c;
           u_int i;
   
           for (i = 0; i < channels_alloc; i++) {
                   c = channels[i];
                   if (c != NULL && c->remote_id == remote_id)
                           return c;
           }
           return NULL;
   }
   
 /*  /*
  * Returns the channel if it is allowed to receive protocol messages.   * Returns the channel if it is allowed to receive protocol messages.
  * Private channels, like listening sockets, may not receive messages.   * Private channels, like listening sockets, may not receive messages.
Line 230  channel_lookup(int id)
Line 249  channel_lookup(int id)
         case SSH_CHANNEL_INPUT_DRAINING:          case SSH_CHANNEL_INPUT_DRAINING:
         case SSH_CHANNEL_OUTPUT_DRAINING:          case SSH_CHANNEL_OUTPUT_DRAINING:
         case SSH_CHANNEL_ABANDONED:          case SSH_CHANNEL_ABANDONED:
           case SSH_CHANNEL_MUX_PROXY:
                 return (c);                  return (c);
         }          }
         logit("Non-public channel %d, type %d.", id, c->type);          logit("Non-public channel %d, type %d.", id, c->type);
Line 245  channel_register_fds(Channel *c, int rfd
Line 265  channel_register_fds(Channel *c, int rfd
     int extusage, int nonblock, int is_tty)      int extusage, int nonblock, int is_tty)
 {  {
         /* Update the maximum file descriptor value. */          /* Update the maximum file descriptor value. */
         channel_max_fd = MAX(channel_max_fd, rfd);          channel_max_fd = MAXIMUM(channel_max_fd, rfd);
         channel_max_fd = MAX(channel_max_fd, wfd);          channel_max_fd = MAXIMUM(channel_max_fd, wfd);
         channel_max_fd = MAX(channel_max_fd, efd);          channel_max_fd = MAXIMUM(channel_max_fd, efd);
   
         if (rfd != -1)          if (rfd != -1)
                 fcntl(rfd, F_SETFD, FD_CLOEXEC);                  fcntl(rfd, F_SETFD, FD_CLOEXEC);
Line 371  channel_find_maxfd(void)
Line 391  channel_find_maxfd(void)
         for (i = 0; i < channels_alloc; i++) {          for (i = 0; i < channels_alloc; i++) {
                 c = channels[i];                  c = channels[i];
                 if (c != NULL) {                  if (c != NULL) {
                         max = MAX(max, c->rfd);                          max = MAXIMUM(max, c->rfd);
                         max = MAX(max, c->wfd);                          max = MAXIMUM(max, c->wfd);
                         max = MAX(max, c->efd);                          max = MAXIMUM(max, c->efd);
                 }                  }
         }          }
         return max;          return max;
Line 409  channel_free(Channel *c)
Line 429  channel_free(Channel *c)
 {  {
         char *s;          char *s;
         u_int i, n;          u_int i, n;
           Channel *other;
         struct channel_confirm *cc;          struct channel_confirm *cc;
   
         for (n = 0, i = 0; i < channels_alloc; i++)          for (n = 0, i = 0; i < channels_alloc; i++) {
                 if (channels[i])                  if ((other = channels[i]) != NULL) {
                         n++;                          n++;
   
                           /* detach from mux client and prepare for closing */
                           if (c->type == SSH_CHANNEL_MUX_CLIENT &&
                               other->type == SSH_CHANNEL_MUX_PROXY &&
                               other->mux_ctx == c) {
                                   other->mux_ctx = NULL;
                                   other->type = SSH_CHANNEL_OPEN;
                                   other->istate = CHAN_INPUT_CLOSED;
                                   other->ostate = CHAN_OUTPUT_CLOSED;
                           }
                   }
           }
         debug("channel %d: free: %s, nchannels %u", c->self,          debug("channel %d: free: %s, nchannels %u", c->self,
             c->remote_name ? c->remote_name : "???", n);              c->remote_name ? c->remote_name : "???", n);
   
           /* XXX more MUX cleanup: remove remote forwardings */
           if (c->type == SSH_CHANNEL_MUX_CLIENT) {
                   for (i = 0; i < (u_int)num_permitted_opens; i++) {
                           if (permitted_opens[i].downstream != c)
                                   continue;
                           /* cancel on the server, since mux client is gone */
                           debug("channel %d: cleanup remote forward for %s:%u",
                               c->self,
                               permitted_opens[i].listen_host,
                               permitted_opens[i].listen_port);
                           packet_start(SSH2_MSG_GLOBAL_REQUEST);
                           packet_put_cstring("cancel-tcpip-forward");
                           packet_put_char(0);
                           packet_put_cstring(channel_rfwd_bind_host(
                               permitted_opens[i].listen_host));
                           packet_put_int(permitted_opens[i].listen_port);
                           packet_send();
                           /* unregister */
                           permitted_opens[i].listen_port = 0;
                           permitted_opens[i].port_to_connect = 0;
                           free(permitted_opens[i].host_to_connect);
                           permitted_opens[i].host_to_connect = NULL;
                           free(permitted_opens[i].listen_host);
                           permitted_opens[i].listen_host = NULL;
                           permitted_opens[i].listen_path = NULL;
                           permitted_opens[i].downstream = NULL;
                   }
           }
   
         s = channel_open_message();          s = channel_open_message();
         debug3("channel %d: status: %s", c->self, s);          debug3("channel %d: status: %s", c->self, s);
         free(s);          free(s);
Line 562  channel_still_open(void)
Line 624  channel_still_open(void)
                 case SSH_CHANNEL_OPEN:                  case SSH_CHANNEL_OPEN:
                 case SSH_CHANNEL_X11_OPEN:                  case SSH_CHANNEL_X11_OPEN:
                 case SSH_CHANNEL_MUX_CLIENT:                  case SSH_CHANNEL_MUX_CLIENT:
                   case SSH_CHANNEL_MUX_PROXY:
                         return 1;                          return 1;
                 case SSH_CHANNEL_INPUT_DRAINING:                  case SSH_CHANNEL_INPUT_DRAINING:
                 case SSH_CHANNEL_OUTPUT_DRAINING:                  case SSH_CHANNEL_OUTPUT_DRAINING:
Line 595  channel_find_open(void)
Line 658  channel_find_open(void)
                 case SSH_CHANNEL_RPORT_LISTENER:                  case SSH_CHANNEL_RPORT_LISTENER:
                 case SSH_CHANNEL_MUX_LISTENER:                  case SSH_CHANNEL_MUX_LISTENER:
                 case SSH_CHANNEL_MUX_CLIENT:                  case SSH_CHANNEL_MUX_CLIENT:
                   case SSH_CHANNEL_MUX_PROXY:
                 case SSH_CHANNEL_OPENING:                  case SSH_CHANNEL_OPENING:
                 case SSH_CHANNEL_CONNECTING:                  case SSH_CHANNEL_CONNECTING:
                 case SSH_CHANNEL_ZOMBIE:                  case SSH_CHANNEL_ZOMBIE:
Line 620  channel_find_open(void)
Line 684  channel_find_open(void)
         return -1;          return -1;
 }  }
   
   
 /*  /*
  * Returns a message describing the currently open forwarded connections,   * Returns a message describing the currently open forwarded connections,
  * suitable for sending to the client.  The message contains crlf pairs for   * suitable for sending to the client.  The message contains crlf pairs for
Line 649  channel_open_message(void)
Line 712  channel_open_message(void)
                 case SSH_CHANNEL_AUTH_SOCKET:                  case SSH_CHANNEL_AUTH_SOCKET:
                 case SSH_CHANNEL_ZOMBIE:                  case SSH_CHANNEL_ZOMBIE:
                 case SSH_CHANNEL_ABANDONED:                  case SSH_CHANNEL_ABANDONED:
                 case SSH_CHANNEL_MUX_CLIENT:  
                 case SSH_CHANNEL_MUX_LISTENER:                  case SSH_CHANNEL_MUX_LISTENER:
                 case SSH_CHANNEL_UNIX_LISTENER:                  case SSH_CHANNEL_UNIX_LISTENER:
                 case SSH_CHANNEL_RUNIX_LISTENER:                  case SSH_CHANNEL_RUNIX_LISTENER:
Line 662  channel_open_message(void)
Line 724  channel_open_message(void)
                 case SSH_CHANNEL_X11_OPEN:                  case SSH_CHANNEL_X11_OPEN:
                 case SSH_CHANNEL_INPUT_DRAINING:                  case SSH_CHANNEL_INPUT_DRAINING:
                 case SSH_CHANNEL_OUTPUT_DRAINING:                  case SSH_CHANNEL_OUTPUT_DRAINING:
                   case SSH_CHANNEL_MUX_PROXY:
                   case SSH_CHANNEL_MUX_CLIENT:
                         snprintf(buf, sizeof buf,                          snprintf(buf, sizeof buf,
                             "  #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n",                              "  #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n",
                             c->self, c->remote_name,                              c->self, c->remote_name,
Line 1443  port_open_helper(Channel *c, const char 
Line 1507  port_open_helper(Channel *c, const char 
 {  {
         char buf[1024];          char buf[1024];
         char *local_ipaddr = get_local_ipaddr(c->sock);          char *local_ipaddr = get_local_ipaddr(c->sock);
         int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);          int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);
         char *remote_ipaddr = get_peer_ipaddr(c->sock);          char *remote_ipaddr = get_peer_ipaddr(c->sock);
         int remote_port = get_peer_port(c->sock);          int remote_port = get_peer_port(c->sock);
   
Line 1912  read_mux(Channel *c, u_int need)
Line 1976  read_mux(Channel *c, u_int need)
   
         if (buffer_len(&c->input) < need) {          if (buffer_len(&c->input) < need) {
                 rlen = need - buffer_len(&c->input);                  rlen = need - buffer_len(&c->input);
                 len = read(c->rfd, buf, MIN(rlen, CHAN_RBUF));                  len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF));
                 if (len < 0 && (errno == EINTR || errno == EAGAIN))                  if (len < 0 && (errno == EINTR || errno == EAGAIN))
                         return buffer_len(&c->input);                          return buffer_len(&c->input);
                 if (len <= 0) {                  if (len <= 0) {
Line 2215  channel_prepare_select(fd_set **readsetp
Line 2279  channel_prepare_select(fd_set **readsetp
 {  {
         u_int n, sz, nfdset;          u_int n, sz, nfdset;
   
         n = MAX(*maxfdp, channel_max_fd);          n = MAXIMUM(*maxfdp, channel_max_fd);
   
         nfdset = howmany(n+1, NFDBITS);          nfdset = howmany(n+1, NFDBITS);
         /* Explicitly test here, because xrealloc isn't always called */          /* Explicitly test here, because xrealloc isn't always called */
Line 2377  channel_output_poll(void)
Line 2441  channel_output_poll(void)
         return (packet_length);          return (packet_length);
 }  }
   
   /* -- mux proxy support  */
   
   /*
    * When multiplexing channel messages for mux clients we have to deal
    * with downstream messages from the mux client and upstream messages
    * from the ssh server:
    * 1) Handling downstream messages is straightforward and happens
    *    in channel_proxy_downstream():
    *    - We forward all messages (mostly) unmodified to the server.
    *    - However, in order to route messages from upstream to the correct
    *      downstream client, we have to replace the channel IDs used by the
    *      mux clients with a unique channel ID because the mux clients might
    *      use conflicting channel IDs.
    *    - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and
    *      SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local
    *      SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
    *      with the newly allocated channel ID.
    * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
    *    channels and procesed by channel_proxy_upstream(). The local channel ID
    *    is then translated back to the original mux client ID.
    * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
    *    messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
    * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the
    *    downstream mux client are removed.
    * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server
    *    requires more work, because they are not addressed to a specific
    *    channel. E.g. client_request_forwarded_tcpip() needs to figure
    *    out whether the request is addressed to the local client or a
    *    specific downstream client based on the listen-address/port.
    * 6) Agent and X11-Forwarding have a similar problem and are currenly
    *    not supported as the matching session/channel cannot be identified
    *    easily.
    */
   
   /*
    * receive packets from downstream mux clients:
    * channel callback fired on read from mux client, creates
    * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs
    * on channel creation.
    */
   int
   channel_proxy_downstream(Channel *downstream)
   {
           Channel *c = NULL;
           struct ssh *ssh = active_state;
           struct sshbuf *original = NULL, *modified = NULL;
           const u_char *cp;
           char *ctype = NULL, *listen_host = NULL;
           u_char type;
           size_t have;
           int ret = -1, r, idx;
           u_int id, remote_id, listen_port;
   
           /* sshbuf_dump(&downstream->input, stderr); */
           if ((r = sshbuf_get_string_direct(&downstream->input, &cp, &have))
               != 0) {
                   error("%s: malformed message: %s", __func__, ssh_err(r));
                   return -1;
           }
           if (have < 2) {
                   error("%s: short message", __func__);
                   return -1;
           }
           type = cp[1];
           /* skip padlen + type */
           cp += 2;
           have -= 2;
           if (ssh_packet_log_type(type))
                   debug3("%s: channel %u: down->up: type %u", __func__,
                       downstream->self, type);
   
           switch (type) {
           case SSH2_MSG_CHANNEL_OPEN:
                   if ((original = sshbuf_from(cp, have)) == NULL ||
                       (modified = sshbuf_new()) == NULL) {
                           error("%s: alloc", __func__);
                           goto out;
                   }
                   if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||
                       (r = sshbuf_get_u32(original, &id)) != 0) {
                           error("%s: parse error %s", __func__, ssh_err(r));
                           goto out;
                   }
                   c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY,
                      -1, -1, -1, 0, 0, 0, ctype, 1);
                   c->mux_ctx = downstream;        /* point to mux client */
                   c->mux_downstream_id = id;      /* original downstream id */
                   if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
                       (r = sshbuf_put_u32(modified, c->self)) != 0 ||
                       (r = sshbuf_putb(modified, original)) != 0) {
                           error("%s: compose error %s", __func__, ssh_err(r));
                           channel_free(c);
                           goto out;
                   }
                   break;
           case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
                   /*
                    * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we
                    * need to parse 'remote_id' instead of 'ctype'.
                    */
                   if ((original = sshbuf_from(cp, have)) == NULL ||
                       (modified = sshbuf_new()) == NULL) {
                           error("%s: alloc", __func__);
                           goto out;
                   }
                   if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
                       (r = sshbuf_get_u32(original, &id)) != 0) {
                           error("%s: parse error %s", __func__, ssh_err(r));
                           goto out;
                   }
                   c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY,
                      -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
                   c->mux_ctx = downstream;        /* point to mux client */
                   c->mux_downstream_id = id;
                   c->remote_id = remote_id;
                   if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
                       (r = sshbuf_put_u32(modified, c->self)) != 0 ||
                       (r = sshbuf_putb(modified, original)) != 0) {
                           error("%s: compose error %s", __func__, ssh_err(r));
                           channel_free(c);
                           goto out;
                   }
                   break;
           case SSH2_MSG_GLOBAL_REQUEST:
                   if ((original = sshbuf_from(cp, have)) == NULL) {
                           error("%s: alloc", __func__);
                           goto out;
                   }
                   if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {
                           error("%s: parse error %s", __func__, ssh_err(r));
                           goto out;
                   }
                   if (strcmp(ctype, "tcpip-forward") != 0) {
                           error("%s: unsupported request %s", __func__, ctype);
                           goto out;
                   }
                   if ((r = sshbuf_get_u8(original, NULL)) != 0 ||
                       (r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||
                       (r = sshbuf_get_u32(original, &listen_port)) != 0) {
                           error("%s: parse error %s", __func__, ssh_err(r));
                           goto out;
                   }
                   if (listen_port > 65535) {
                           error("%s: tcpip-forward for %s: bad port %u",
                               __func__, listen_host, listen_port);
                           goto out;
                   }
                   /* Record that connection to this host/port is permitted. */
                   permitted_opens = xreallocarray(permitted_opens,
                       num_permitted_opens + 1, sizeof(*permitted_opens));
                   idx = num_permitted_opens++;
                   permitted_opens[idx].host_to_connect = xstrdup("<mux>");
                   permitted_opens[idx].port_to_connect = -1;
                   permitted_opens[idx].listen_host = listen_host;
                   permitted_opens[idx].listen_port = (int)listen_port;
                   permitted_opens[idx].downstream = downstream;
                   listen_host = NULL;
                   break;
           case SSH2_MSG_CHANNEL_CLOSE:
                   if (have < 4)
                           break;
                   remote_id = PEEK_U32(cp);
                   if ((c = channel_by_remote_id(remote_id)) != NULL) {
                           if (c->flags & CHAN_CLOSE_RCVD)
                                   channel_free(c);
                           else
                                   c->flags |= CHAN_CLOSE_SENT;
                   }
                   break;
           }
           if (modified) {
                   if ((r = sshpkt_start(ssh, type)) != 0 ||
                       (r = sshpkt_putb(ssh, modified)) != 0 ||
                       (r = sshpkt_send(ssh)) != 0) {
                           error("%s: send %s", __func__, ssh_err(r));
                           goto out;
                   }
           } else {
                   if ((r = sshpkt_start(ssh, type)) != 0 ||
                       (r = sshpkt_put(ssh, cp, have)) != 0 ||
                       (r = sshpkt_send(ssh)) != 0) {
                           error("%s: send %s", __func__, ssh_err(r));
                           goto out;
                   }
           }
           ret = 0;
    out:
           free(ctype);
           free(listen_host);
           sshbuf_free(original);
           sshbuf_free(modified);
           return ret;
   }
   
   /*
    * receive packets from upstream server and de-multiplex packets
    * to correct downstream:
    * implemented as a helper for channel input handlers,
    * replaces local (proxy) channel ID with downstream channel ID.
    */
   int
   channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt)
   {
           struct ssh *ssh = active_state;
           struct sshbuf *b = NULL;
           Channel *downstream;
           const u_char *cp = NULL;
           size_t len;
           int r;
   
           /*
            * When receiving packets from the peer we need to check whether we
            * need to forward the packets to the mux client. In this case we
            * restore the orignal channel id and keep track of CLOSE messages,
            * so we can cleanup the channel.
            */
           if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)
                   return 0;
           if ((downstream = c->mux_ctx) == NULL)
                   return 0;
           switch (type) {
           case SSH2_MSG_CHANNEL_CLOSE:
           case SSH2_MSG_CHANNEL_DATA:
           case SSH2_MSG_CHANNEL_EOF:
           case SSH2_MSG_CHANNEL_EXTENDED_DATA:
           case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
           case SSH2_MSG_CHANNEL_OPEN_FAILURE:
           case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
           case SSH2_MSG_CHANNEL_SUCCESS:
           case SSH2_MSG_CHANNEL_FAILURE:
           case SSH2_MSG_CHANNEL_REQUEST:
                   break;
           default:
                   debug2("%s: channel %u: unsupported type %u", __func__,
                       c->self, type);
                   return 0;
           }
           if ((b = sshbuf_new()) == NULL) {
                   error("%s: alloc reply", __func__);
                   goto out;
           }
           /* get remaining payload (after id) */
           cp = sshpkt_ptr(ssh, &len);
           if (cp == NULL) {
                   error("%s: no packet", __func__);
                   goto out;
           }
           /* translate id and send to muxclient */
           if ((r = sshbuf_put_u8(b, 0)) != 0 ||   /* padlen */
               (r = sshbuf_put_u8(b, type)) != 0 ||
               (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
               (r = sshbuf_put(b, cp, len)) != 0 ||
               (r = sshbuf_put_stringb(&downstream->output, b)) != 0) {
                   error("%s: compose for muxclient %s", __func__, ssh_err(r));
                   goto out;
           }
           /* sshbuf_dump(b, stderr); */
           if (ssh_packet_log_type(type))
                   debug3("%s: channel %u: up->down: type %u", __func__, c->self,
                       type);
    out:
           /* update state */
           switch (type) {
           case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
                   /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */
                   if (cp && len > 4)
                           c->remote_id = PEEK_U32(cp);
                   break;
           case SSH2_MSG_CHANNEL_CLOSE:
                   if (c->flags & CHAN_CLOSE_SENT)
                           channel_free(c);
                   else
                           c->flags |= CHAN_CLOSE_RCVD;
                   break;
           }
           sshbuf_free(b);
           return 1;
   }
   
 /* -- protocol input */  /* -- protocol input */
   
Line 2394  channel_input_data(int type, u_int32_t s
Line 2736  channel_input_data(int type, u_int32_t s
         c = channel_lookup(id);          c = channel_lookup(id);
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received data for nonexistent channel %d.", id);                  packet_disconnect("Received data for nonexistent channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
   
         /* Ignore any data for non-open channels (might happen on close) */          /* Ignore any data for non-open channels (might happen on close) */
         if (c->type != SSH_CHANNEL_OPEN &&          if (c->type != SSH_CHANNEL_OPEN &&
Line 2456  channel_input_extended_data(int type, u_
Line 2800  channel_input_extended_data(int type, u_
   
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received extended_data for bad channel %d.", id);                  packet_disconnect("Received extended_data for bad channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
         if (c->type != SSH_CHANNEL_OPEN) {          if (c->type != SSH_CHANNEL_OPEN) {
                 logit("channel %d: ext data for non open", id);                  logit("channel %d: ext data for non open", id);
                 return 0;                  return 0;
Line 2501  channel_input_ieof(int type, u_int32_t s
Line 2847  channel_input_ieof(int type, u_int32_t s
         c = channel_lookup(id);          c = channel_lookup(id);
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received ieof for nonexistent channel %d.", id);                  packet_disconnect("Received ieof for nonexistent channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
         chan_rcvd_ieof(c);          chan_rcvd_ieof(c);
   
         /* XXX force input close */          /* XXX force input close */
Line 2525  channel_input_close(int type, u_int32_t 
Line 2873  channel_input_close(int type, u_int32_t 
         c = channel_lookup(id);          c = channel_lookup(id);
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received close for nonexistent channel %d.", id);                  packet_disconnect("Received close for nonexistent channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
         /*          /*
          * Send a confirmation that we have closed the channel and no more           * Send a confirmation that we have closed the channel and no more
          * data is coming for it.           * data is coming for it.
Line 2560  channel_input_oclose(int type, u_int32_t
Line 2909  channel_input_oclose(int type, u_int32_t
         int id = packet_get_int();          int id = packet_get_int();
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         packet_check_eom();  
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received oclose for nonexistent channel %d.", id);                  packet_disconnect("Received oclose for nonexistent channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
           packet_check_eom();
         chan_rcvd_oclose(c);          chan_rcvd_oclose(c);
         return 0;          return 0;
 }  }
Line 2574  channel_input_close_confirmation(int typ
Line 2925  channel_input_close_confirmation(int typ
         int id = packet_get_int();          int id = packet_get_int();
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         packet_check_eom();  
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("Received close confirmation for "                  packet_disconnect("Received close confirmation for "
                     "out-of-range channel %d.", id);                      "out-of-range channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
           packet_check_eom();
         if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED)          if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED)
                 packet_disconnect("Received close confirmation for "                  packet_disconnect("Received close confirmation for "
                     "non-closed channel %d (type %d).", id, c->type);                      "non-closed channel %d (type %d).", id, c->type);
Line 2595  channel_input_open_confirmation(int type
Line 2948  channel_input_open_confirmation(int type
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
   
         if (c==NULL || c->type != SSH_CHANNEL_OPENING)          if (c==NULL)
                   packet_disconnect("Received open confirmation for "
                       "unknown channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
           if (c->type != SSH_CHANNEL_OPENING)
                 packet_disconnect("Received open confirmation for "                  packet_disconnect("Received open confirmation for "
                     "non-opening channel %d.", id);                      "non-opening channel %d.", id);
         remote_id = packet_get_int();          remote_id = packet_get_int();
Line 2645  channel_input_open_failure(int type, u_i
Line 3003  channel_input_open_failure(int type, u_i
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
   
         if (c==NULL || c->type != SSH_CHANNEL_OPENING)          if (c==NULL)
                   packet_disconnect("Received open failure for "
                       "unknown channel %d.", id);
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
           if (c->type != SSH_CHANNEL_OPENING)
                 packet_disconnect("Received open failure for "                  packet_disconnect("Received open failure for "
                     "non-opening channel %d.", id);                      "non-opening channel %d.", id);
         if (compat20) {          if (compat20) {
Line 2689  channel_input_window_adjust(int type, u_
Line 3052  channel_input_window_adjust(int type, u_
                 logit("Received window adjust for non-open channel %d.", id);                  logit("Received window adjust for non-open channel %d.", id);
                 return 0;                  return 0;
         }          }
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
         adjust = packet_get_int();          adjust = packet_get_int();
         packet_check_eom();          packet_check_eom();
         debug2("channel %d: rcvd adjust %u", id, adjust);          debug2("channel %d: rcvd adjust %u", id, adjust);
Line 2743  channel_input_status_confirm(int type, u
Line 3108  channel_input_status_confirm(int type, u
         packet_set_alive_timeouts(0);          packet_set_alive_timeouts(0);
   
         id = packet_get_int();          id = packet_get_int();
         packet_check_eom();  
   
         debug2("channel_input_status_confirm: type %d id %d", type, id);          debug2("channel_input_status_confirm: type %d id %d", type, id);
   
         if ((c = channel_lookup(id)) == NULL) {          if ((c = channel_lookup(id)) == NULL) {
                 logit("channel_input_status_confirm: %d: unknown", id);                  logit("channel_input_status_confirm: %d: unknown", id);
                 return 0;                  return 0;
         }          }
           if (channel_proxy_upstream(c, type, seq, ctxt))
                   return 0;
           packet_check_eom();
         if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)          if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
                 return 0;                  return 0;
         cc->cb(type, c, cc->ctx);          cc->cb(type, c, cc->ctx);
Line 2955  channel_setup_fwd_listener_tcpip(int typ
Line 3321  channel_setup_fwd_listener_tcpip(int typ
                 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&                  if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
                     allocated_listen_port != NULL &&                      allocated_listen_port != NULL &&
                     *allocated_listen_port == 0) {                      *allocated_listen_port == 0) {
                         *allocated_listen_port = get_sock_port(sock, 1);                          *allocated_listen_port = get_local_port(sock);
                         debug("Allocated listen port %d",                          debug("Allocated listen port %d",
                             *allocated_listen_port);                              *allocated_listen_port);
                 }                  }
Line 3311  channel_request_remote_forwarding(struct
Line 3677  channel_request_remote_forwarding(struct
                         permitted_opens[idx].listen_path = NULL;                          permitted_opens[idx].listen_path = NULL;
                         permitted_opens[idx].listen_port = fwd->listen_port;                          permitted_opens[idx].listen_port = fwd->listen_port;
                 }                  }
                   permitted_opens[idx].downstream = NULL;
         }          }
         return (idx);          return (idx);
 }  }
Line 3324  open_match(ForwardPermission *allowed_op
Line 3691  open_match(ForwardPermission *allowed_op
         if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&          if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
             allowed_open->port_to_connect != requestedport)              allowed_open->port_to_connect != requestedport)
                 return 0;                  return 0;
         if (strcmp(allowed_open->host_to_connect, requestedhost) != 0)          if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 &&
               strcmp(allowed_open->host_to_connect, requestedhost) != 0)
                 return 0;                  return 0;
         return 1;          return 1;
 }  }
Line 3405  channel_request_rforward_cancel_tcpip(co
Line 3773  channel_request_rforward_cancel_tcpip(co
         free(permitted_opens[i].listen_host);          free(permitted_opens[i].listen_host);
         permitted_opens[i].listen_host = NULL;          permitted_opens[i].listen_host = NULL;
         permitted_opens[i].listen_path = NULL;          permitted_opens[i].listen_path = NULL;
           permitted_opens[i].downstream = NULL;
   
         return 0;          return 0;
 }  }
Line 3442  channel_request_rforward_cancel_streamlo
Line 3811  channel_request_rforward_cancel_streamlo
         permitted_opens[i].listen_host = NULL;          permitted_opens[i].listen_host = NULL;
         free(permitted_opens[i].listen_path);          free(permitted_opens[i].listen_path);
         permitted_opens[i].listen_path = NULL;          permitted_opens[i].listen_path = NULL;
           permitted_opens[i].downstream = NULL;
   
         return 0;          return 0;
 }  }
Line 3462  channel_request_rforward_cancel(struct F
Line 3832  channel_request_rforward_cancel(struct F
 }  }
   
 /*  /*
  * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates  
  * listening for the port, and sends back a success reply (or disconnect  
  * message if there was an error).  
  */  
 int  
 channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)  
 {  
         int success = 0;  
         struct Forward fwd;  
   
         /* Get arguments from the packet. */  
         memset(&fwd, 0, sizeof(fwd));  
         fwd.listen_port = packet_get_int();  
         fwd.connect_host = packet_get_string(NULL);  
         fwd.connect_port = packet_get_int();  
   
         /*  
          * Check that an unprivileged user is not trying to forward a  
          * privileged port.  
          */  
         if (fwd.listen_port < IPPORT_RESERVED && !is_root)  
                 packet_disconnect(  
                     "Requested forwarding of port %d but user is not root.",  
                     fwd.listen_port);  
         if (fwd.connect_port == 0)  
                 packet_disconnect("Dynamic forwarding denied.");  
   
         /* Initiate forwarding */  
         success = channel_setup_local_fwd_listener(&fwd, fwd_opts);  
   
         /* Free the argument string. */  
         free(fwd.connect_host);  
   
         return (success ? 0 : -1);  
 }  
   
 /*  
  * Permits opening to any host/port if permitted_opens[] is empty.  This is   * Permits opening to any host/port if permitted_opens[] is empty.  This is
  * usually called by the server, because the user could connect to any port   * usually called by the server, because the user could connect to any port
  * anyway, and the server has no way to know but to trust the client anyway.   * anyway, and the server has no way to know but to trust the client anyway.
Line 3522  channel_add_permitted_opens(char *host, 
Line 3855  channel_add_permitted_opens(char *host, 
         permitted_opens[num_permitted_opens].listen_host = NULL;          permitted_opens[num_permitted_opens].listen_host = NULL;
         permitted_opens[num_permitted_opens].listen_path = NULL;          permitted_opens[num_permitted_opens].listen_path = NULL;
         permitted_opens[num_permitted_opens].listen_port = 0;          permitted_opens[num_permitted_opens].listen_port = 0;
           permitted_opens[num_permitted_opens].downstream = NULL;
         num_permitted_opens++;          num_permitted_opens++;
   
         all_opens_permitted = 0;          all_opens_permitted = 0;
Line 3653  connect_next(struct channel_connect *cct
Line 3987  connect_next(struct channel_connect *cct
 {  {
         int sock, saved_errno;          int sock, saved_errno;
         struct sockaddr_un *sunaddr;          struct sockaddr_un *sunaddr;
         char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];          char ntop[NI_MAXHOST], strport[MAXIMUM(NI_MAXSERV,sizeof(sunaddr->sun_path))];
   
         for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {          for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
                 switch (cctx->ai->ai_family) {                  switch (cctx->ai->ai_family) {
Line 3784  connect_to(const char *name, int port, c
Line 4118  connect_to(const char *name, int port, c
         return c;          return c;
 }  }
   
   /*
    * returns either the newly connected channel or the downstream channel
    * that needs to deal with this connection.
    */
 Channel *  Channel *
 channel_connect_by_listen_address(const char *listen_host,  channel_connect_by_listen_address(const char *listen_host,
     u_short listen_port, const char *ctype, char *rname)      u_short listen_port, const char *ctype, char *rname)
Line 3793  channel_connect_by_listen_address(const 
Line 4131  channel_connect_by_listen_address(const 
         for (i = 0; i < num_permitted_opens; i++) {          for (i = 0; i < num_permitted_opens; i++) {
                 if (open_listen_match_tcpip(&permitted_opens[i], listen_host,                  if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
                     listen_port, 1)) {                      listen_port, 1)) {
                           if (permitted_opens[i].downstream)
                                   return permitted_opens[i].downstream;
                         return connect_to(                          return connect_to(
                             permitted_opens[i].host_to_connect,                              permitted_opens[i].host_to_connect,
                             permitted_opens[i].port_to_connect, ctype, rname);                              permitted_opens[i].port_to_connect, ctype, rname);
Line 4211  x11_request_forwarding_with_spoofing(int
Line 4551  x11_request_forwarding_with_spoofing(int
         char *new_data;          char *new_data;
         int screen_number;          int screen_number;
         const char *cp;          const char *cp;
         u_int32_t rnd = 0;  
   
         if (x11_saved_display == NULL)          if (x11_saved_display == NULL)
                 x11_saved_display = xstrdup(disp);                  x11_saved_display = xstrdup(disp);
Line 4232  x11_request_forwarding_with_spoofing(int
Line 4571  x11_request_forwarding_with_spoofing(int
         if (x11_saved_proto == NULL) {          if (x11_saved_proto == NULL) {
                 /* Save protocol name. */                  /* Save protocol name. */
                 x11_saved_proto = xstrdup(proto);                  x11_saved_proto = xstrdup(proto);
                 /*  
                  * Extract real authentication data and generate fake data                  /* Extract real authentication data. */
                  * of the same length.  
                  */  
                 x11_saved_data = xmalloc(data_len);                  x11_saved_data = xmalloc(data_len);
                 x11_fake_data = xmalloc(data_len);  
                 for (i = 0; i < data_len; i++) {                  for (i = 0; i < data_len; i++) {
                         if (sscanf(data + 2 * i, "%2x", &value) != 1)                          if (sscanf(data + 2 * i, "%2x", &value) != 1)
                                 fatal("x11_request_forwarding: bad "                                  fatal("x11_request_forwarding: bad "
                                     "authentication data: %.100s", data);                                      "authentication data: %.100s", data);
                         if (i % 4 == 0)  
                                 rnd = arc4random();  
                         x11_saved_data[i] = value;                          x11_saved_data[i] = value;
                         x11_fake_data[i] = rnd & 0xff;  
                         rnd >>= 8;  
                 }                  }
                 x11_saved_data_len = data_len;                  x11_saved_data_len = data_len;
   
                   /* Generate fake data of the same length. */
                   x11_fake_data = xmalloc(data_len);
                   arc4random_buf(x11_fake_data, data_len);
                 x11_fake_data_len = data_len;                  x11_fake_data_len = data_len;
         }          }
   

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.15.2.2

CVSweb <webmaster@jp.NetBSD.org>