[BACK]Return to channels.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/channels.c between version 1.210 and 1.210.2.3

version 1.210, 2004/08/23 11:48:47 version 1.210.2.3, 2005/09/02 03:44:59
Line 58 
Line 58 
   
 /* -- channel core */  /* -- channel core */
   
   #define CHAN_RBUF       16*1024
   
 /*  /*
  * Pointer to an array containing all allocated channels.  The array is   * Pointer to an array containing all allocated channels.  The array is
  * dynamically extended as needed.   * dynamically extended as needed.
Line 109 
Line 111 
 /* Maximum number of fake X11 displays to try. */  /* Maximum number of fake X11 displays to try. */
 #define MAX_DISPLAYS  1000  #define MAX_DISPLAYS  1000
   
   /* Saved X11 local (client) display. */
   static char *x11_saved_display = NULL;
   
 /* Saved X11 authentication protocol name. */  /* Saved X11 authentication protocol name. */
 static char *x11_saved_proto = NULL;  static char *x11_saved_proto = NULL;
   
Line 711 
Line 716 
 {  {
         u_int limit = compat20 ? c->remote_window : packet_get_maxsize();          u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
   
           /* check buffer limits */
           limit = MIN(limit, (BUFFER_MAX_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF));
   
         if (c->istate == CHAN_INPUT_OPEN &&          if (c->istate == CHAN_INPUT_OPEN &&
             limit > 0 &&              limit > 0 &&
             buffer_len(&c->input) < limit)              buffer_len(&c->input) < limit)
Line 721 
Line 729 
                         FD_SET(c->wfd, writeset);                          FD_SET(c->wfd, writeset);
                 } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {                  } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                         if (CHANNEL_EFD_OUTPUT_ACTIVE(c))                          if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
                                debug2("channel %d: obuf_empty delayed efd %d/(%d)",                                  debug2("channel %d: obuf_empty delayed efd %d/(%d)",
                                    c->self, c->efd, buffer_len(&c->extended));                                      c->self, c->efd, buffer_len(&c->extended));
                         else                          else
                                 chan_obuf_empty(c);                                  chan_obuf_empty(c);
                 }                  }
Line 888 
Line 896 
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)  channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         char *p, *host;          char *p, *host;
         int len, have, i, found;          u_int len, have, i, found;
         char username[256];          char username[256];
         struct {          struct {
                 u_int8_t version;                  u_int8_t version;
Line 973 
Line 981 
         } s5_req, s5_rsp;          } s5_req, s5_rsp;
         u_int16_t dest_port;          u_int16_t dest_port;
         u_char *p, dest_addr[255+1];          u_char *p, dest_addr[255+1];
         int i, have, found, nmethods, addrlen, af;          u_int have, i, found, nmethods, addrlen, af;
   
         debug2("channel %d: decode socks5", c->self);          debug2("channel %d: decode socks5", c->self);
         p = buffer_ptr(&c->input);          p = buffer_ptr(&c->input);
Line 1017 
Line 1025 
                 debug2("channel %d: only socks5 connect supported", c->self);                  debug2("channel %d: only socks5 connect supported", c->self);
                 return -1;                  return -1;
         }          }
         switch(s5_req.atyp){          switch (s5_req.atyp){
         case SSH_SOCKS5_IPV4:          case SSH_SOCKS5_IPV4:
                 addrlen = 4;                  addrlen = 4;
                 af = AF_INET;                  af = AF_INET;
Line 1069 
Line 1077 
 channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)  channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         u_char *p;          u_char *p;
         int have, ret;          u_int have;
           int ret;
   
         have = buffer_len(&c->input);          have = buffer_len(&c->input);
         c->delayed = 0;          c->delayed = 0;
Line 1172 
Line 1181 
         int direct;          int direct;
         char buf[1024];          char buf[1024];
         char *remote_ipaddr = get_peer_ipaddr(c->sock);          char *remote_ipaddr = get_peer_ipaddr(c->sock);
         u_short remote_port = get_peer_port(c->sock);          int remote_port = get_peer_port(c->sock);
   
         direct = (strcmp(rtype, "direct-tcpip") == 0);          direct = (strcmp(rtype, "direct-tcpip") == 0);
   
Line 1202 
Line 1211 
                 }                  }
                 /* originator host and port */                  /* originator host and port */
                 packet_put_cstring(remote_ipaddr);                  packet_put_cstring(remote_ipaddr);
                 packet_put_int(remote_port);                  packet_put_int((u_int)remote_port);
                 packet_send();                  packet_send();
         } else {          } else {
                 packet_start(SSH_MSG_PORT_OPEN);                  packet_start(SSH_MSG_PORT_OPEN);
Line 1359 
Line 1368 
 static int  static int
 channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)  channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         char buf[16*1024];          char buf[CHAN_RBUF];
         int len;          int len;
   
         if (c->rfd != -1 &&          if (c->rfd != -1 &&
Line 1448 
Line 1457 
 static int  static int
 channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)  channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         char buf[16*1024];          char buf[CHAN_RBUF];
         int len;          int len;
   
 /** XXX handle drain efd, too */  /** XXX handle drain efd, too */
Line 1798 
Line 1807 
                          * hack for extended data: delay EOF if EFD still in use.                           * hack for extended data: delay EOF if EFD still in use.
                          */                           */
                         if (CHANNEL_EFD_INPUT_ACTIVE(c))                          if (CHANNEL_EFD_INPUT_ACTIVE(c))
                                debug2("channel %d: ibuf_empty delayed efd %d/(%d)",                                  debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
                                    c->self, c->efd, buffer_len(&c->extended));                                      c->self, c->efd, buffer_len(&c->extended));
                         else                          else
                                 chan_ibuf_empty(c);                                  chan_ibuf_empty(c);
                 }                  }
Line 2173 
Line 2182 
     const char *host_to_connect, u_short port_to_connect, int gateway_ports)      const char *host_to_connect, u_short port_to_connect, int gateway_ports)
 {  {
         Channel *c;          Channel *c;
         int success, sock, on = 1;          int sock, r, success = 0, on = 1, wildcard = 0, is_client;
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         const char *host;          const char *host, *addr;
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          char ntop[NI_MAXHOST], strport[NI_MAXSERV];
   
         success = 0;  
         host = (type == SSH_CHANNEL_RPORT_LISTENER) ?          host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
             listen_addr : host_to_connect;              listen_addr : host_to_connect;
           is_client = (type == SSH_CHANNEL_PORT_LISTENER);
   
         if (host == NULL) {          if (host == NULL) {
                 error("No forward host name.");                  error("No forward host name.");
                 return success;                  return 0;
         }          }
         if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) {          if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) {
                 error("Forward host name too long.");                  error("Forward host name too long.");
                 return success;                  return 0;
         }          }
   
         /*          /*
            * 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           * getaddrinfo returns a loopback address if the hostname is
          * set to NULL and hints.ai_flags is not AI_PASSIVE           * set to NULL and hints.ai_flags is not AI_PASSIVE
          */           */
         memset(&hints, 0, sizeof(hints));          memset(&hints, 0, sizeof(hints));
         hints.ai_family = IPv4or6;          hints.ai_family = IPv4or6;
         hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;          hints.ai_flags = wildcard ? AI_PASSIVE : 0;
         hints.ai_socktype = SOCK_STREAM;          hints.ai_socktype = SOCK_STREAM;
         snprintf(strport, sizeof strport, "%d", listen_port);          snprintf(strport, sizeof strport, "%d", listen_port);
         if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)          if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
                 packet_disconnect("getaddrinfo: fatal error");                  if (addr == NULL) {
                           /* This really shouldn't happen */
                           packet_disconnect("getaddrinfo: fatal error: %s",
                               gai_strerror(r));
                   } else {
                           error("channel_setup_fwd_listener: "
                               "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
                   }
                   return 0;
           }
   
         for (ai = aitop; ai; ai = ai->ai_next) {          for (ai = aitop; ai; ai = ai->ai_next) {
                 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)                  if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Line 2263 
Line 2314 
         u_int i;          u_int i;
         int found = 0;          int found = 0;
   
         for(i = 0; i < channels_alloc; i++) {          for (i = 0; i < channels_alloc; i++) {
                 Channel *c = channels[i];                  Channel *c = channels[i];
   
                 if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&                  if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&
Line 2280 
Line 2331 
   
 /* protocol local port fwd, used by ssh (and sshd in v1) */  /* protocol local port fwd, used by ssh (and sshd in v1) */
 int  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)      const char *host_to_connect, u_short port_to_connect, int gateway_ports)
 {  {
         return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,          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 */  /* protocol v2 remote port fwd, used by sshd */
Line 2302 
Line 2354 
  */   */
   
 void  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)      const char *host_to_connect, u_short port_to_connect)
 {  {
         int type, success = 0;          int type, success = 0;
Line 2313 
Line 2365 
   
         /* Send the forward request to the remote side. */          /* Send the forward request to the remote side. */
         if (compat20) {          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_start(SSH2_MSG_GLOBAL_REQUEST);
                 packet_put_cstring("tcpip-forward");                  packet_put_cstring("tcpip-forward");
                 packet_put_char(1);                     /* boolean: want reply */                  packet_put_char(1);                     /* boolean: want reply */
Line 2359 
Line 2418 
  * local side.   * local side.
  */   */
 void  void
 channel_request_rforward_cancel(u_short port)  channel_request_rforward_cancel(const char *host, u_short port)
 {  {
         int i;          int i;
         const char *address_to_bind = "0.0.0.0";  
   
         if (!compat20)          if (!compat20)
                 return;                  return;
Line 2379 
Line 2437 
         packet_start(SSH2_MSG_GLOBAL_REQUEST);          packet_start(SSH2_MSG_GLOBAL_REQUEST);
         packet_put_cstring("cancel-tcpip-forward");          packet_put_cstring("cancel-tcpip-forward");
         packet_put_char(0);          packet_put_char(0);
         packet_put_cstring(address_to_bind);          packet_put_cstring(host == NULL ? "" : host);
         packet_put_int(port);          packet_put_int(port);
         packet_send();          packet_send();
   
Line 2418 
Line 2476 
                 packet_disconnect("Dynamic forwarding denied.");                  packet_disconnect("Dynamic forwarding denied.");
   
         /* Initiate forwarding */          /* 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. */          /* Free the argument string. */
         xfree(hostname);          xfree(hostname);
Line 2565 
Line 2624 
         struct winsize ws;          struct winsize ws;
   
         for (i = 0; i < channels_alloc; i++) {          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)                      channels[i]->type != SSH_CHANNEL_OPEN)
                         continue;                          continue;
                 if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)                  if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
Line 2588 
Line 2647 
  */   */
 int  int
 x11_create_display_inet(int x11_display_offset, int x11_use_localhost,  x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
     int single_connection, u_int *display_numberp)      int single_connection, u_int *display_numberp, int **chanids)
 {  {
         Channel *nc = NULL;          Channel *nc = NULL;
         int display_number, sock;          int display_number, sock;
Line 2656 
Line 2715 
         }          }
   
         /* Allocate a channel for each socket. */          /* Allocate a channel for each socket. */
           if (chanids != NULL)
                   *chanids = xmalloc(sizeof(**chanids) * (num_socks + 1));
         for (n = 0; n < num_socks; n++) {          for (n = 0; n < num_socks; n++) {
                 sock = socks[n];                  sock = socks[n];
                 nc = channel_new("x11 listener",                  nc = channel_new("x11 listener",
Line 2663 
Line 2724 
                     CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,                      CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
                     0, "X11 inet listener", 1);                      0, "X11 inet listener", 1);
                 nc->single_connection = single_connection;                  nc->single_connection = single_connection;
                   if (*chanids != NULL)
                           (*chanids)[n] = nc->self;
         }          }
           if (*chanids != NULL)
                   (*chanids)[n] = -1;
   
         /* Return the display number for the DISPLAY environment variable. */          /* Return the display number for the DISPLAY environment variable. */
         *display_numberp = display_number;          *display_numberp = display_number;
Line 2861 
Line 2926 
  * This should be called in the client only.   * This should be called in the client only.
  */   */
 void  void
 x11_request_forwarding_with_spoofing(int client_session_id,  x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
     const char *proto, const char *data)      const char *proto, const char *data)
 {  {
         u_int data_len = (u_int) strlen(data) / 2;          u_int data_len = (u_int) strlen(data) / 2;
         u_int i, value, len;          u_int i, value;
         char *new_data;          char *new_data;
         int screen_number;          int screen_number;
         const char *cp;          const char *cp;
         u_int32_t rnd = 0;          u_int32_t rnd = 0;
   
         cp = getenv("DISPLAY");          if (x11_saved_display == NULL)
                   x11_saved_display = xstrdup(disp);
           else if (strcmp(disp, x11_saved_display) != 0) {
                   error("x11_request_forwarding_with_spoofing: different "
                       "$DISPLAY already forwarded");
                   return;
           }
   
           cp = disp;
           if (disp)
                   cp = strchr(disp, ':');
         if (cp)          if (cp)
                 cp = strchr(cp, ':');  
         if (cp)  
                 cp = strchr(cp, '.');                  cp = strchr(cp, '.');
         if (cp)          if (cp)
                 screen_number = atoi(cp + 1);                  screen_number = atoi(cp + 1);
         else          else
                 screen_number = 0;                  screen_number = 0;
   
         /* Save protocol name. */          if (x11_saved_proto == NULL) {
         x11_saved_proto = xstrdup(proto);                  /* Save protocol name. */
                   x11_saved_proto = xstrdup(proto);
         /*                  /*
          * Extract real authentication data and generate fake data of the                   * Extract real authentication data and generate fake data
          * same length.                   * of the same length.
          */                   */
         x11_saved_data = xmalloc(data_len);                  x11_saved_data = xmalloc(data_len);
         x11_fake_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 authentication data: %.100s", data);                                  fatal("x11_request_forwarding: bad "
                 if (i % 4 == 0)                                      "authentication data: %.100s", data);
                         rnd = arc4random();                          if (i % 4 == 0)
                 x11_saved_data[i] = value;                                  rnd = arc4random();
                 x11_fake_data[i] = rnd & 0xff;                          x11_saved_data[i] = value;
                 rnd >>= 8;                          x11_fake_data[i] = rnd & 0xff;
                           rnd >>= 8;
                   }
                   x11_saved_data_len = data_len;
                   x11_fake_data_len = data_len;
         }          }
         x11_saved_data_len = data_len;  
         x11_fake_data_len = data_len;  
   
         /* Convert the fake data into hex. */          /* Convert the fake data into hex. */
         len = 2 * data_len + 1;          new_data = tohex(x11_fake_data, data_len);
         new_data = xmalloc(len);  
         for (i = 0; i < data_len; i++)  
                 snprintf(new_data + 2 * i, len - 2 * i,  
                     "%02x", (u_char) x11_fake_data[i]);  
   
         /* Send the request packet. */          /* Send the request packet. */
         if (compat20) {          if (compat20) {

Legend:
Removed from v.1.210  
changed lines
  Added in v.1.210.2.3