[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.72.2.7 and 1.72.2.8

version 1.72.2.7, 2001/11/15 00:14:59 version 1.72.2.8, 2002/03/08 17:04:42
Line 13 
Line 13 
  * called by a name other than "ssh" or "Secure Shell".   * called by a name other than "ssh" or "Secure Shell".
  *   *
  * SSH2 support added by Markus Friedl.   * SSH2 support added by Markus Friedl.
  * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.   * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  * Copyright (c) 1999 Dug Song.  All rights reserved.   * Copyright (c) 1999 Dug Song.  All rights reserved.
  * Copyright (c) 1999 Theo de Raadt.  All rights reserved.   * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
  *   *
Line 54 
Line 54 
 #include "canohost.h"  #include "canohost.h"
 #include "key.h"  #include "key.h"
 #include "authfd.h"  #include "authfd.h"
   #include "pathnames.h"
   
   
 /* -- channel core */  /* -- channel core */
Line 145 
Line 146 
 {  {
         Channel *c;          Channel *c;
   
         if (id < 0 || id > channels_alloc) {          if (id < 0 || id >= channels_alloc) {
                 log("channel_lookup: %d: bad id", id);                  log("channel_lookup: %d: bad id", id);
                 return NULL;                  return NULL;
         }          }
Line 216 
Line 217 
   
         /* Do initial allocation if this is the first call. */          /* Do initial allocation if this is the first call. */
         if (channels_alloc == 0) {          if (channels_alloc == 0) {
                 chan_init();  
                 channels_alloc = 10;                  channels_alloc = 10;
                 channels = xmalloc(channels_alloc * sizeof(Channel *));                  channels = xmalloc(channels_alloc * sizeof(Channel *));
                 for (i = 0; i < channels_alloc; i++)                  for (i = 0; i < channels_alloc; i++)
Line 245 
Line 245 
         buffer_init(&c->input);          buffer_init(&c->input);
         buffer_init(&c->output);          buffer_init(&c->output);
         buffer_init(&c->extended);          buffer_init(&c->extended);
         chan_init_iostates(c);          c->ostate = CHAN_OUTPUT_OPEN;
           c->istate = CHAN_INPUT_OPEN;
           c->flags = 0;
         channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);          channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
         c->self = found;          c->self = found;
         c->type = type;          c->type = type;
Line 258 
Line 260 
         c->remote_name = remote_name;          c->remote_name = remote_name;
         c->remote_window = 0;          c->remote_window = 0;
         c->remote_maxpacket = 0;          c->remote_maxpacket = 0;
         c->cb_fn = NULL;  
         c->cb_arg = NULL;  
         c->cb_event = 0;  
         c->force_drain = 0;          c->force_drain = 0;
           c->single_connection = 0;
         c->detach_user = NULL;          c->detach_user = NULL;
           c->confirm = NULL;
         c->input_filter = NULL;          c->input_filter = NULL;
         debug("channel %d: new [%s]", found, remote_name);          debug("channel %d: new [%s]", found, remote_name);
         return c;          return c;
Line 361 
Line 362 
  */   */
   
 void  void
 channel_close_all()  channel_close_all(void)
 {  {
         int i;          int i;
   
Line 402 
Line 403 
  */   */
   
 int  int
 channel_not_very_much_buffered_data()  channel_not_very_much_buffered_data(void)
 {  {
         u_int i;          u_int i;
         Channel *c;          Channel *c;
Line 432 
Line 433 
 /* Returns true if any channel is still open. */  /* Returns true if any channel is still open. */
   
 int  int
 channel_still_open()  channel_still_open(void)
 {  {
         int i;          int i;
         Channel *c;          Channel *c;
Line 475 
Line 476 
 /* Returns the id of an open channel suitable for keepaliving */  /* Returns the id of an open channel suitable for keepaliving */
   
 int  int
 channel_find_open()  channel_find_open(void)
 {  {
         int i;          int i;
         Channel *c;          Channel *c;
Line 520 
Line 521 
  */   */
   
 char *  char *
 channel_open_message()  channel_open_message(void)
 {  {
         Buffer buffer;          Buffer buffer;
         Channel *c;          Channel *c;
Line 587 
Line 588 
 }  }
   
 void  void
 channel_request(int id, char *service, int wantconfirm)  channel_request_start(int local_id, char *service, int wantconfirm)
 {  {
         channel_request_start(id, service, wantconfirm);          Channel *c = channel_lookup(local_id);
         packet_send();  
         debug("channel request %d: %s", id, service) ;  
 }  
 void  
 channel_request_start(int id, char *service, int wantconfirm)  
 {  
         Channel *c = channel_lookup(id);  
         if (c == NULL) {          if (c == NULL) {
                 log("channel_request: %d: bad id", id);                  log("channel_request_start: %d: unknown channel id", local_id);
                 return;                  return;
         }          }
           debug("channel request %d: %s", local_id, service) ;
         packet_start(SSH2_MSG_CHANNEL_REQUEST);          packet_start(SSH2_MSG_CHANNEL_REQUEST);
         packet_put_int(c->remote_id);          packet_put_int(c->remote_id);
         packet_put_cstring(service);          packet_put_cstring(service);
         packet_put_char(wantconfirm);          packet_put_char(wantconfirm);
 }  }
 void  void
 channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg)  channel_register_confirm(int id, channel_callback_fn *fn)
 {  {
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
         if (c == NULL) {          if (c == NULL) {
                 log("channel_register_callback: %d: bad id", id);                  log("channel_register_comfirm: %d: bad id", id);
                 return;                  return;
         }          }
         c->cb_event = mtype;          c->confirm = fn;
         c->cb_fn = fn;  
         c->cb_arg = arg;  
 }  }
 void  void
 channel_register_cleanup(int id, channel_callback_fn *fn)  channel_register_cleanup(int id, channel_callback_fn *fn)
Line 651 
Line 644 
   
 void  void
 channel_set_fds(int id, int rfd, int wfd, int efd,  channel_set_fds(int id, int rfd, int wfd, int efd,
     int extusage, int nonblock)      int extusage, int nonblock, u_int window_max)
 {  {
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
         if (c == NULL || c->type != SSH_CHANNEL_LARVAL)          if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
                 fatal("channel_activate for non-larval channel %d.", id);                  fatal("channel_activate for non-larval channel %d.", id);
         channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);          channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
         c->type = SSH_CHANNEL_OPEN;          c->type = SSH_CHANNEL_OPEN;
         /* XXX window size? */          c->local_window = c->local_window_max = window_max;
         c->local_window = c->local_window_max = c->local_maxpacket * 2;  
         packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);          packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
         packet_put_int(c->remote_id);          packet_put_int(c->remote_id);
         packet_put_int(c->local_window);          packet_put_int(c->local_window);
Line 701 
Line 693 
 }  }
   
 static void  static void
 channel_pre_open_15(Channel *c, fd_set * readset, fd_set * writeset)  channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         /* test whether sockets are 'alive' for read/write */          u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
         if (c->istate == CHAN_INPUT_OPEN)  
                 if (buffer_len(&c->input) < packet_get_maxsize())  
                         FD_SET(c->sock, readset);  
         if (c->ostate == CHAN_OUTPUT_OPEN ||  
             c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {  
                 if (buffer_len(&c->output) > 0) {  
                         FD_SET(c->sock, writeset);  
                 } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {  
                         chan_obuf_empty(c);  
                 }  
         }  
 }  
   
 static void  
 channel_pre_open_20(Channel *c, fd_set * readset, fd_set * writeset)  
 {  
         if (c->istate == CHAN_INPUT_OPEN &&          if (c->istate == CHAN_INPUT_OPEN &&
             c->remote_window > 0 &&              limit > 0 &&
             buffer_len(&c->input) < c->remote_window)              buffer_len(&c->input) < limit)
                 FD_SET(c->rfd, readset);                  FD_SET(c->rfd, readset);
         if (c->ostate == CHAN_OUTPUT_OPEN ||          if (c->ostate == CHAN_OUTPUT_OPEN ||
             c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {              c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
Line 733 
Line 710 
                 }                  }
         }          }
         /** XXX check close conditions, too */          /** XXX check close conditions, too */
         if (c->efd != -1) {          if (compat20 && c->efd != -1) {
                 if (c->extended_usage == CHAN_EXTENDED_WRITE &&                  if (c->extended_usage == CHAN_EXTENDED_WRITE &&
                     buffer_len(&c->extended) > 0)                      buffer_len(&c->extended) > 0)
                         FD_SET(c->efd, writeset);                          FD_SET(c->efd, writeset);
Line 784 
Line 761 
                 return 0;                  return 0;
   
         /* Parse the lengths of variable-length fields. */          /* Parse the lengths of variable-length fields. */
         ucp = (u_char *) buffer_ptr(b);          ucp = buffer_ptr(b);
         if (ucp[0] == 0x42) {   /* Byte order MSB first. */          if (ucp[0] == 0x42) {   /* Byte order MSB first. */
                 proto_len = 256 * ucp[6] + ucp[7];                  proto_len = 256 * ucp[6] + ucp[7];
                 data_len = 256 * ucp[8] + ucp[9];                  data_len = 256 * ucp[8] + ucp[9];
Line 793 
Line 770 
                 data_len = ucp[8] + 256 * ucp[9];                  data_len = ucp[8] + 256 * ucp[9];
         } else {          } else {
                 debug("Initial X11 packet contains bad byte order byte: 0x%x",                  debug("Initial X11 packet contains bad byte order byte: 0x%x",
                       ucp[0]);                      ucp[0]);
                 return -1;                  return -1;
         }          }
   
Line 865 
Line 842 
   
         if (ret == 1) {          if (ret == 1) {
                 c->type = SSH_CHANNEL_OPEN;                  c->type = SSH_CHANNEL_OPEN;
                 if (compat20)                  channel_pre_open(c, readset, writeset);
                         channel_pre_open_20(c, readset, writeset);  
                 else  
                         channel_pre_open_15(c, readset, writeset);  
         } else if (ret == -1) {          } else if (ret == -1) {
                   log("X11 connection rejected because of wrong authentication.");
                 debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);                  debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
                 chan_read_failed(c);    /** force close? */                  chan_read_failed(c);
                 chan_write_failed(c);                  buffer_clear(&c->input);
                   chan_ibuf_empty(c);
                   buffer_clear(&c->output);
                   /* for proto v1, the peer will send an IEOF */
                   if (compat20)
                           chan_write_failed(c);
                   else
                           c->type = SSH_CHANNEL_OPEN;
                 debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);                  debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
         }          }
 }  }
Line 883 
Line 865 
 {  {
         u_char *p, *host;          u_char *p, *host;
         int len, have, i, found;          int len, have, i, found;
         char username[256];          char username[256];
         struct {          struct {
                 u_int8_t version;                  u_int8_t version;
                 u_int8_t command;                  u_int8_t command;
Line 930 
Line 912 
         host = inet_ntoa(s4_req.dest_addr);          host = inet_ntoa(s4_req.dest_addr);
         strlcpy(c->path, host, sizeof(c->path));          strlcpy(c->path, host, sizeof(c->path));
         c->host_port = ntohs(s4_req.dest_port);          c->host_port = ntohs(s4_req.dest_port);
   
         debug("channel %d: dynamic request: socks4 host %s port %u command %u",          debug("channel %d: dynamic request: socks4 host %s port %u command %u",
             c->self, host, c->host_port, s4_req.command);              c->self, host, c->host_port, s4_req.command);
   
Line 1002 
Line 984 
                 debug("X11 connection requested.");                  debug("X11 connection requested.");
                 addrlen = sizeof(addr);                  addrlen = sizeof(addr);
                 newsock = accept(c->sock, &addr, &addrlen);                  newsock = accept(c->sock, &addr, &addrlen);
                   if (c->single_connection) {
                           debug("single_connection: closing X11 listener.");
                           channel_close_fd(&c->sock);
                           chan_mark_dead(c);
                   }
                 if (newsock < 0) {                  if (newsock < 0) {
                         error("accept: %.100s", strerror(errno));                          error("accept: %.100s", strerror(errno));
                         return;                          return;
                 }                  }
                   set_nodelay(newsock);
                 remote_ipaddr = get_peer_ipaddr(newsock);                  remote_ipaddr = get_peer_ipaddr(newsock);
                 remote_port = get_peer_port(newsock);                  remote_port = get_peer_port(newsock);
                 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",                  snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
Line 1015 
Line 1003 
                     SSH_CHANNEL_OPENING, newsock, newsock, -1,                      SSH_CHANNEL_OPENING, newsock, newsock, -1,
                     c->local_window_max, c->local_maxpacket,                      c->local_window_max, c->local_maxpacket,
                     0, xstrdup(buf), 1);                      0, xstrdup(buf), 1);
                 if (nc == NULL) {  
                         close(newsock);  
                         xfree(remote_ipaddr);  
                         return;  
                 }  
                 if (compat20) {                  if (compat20) {
                         packet_start(SSH2_MSG_CHANNEL_OPEN);                          packet_start(SSH2_MSG_CHANNEL_OPEN);
                         packet_put_cstring("x11");                          packet_put_cstring("x11");
                         packet_put_int(nc->self);                          packet_put_int(nc->self);
                         packet_put_int(c->local_window_max);                          packet_put_int(nc->local_window_max);
                         packet_put_int(c->local_maxpacket);                          packet_put_int(nc->local_maxpacket);
                         /* originator ipaddr and port */                          /* originator ipaddr and port */
                         packet_put_cstring(remote_ipaddr);                          packet_put_cstring(remote_ipaddr);
                         if (datafellows & SSH_BUG_X11FWD) {                          if (datafellows & SSH_BUG_X11FWD) {
Line 1133 
Line 1116 
                         error("accept: %.100s", strerror(errno));                          error("accept: %.100s", strerror(errno));
                         return;                          return;
                 }                  }
                   set_nodelay(newsock);
                 nc = channel_new(rtype,                  nc = channel_new(rtype,
                     nextstate, newsock, newsock, -1,                      nextstate, newsock, newsock, -1,
                     c->local_window_max, c->local_maxpacket,                      c->local_window_max, c->local_maxpacket,
                     0, xstrdup(rtype), 1);                      0, xstrdup(rtype), 1);
                 if (nc == NULL) {  
                         error("channel_post_port_listener: no new channel:");  
                         close(newsock);  
                         return;  
                 }  
                 nc->listening_port = c->listening_port;                  nc->listening_port = c->listening_port;
                 nc->host_port = c->host_port;                  nc->host_port = c->host_port;
                 strlcpy(nc->path, c->path, sizeof(nc->path));                  strlcpy(nc->path, c->path, sizeof(nc->path));
Line 1184 
Line 1163 
                     SSH_CHANNEL_OPENING, newsock, newsock, -1,                      SSH_CHANNEL_OPENING, newsock, newsock, -1,
                     c->local_window_max, c->local_maxpacket,                      c->local_window_max, c->local_maxpacket,
                     0, name, 1);                      0, name, 1);
                 if (nc == NULL) {  
                         error("channel_post_auth_listener: channel_new failed");  
                         xfree(name);  
                         close(newsock);  
                 }  
                 if (compat20) {                  if (compat20) {
                         packet_start(SSH2_MSG_CHANNEL_OPEN);                          packet_start(SSH2_MSG_CHANNEL_OPEN);
                         packet_put_cstring("auth-agent@openssh.com");                          packet_put_cstring("auth-agent@openssh.com");
Line 1210 
Line 1184 
         socklen_t sz = sizeof(err);          socklen_t sz = sizeof(err);
   
         if (FD_ISSET(c->sock, writeset)) {          if (FD_ISSET(c->sock, writeset)) {
                 if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err,                  if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
                     &sz) < 0) {  
                         err = errno;                          err = errno;
                         error("getsockopt SO_ERROR failed");                          error("getsockopt SO_ERROR failed");
                 }                  }
Line 1269 
Line 1242 
                                 chan_mark_dead(c);                                  chan_mark_dead(c);
                                 return -1;                                  return -1;
                         } else if (compat13) {                          } else if (compat13) {
                                 buffer_consume(&c->output, buffer_len(&c->output));                                  buffer_clear(&c->output);
                                 c->type = SSH_CHANNEL_INPUT_DRAINING;                                  c->type = SSH_CHANNEL_INPUT_DRAINING;
                                 debug("channel %d: input draining.", c->self);                                  debug("channel %d: input draining.", c->self);
                         } else {                          } else {
Line 1277 
Line 1250 
                         }                          }
                         return -1;                          return -1;
                 }                  }
                 if(c->input_filter != NULL) {                  if (c->input_filter != NULL) {
                         if (c->input_filter(c, buf, len) == -1) {                          if (c->input_filter(c, buf, len) == -1) {
                                 debug("channel %d: filter stops", c->self);                                  debug("channel %d: filter stops", c->self);
                                 chan_read_failed(c);                                  chan_read_failed(c);
Line 1311 
Line 1284 
                                 chan_mark_dead(c);                                  chan_mark_dead(c);
                                 return -1;                                  return -1;
                         } else if (compat13) {                          } else if (compat13) {
                                 buffer_consume(&c->output, buffer_len(&c->output));                                  buffer_clear(&c->output);
                                 debug("channel %d: input draining.", c->self);                                  debug("channel %d: input draining.", c->self);
                                 c->type = SSH_CHANNEL_INPUT_DRAINING;                                  c->type = SSH_CHANNEL_INPUT_DRAINING;
                         } else {                          } else {
Line 1368 
Line 1341 
                     FD_ISSET(c->efd, readset)) {                      FD_ISSET(c->efd, readset)) {
                         len = read(c->efd, buf, sizeof(buf));                          len = read(c->efd, buf, sizeof(buf));
                         debug2("channel %d: read %d from efd %d",                          debug2("channel %d: read %d from efd %d",
                              c->self, len, c->efd);                              c->self, len, c->efd);
                         if (len < 0 && (errno == EINTR || errno == EAGAIN))                          if (len < 0 && (errno == EINTR || errno == EAGAIN))
                                 return 1;                                  return 1;
                         if (len <= 0) {                          if (len <= 0) {
Line 1403 
Line 1376 
 }  }
   
 static void  static void
 channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset)  channel_post_open(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         if (c->delayed)          if (c->delayed)
                 return;                  return;
         channel_handle_rfd(c, readset, writeset);          channel_handle_rfd(c, readset, writeset);
         channel_handle_wfd(c, readset, writeset);          channel_handle_wfd(c, readset, writeset);
 }          if (!compat20)
   
 static void  
 channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset)  
 {  
         if (c->delayed)  
                 return;                  return;
         channel_handle_rfd(c, readset, writeset);  
         channel_handle_wfd(c, readset, writeset);  
         channel_handle_efd(c, readset, writeset);          channel_handle_efd(c, readset, writeset);
   
         channel_check_window(c);          channel_check_window(c);
 }  }
   
Line 1432 
Line 1397 
                 len = write(c->sock, buffer_ptr(&c->output),                  len = write(c->sock, buffer_ptr(&c->output),
                             buffer_len(&c->output));                              buffer_len(&c->output));
                 if (len <= 0)                  if (len <= 0)
                         buffer_consume(&c->output, buffer_len(&c->output));                          buffer_clear(&c->output);
                 else                  else
                         buffer_consume(&c->output, len);                          buffer_consume(&c->output, len);
         }          }
Line 1441 
Line 1406 
 static void  static void
 channel_handler_init_20(void)  channel_handler_init_20(void)
 {  {
         channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open_20;          channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open;
         channel_pre[SSH_CHANNEL_X11_OPEN] =             &channel_pre_x11_open;          channel_pre[SSH_CHANNEL_X11_OPEN] =             &channel_pre_x11_open;
         channel_pre[SSH_CHANNEL_PORT_LISTENER] =        &channel_pre_listener;          channel_pre[SSH_CHANNEL_PORT_LISTENER] =        &channel_pre_listener;
         channel_pre[SSH_CHANNEL_RPORT_LISTENER] =       &channel_pre_listener;          channel_pre[SSH_CHANNEL_RPORT_LISTENER] =       &channel_pre_listener;
Line 1450 
Line 1415 
         channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;          channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;
         channel_pre[SSH_CHANNEL_DYNAMIC] =              &channel_pre_dynamic;          channel_pre[SSH_CHANNEL_DYNAMIC] =              &channel_pre_dynamic;
   
         channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open_2;          channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open;
         channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;          channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;
         channel_post[SSH_CHANNEL_RPORT_LISTENER] =      &channel_post_port_listener;          channel_post[SSH_CHANNEL_RPORT_LISTENER] =      &channel_post_port_listener;
         channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;          channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;
         channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;          channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;
         channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;          channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;
         channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open_2;          channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open;
 }  }
   
 static void  static void
Line 1472 
Line 1437 
         channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;          channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;
         channel_pre[SSH_CHANNEL_DYNAMIC] =              &channel_pre_dynamic;          channel_pre[SSH_CHANNEL_DYNAMIC] =              &channel_pre_dynamic;
   
         channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open_1;          channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open;
         channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;          channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;
         channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;          channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;
         channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;          channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;
         channel_post[SSH_CHANNEL_OUTPUT_DRAINING] =     &channel_post_output_drain_13;          channel_post[SSH_CHANNEL_OUTPUT_DRAINING] =     &channel_post_output_drain_13;
         channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;          channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;
         channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open_1;          channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open;
 }  }
   
 static void  static void
 channel_handler_init_15(void)  channel_handler_init_15(void)
 {  {
         channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open_15;          channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open;
         channel_pre[SSH_CHANNEL_X11_OPEN] =             &channel_pre_x11_open;          channel_pre[SSH_CHANNEL_X11_OPEN] =             &channel_pre_x11_open;
         channel_pre[SSH_CHANNEL_X11_LISTENER] =         &channel_pre_listener;          channel_pre[SSH_CHANNEL_X11_LISTENER] =         &channel_pre_listener;
         channel_pre[SSH_CHANNEL_PORT_LISTENER] =        &channel_pre_listener;          channel_pre[SSH_CHANNEL_PORT_LISTENER] =        &channel_pre_listener;
Line 1495 
Line 1460 
         channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;          channel_post[SSH_CHANNEL_X11_LISTENER] =        &channel_post_x11_listener;
         channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;          channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;
         channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;          channel_post[SSH_CHANNEL_AUTH_SOCKET] =         &channel_post_auth_listener;
         channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open_1;          channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open;
         channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;          channel_post[SSH_CHANNEL_CONNECTING] =          &channel_post_connecting;
         channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open_1;          channel_post[SSH_CHANNEL_DYNAMIC] =             &channel_post_open;
 }  }
   
 static void  static void
 channel_handler_init(void)  channel_handler_init(void)
 {  {
         int i;          int i;
         for(i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {          for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
                 channel_pre[i] = NULL;                  channel_pre[i] = NULL;
                 channel_post[i] = NULL;                  channel_post[i] = NULL;
         }          }
Line 1601 
Line 1566 
 /* If there is data to send to the connection, enqueue some of it now. */  /* If there is data to send to the connection, enqueue some of it now. */
   
 void  void
 channel_output_poll()  channel_output_poll(void)
 {  {
         int len, i;          int len, i;
         Channel *c;          Channel *c;
Line 1699 
Line 1664 
 /* -- protocol input */  /* -- protocol input */
   
 void  void
 channel_input_data(int type, int plen, void *ctxt)  channel_input_data(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;          int id;
         char *data;          char *data;
Line 1723 
Line 1688 
   
         /* Get the data. */          /* Get the data. */
         data = packet_get_string(&data_len);          data = packet_get_string(&data_len);
         packet_done();  
   
         if (compat20){          if (compat20) {
                 if (data_len > c->local_maxpacket) {                  if (data_len > c->local_maxpacket) {
                         log("channel %d: rcvd big packet %d, maxpack %d",                          log("channel %d: rcvd big packet %d, maxpack %d",
                             c->self, data_len, c->local_maxpacket);                              c->self, data_len, c->local_maxpacket);
Line 1737 
Line 1701 
                         return;                          return;
                 }                  }
                 c->local_window -= data_len;                  c->local_window -= data_len;
         }else{  
                 packet_integrity_check(plen, 4 + 4 + data_len, type);  
         }          }
           packet_check_eom();
         buffer_append(&c->output, data, data_len);          buffer_append(&c->output, data, data_len);
         xfree(data);          xfree(data);
 }  }
   
 void  void
 channel_input_extended_data(int type, int plen, void *ctxt)  channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;          int id;
         int tcode;          int tcode;
Line 1771 
Line 1734 
                 return;                  return;
         }          }
         data = packet_get_string(&data_len);          data = packet_get_string(&data_len);
         packet_done();          packet_check_eom();
         if (data_len > c->local_window) {          if (data_len > c->local_window) {
                 log("channel %d: rcvd too much extended_data %d, win %d",                  log("channel %d: rcvd too much extended_data %d, win %d",
                     c->self, data_len, c->local_window);                      c->self, data_len, c->local_window);
Line 1785 
Line 1748 
 }  }
   
 void  void
 channel_input_ieof(int type, int plen, void *ctxt)  channel_input_ieof(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;          int id;
         Channel *c;          Channel *c;
   
         packet_integrity_check(plen, 4, type);  
   
         id = packet_get_int();          id = packet_get_int();
           packet_check_eom();
         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);
         chan_rcvd_ieof(c);          chan_rcvd_ieof(c);
   
         /* XXX force input close */          /* XXX force input close */
         if (c->force_drain) {          if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {
                 debug("channel %d: FORCE input drain", c->self);                  debug("channel %d: FORCE input drain", c->self);
                 c->istate = CHAN_INPUT_WAIT_DRAIN;                  c->istate = CHAN_INPUT_WAIT_DRAIN;
                   if (buffer_len(&c->input) == 0)
                           chan_ibuf_empty(c);
         }          }
   
 }  }
   
 void  void
 channel_input_close(int type, int plen, void *ctxt)  channel_input_close(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;          int id;
         Channel *c;          Channel *c;
   
         packet_integrity_check(plen, 4, type);  
   
         id = packet_get_int();          id = packet_get_int();
           packet_check_eom();
         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);
Line 1839 
Line 1802 
                  * Not a closed channel - mark it as draining, which will                   * Not a closed channel - mark it as draining, which will
                  * cause it to be freed later.                   * cause it to be freed later.
                  */                   */
                 buffer_consume(&c->input, buffer_len(&c->input));                  buffer_clear(&c->input);
                 c->type = SSH_CHANNEL_OUTPUT_DRAINING;                  c->type = SSH_CHANNEL_OUTPUT_DRAINING;
         }          }
 }  }
   
 /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */  /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
 void  void
 channel_input_oclose(int type, int plen, void *ctxt)  channel_input_oclose(int type, u_int32_t seq, void *ctxt)
 {  {
         int id = packet_get_int();          int id = packet_get_int();
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
         packet_integrity_check(plen, 4, type);  
           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);
         chan_rcvd_oclose(c);          chan_rcvd_oclose(c);
 }  }
   
 void  void
 channel_input_close_confirmation(int type, int plen, void *ctxt)  channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt)
 {  {
         int id = packet_get_int();          int id = packet_get_int();
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         packet_done();          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);
Line 1873 
Line 1837 
 }  }
   
 void  void
 channel_input_open_confirmation(int type, int plen, void *ctxt)  channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
 {  {
         int id, remote_id;          int id, remote_id;
         Channel *c;          Channel *c;
   
         if (!compat20)  
                 packet_integrity_check(plen, 4 + 4, type);  
   
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
   
Line 1895 
Line 1856 
         if (compat20) {          if (compat20) {
                 c->remote_window = packet_get_int();                  c->remote_window = packet_get_int();
                 c->remote_maxpacket = packet_get_int();                  c->remote_maxpacket = packet_get_int();
                 packet_done();                  if (c->confirm) {
                 if (c->cb_fn != NULL && c->cb_event == type) {  
                         debug2("callback start");                          debug2("callback start");
                         c->cb_fn(c->self, c->cb_arg);                          c->confirm(c->self, NULL);
                         debug2("callback done");                          debug2("callback done");
                 }                  }
                 debug("channel %d: open confirm rwindow %d rmax %d", c->self,                  debug("channel %d: open confirm rwindow %d rmax %d", c->self,
                     c->remote_window, c->remote_maxpacket);                      c->remote_window, c->remote_maxpacket);
         }          }
           packet_check_eom();
 }  }
   
 static char *  static char *
 reason2txt(int reason)  reason2txt(int reason)
 {  {
         switch(reason) {          switch (reason) {
         case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:          case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:
                 return "administratively prohibited";                  return "administratively prohibited";
         case SSH2_OPEN_CONNECT_FAILED:          case SSH2_OPEN_CONNECT_FAILED:
Line 1923 
Line 1884 
 }  }
   
 void  void
 channel_input_open_failure(int type, int plen, void *ctxt)  channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
 {  {
         int id, reason;          int id, reason;
         char *msg = NULL, *lang = NULL;          char *msg = NULL, *lang = NULL;
         Channel *c;          Channel *c;
   
         if (!compat20)  
                 packet_integrity_check(plen, 4, type);  
   
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
   
Line 1944 
Line 1902 
                         msg  = packet_get_string(NULL);                          msg  = packet_get_string(NULL);
                         lang = packet_get_string(NULL);                          lang = packet_get_string(NULL);
                 }                  }
                 packet_done();  
                 log("channel %d: open failed: %s%s%s", id,                  log("channel %d: open failed: %s%s%s", id,
                     reason2txt(reason), msg ? ": ": "", msg ? msg : "");                      reason2txt(reason), msg ? ": ": "", msg ? msg : "");
                 if (msg != NULL)                  if (msg != NULL)
Line 1952 
Line 1909 
                 if (lang != NULL)                  if (lang != NULL)
                         xfree(lang);                          xfree(lang);
         }          }
           packet_check_eom();
         /* Free the channel.  This will also close the socket. */          /* Free the channel.  This will also close the socket. */
         channel_free(c);          channel_free(c);
 }  }
   
 void  void
 channel_input_channel_request(int type, int plen, void *ctxt)  channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;  
         Channel *c;          Channel *c;
   
         id = packet_get_int();  
         c = channel_lookup(id);  
   
         if (c == NULL ||  
             (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_LARVAL))  
                 packet_disconnect("Received request for "  
                     "non-open channel %d.", id);  
         if (c->cb_fn != NULL && c->cb_event == type) {  
                 debug2("callback start");  
                 c->cb_fn(c->self, c->cb_arg);  
                 debug2("callback done");  
         } else {  
                 char *service = packet_get_string(NULL);  
                 debug("channel %d: rcvd request for %s", c->self, service);  
                 debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event);  
                 xfree(service);  
         }  
 }  
   
 void  
 channel_input_window_adjust(int type, int plen, void *ctxt)  
 {  
         Channel *c;  
         int id, adjust;          int id, adjust;
   
         if (!compat20)          if (!compat20)
Line 2000 
Line 1933 
                 return;                  return;
         }          }
         adjust = packet_get_int();          adjust = packet_get_int();
         packet_done();          packet_check_eom();
         debug2("channel %d: rcvd adjust %d", id, adjust);          debug2("channel %d: rcvd adjust %d", id, adjust);
         c->remote_window += adjust;          c->remote_window += adjust;
 }  }
   
 void  void
 channel_input_port_open(int type, int plen, void *ctxt)  channel_input_port_open(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c = NULL;          Channel *c = NULL;
         u_short host_port;          u_short host_port;
Line 2022 
Line 1955 
         } else {          } else {
                 originator_string = xstrdup("unknown (remote did not supply name)");                  originator_string = xstrdup("unknown (remote did not supply name)");
         }          }
         packet_done();          packet_check_eom();
         sock = channel_connect_to(host, host_port);          sock = channel_connect_to(host, host_port);
         if (sock != -1) {          if (sock != -1) {
                 c = channel_new("connected socket",                  c = channel_new("connected socket",
                     SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,                      SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
                     originator_string, 1);                      originator_string, 1);
                 if (c == NULL) {                  c->remote_id = remote_id;
                         error("channel_input_port_open: channel_new failed");  
                         close(sock);  
                 } else {  
                         c->remote_id = remote_id;  
                 }  
         }          }
         if (c == NULL) {          if (c == NULL) {
                 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);                  packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
Line 2052 
Line 1980 
         IPv4or6 = af;          IPv4or6 = af;
 }  }
   
 /*  static int
  * Initiate forwarding of connections to local port "port" through the secure  channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port,
  * channel to host:port from remote side.      const char *host_to_connect, u_short port_to_connect, int gateway_ports)
  */  
 int  
 channel_request_local_forwarding(u_short listen_port, const char *host_to_connect,  
     u_short port_to_connect, int gateway_ports)  
 {  {
         return channel_request_forwarding(  
             NULL, listen_port,  
             host_to_connect, port_to_connect,  
             gateway_ports, /*remote_fwd*/ 0);  
 }  
   
 /*  
  * If 'remote_fwd' is true we have a '-R style' listener for protocol 2  
  * (SSH_CHANNEL_RPORT_LISTENER).  
  */  
 int  
 channel_request_forwarding(  
     const char *listen_address, u_short listen_port,  
     const char *host_to_connect, u_short port_to_connect,  
     int gateway_ports, int remote_fwd)  
 {  
         Channel *c;          Channel *c;
         int success, sock, on = 1, type;          int success, sock, on = 1;
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];  
         const char *host;          const char *host;
           char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         struct linger linger;          struct linger linger;
   
         success = 0;          success = 0;
           host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
               listen_addr : host_to_connect;
   
         if (remote_fwd) {          if (host == NULL) {
                 host = listen_address;                  error("No forward host name.");
                 type = SSH_CHANNEL_RPORT_LISTENER;                  return success;
         } else {  
                 host = host_to_connect;  
                 type = SSH_CHANNEL_PORT_LISTENER;  
         }          }
   
         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 success;
         }          }
   
         /* XXX listen_address is currently ignored */  
         /*          /*
          * 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
Line 2116 
Line 2021 
                         continue;                          continue;
                 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),                  if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
                     strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {                      strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                         error("channel_request_forwarding: getnameinfo failed");                          error("channel_setup_fwd_listener: getnameinfo failed");
                         continue;                          continue;
                 }                  }
                 /* Create a port to listen for the host. */                  /* Create a port to listen for the host. */
Line 2130 
Line 2035 
                  * Set socket options.  We would like the socket to disappear                   * Set socket options.  We would like the socket to disappear
                  * as soon as it has been closed for whatever reason.                   * as soon as it has been closed for whatever reason.
                  */                   */
                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));                  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
                 linger.l_onoff = 1;                  linger.l_onoff = 1;
                 linger.l_linger = 5;                  linger.l_linger = 5;
                 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));                  setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
                 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. */                  /* Bind the socket to the address. */
Line 2153 
Line 2058 
                 c = channel_new("port listener", type, sock, sock, -1,                  c = channel_new("port listener", type, sock, sock, -1,
                     CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,                      CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
                     0, xstrdup("port listener"), 1);                      0, xstrdup("port listener"), 1);
                 if (c == NULL) {  
                         error("channel_request_forwarding: channel_new failed");  
                         close(sock);  
                         continue;  
                 }  
                 strlcpy(c->path, host, sizeof(c->path));                  strlcpy(c->path, host, sizeof(c->path));
                 c->host_port = port_to_connect;                  c->host_port = port_to_connect;
                 c->listening_port = listen_port;                  c->listening_port = listen_port;
                 success = 1;                  success = 1;
         }          }
         if (success == 0)          if (success == 0)
                 error("channel_request_forwarding: cannot listen to port: %d",                  error("channel_setup_fwd_listener: cannot listen to port: %d",
                     listen_port);                      listen_port);
         freeaddrinfo(aitop);          freeaddrinfo(aitop);
         return success;          return success;
 }  }
   
   /* protocol local port fwd, used by ssh (and sshd in v1) */
   int
   channel_setup_local_fwd_listener(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);
   }
   
   /* 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)
   {
           return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
               listen_address, listen_port, NULL, 0, gateway_ports);
   }
   
 /*  /*
  * Initiate forwarding of connections to port "port" on remote host through   * Initiate forwarding of connections to port "port" on remote host through
  * the secure channel to host:port from local side.   * the secure channel to host:port from local side.
Line 2179 
Line 2097 
 channel_request_remote_forwarding(u_short listen_port,  channel_request_remote_forwarding(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 payload_len, type, success = 0;          int type, success = 0;
   
         /* Record locally that connection to this host/port is permitted. */          /* Record locally that connection to this host/port is permitted. */
         if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)          if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
Line 2206 
Line 2124 
                 packet_write_wait();                  packet_write_wait();
   
                 /* Wait for response from the remote side. */                  /* Wait for response from the remote side. */
                 type = packet_read(&payload_len);                  type = packet_read();
                 switch (type) {                  switch (type) {
                 case SSH_SMSG_SUCCESS:                  case SSH_SMSG_SUCCESS:
                         success = 1;                          success = 1;
Line 2253 
Line 2171 
                 packet_disconnect("Requested forwarding of port %d but user is not root.",                  packet_disconnect("Requested forwarding of port %d but user is not root.",
                                   port);                                    port);
         /* Initiate forwarding */          /* Initiate forwarding */
         channel_request_local_forwarding(port, hostname, host_port, gateway_ports);          channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
   
         /* Free the argument string. */          /* Free the argument string. */
         xfree(hostname);          xfree(hostname);
Line 2265 
Line 2183 
  * 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.
  */   */
 void  void
 channel_permit_all_opens()  channel_permit_all_opens(void)
 {  {
         if (num_permitted_opens == 0)          if (num_permitted_opens == 0)
                 all_opens_permitted = 1;                  all_opens_permitted = 1;
Line 2346 
Line 2264 
                 return -1;                  return -1;
         }          }
         /* success */          /* success */
           set_nodelay(sock);
         return sock;          return sock;
 }  }
   
Line 2390 
Line 2309 
   
 /*  /*
  * Creates an internet domain socket for listening for X11 connections.   * Creates an internet domain socket for listening for X11 connections.
  * Returns a suitable value for the DISPLAY variable, or NULL if an error   * Returns a suitable display number for the DISPLAY variable, or -1 if
  * occurs.   * an error occurs.
  */   */
 char *  int
 x11_create_display_inet(int screen_number, int x11_display_offset)  x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
       int single_connection)
 {  {
           Channel *nc = NULL;
         int display_number, sock;          int display_number, sock;
         u_short port;          u_short port;
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         char strport[NI_MAXSERV];          char strport[NI_MAXSERV];
         int gaierr, n, num_socks = 0, socks[NUM_SOCKS];          int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
         char display[512];  
         char hostname[MAXHOSTNAMELEN];  
   
         for (display_number = x11_display_offset;          for (display_number = x11_display_offset;
              display_number < MAX_DISPLAYS;              display_number < MAX_DISPLAYS;
              display_number++) {              display_number++) {
                 port = 6000 + display_number;                  port = 6000 + display_number;
                 memset(&hints, 0, sizeof(hints));                  memset(&hints, 0, sizeof(hints));
                 hints.ai_family = IPv4or6;                  hints.ai_family = IPv4or6;
                 hints.ai_flags = AI_PASSIVE;            /* XXX loopback only ? */                  hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
                 hints.ai_socktype = SOCK_STREAM;                  hints.ai_socktype = SOCK_STREAM;
                 snprintf(strport, sizeof strport, "%d", port);                  snprintf(strport, sizeof strport, "%d", port);
                 if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {                  if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
                         error("getaddrinfo: %.100s", gai_strerror(gaierr));                          error("getaddrinfo: %.100s", gai_strerror(gaierr));
                         return NULL;                          return -1;
                 }                  }
                 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 2423 
Line 2342 
                         sock = socket(ai->ai_family, SOCK_STREAM, 0);                          sock = socket(ai->ai_family, SOCK_STREAM, 0);
                         if (sock < 0) {                          if (sock < 0) {
                                 error("socket: %.100s", strerror(errno));                                  error("socket: %.100s", strerror(errno));
                                 return NULL;                                  return -1;
                         }                          }
                         if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {                          if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                                 debug("bind port %d: %.100s", port, strerror(errno));                                  debug("bind port %d: %.100s", port, strerror(errno));
                                 shutdown(sock, SHUT_RDWR);  
                                 close(sock);                                  close(sock);
                                 for (n = 0; n < num_socks; n++) {                                  for (n = 0; n < num_socks; n++) {
                                         shutdown(socks[n], SHUT_RDWR);  
                                         close(socks[n]);                                          close(socks[n]);
                                 }                                  }
                                 num_socks = 0;                                  num_socks = 0;
Line 2446 
Line 2363 
         }          }
         if (display_number >= MAX_DISPLAYS) {          if (display_number >= MAX_DISPLAYS) {
                 error("Failed to allocate internet-domain X11 display socket.");                  error("Failed to allocate internet-domain X11 display socket.");
                 return NULL;                  return -1;
         }          }
         /* Start listening for connections on the socket. */          /* Start listening for connections on the socket. */
         for (n = 0; n < num_socks; n++) {          for (n = 0; n < num_socks; n++) {
                 sock = socks[n];                  sock = socks[n];
                 if (listen(sock, 5) < 0) {                  if (listen(sock, 5) < 0) {
                         error("listen: %.100s", strerror(errno));                          error("listen: %.100s", strerror(errno));
                         shutdown(sock, SHUT_RDWR);  
                         close(sock);                          close(sock);
                         return NULL;                          return -1;
                 }                  }
         }          }
   
         /* Set up a suitable value for the DISPLAY variable. */  
         if (gethostname(hostname, sizeof(hostname)) < 0)  
                 fatal("gethostname: %.100s", strerror(errno));  
         snprintf(display, sizeof display, "%.400s:%d.%d", hostname,  
                  display_number, screen_number);  
   
         /* Allocate a channel for each socket. */          /* Allocate a channel for each socket. */
         for (n = 0; n < num_socks; n++) {          for (n = 0; n < num_socks; n++) {
                 sock = socks[n];                  sock = socks[n];
                 (void) channel_new("x11 listener",                  nc = channel_new("x11 listener",
                     SSH_CHANNEL_X11_LISTENER, sock, sock, -1,                      SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
                     CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,                      CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
                     0, xstrdup("X11 inet listener"), 1);                      0, xstrdup("X11 inet listener"), 1);
                   nc->single_connection = single_connection;
         }          }
   
         /* Return a suitable value for the DISPLAY environment variable. */          /* Return the display number for the DISPLAY environment variable. */
         return xstrdup(display);          return display_number;
 }  }
   
 #ifndef X_UNIX_PATH  
 #define X_UNIX_PATH "/tmp/.X11-unix/X"  
 #endif  
   
 static int  static int
 connect_local_xsocket(u_int dnr)  connect_local_xsocket(u_int dnr)
 {  {
         static const char *const x_sockets[] = {  
                 X_UNIX_PATH "%u",  
                 "/var/X/.X11-unix/X" "%u",  
                 "/usr/spool/sockets/X11/" "%u",  
                 NULL  
         };  
         int sock;          int sock;
         struct sockaddr_un addr;          struct sockaddr_un addr;
         const char *const * path;  
   
         for (path = x_sockets; *path; ++path) {          sock = socket(AF_UNIX, SOCK_STREAM, 0);
                 sock = socket(AF_UNIX, SOCK_STREAM, 0);          if (sock < 0)
                 if (sock < 0)                  error("socket: %.100s", strerror(errno));
                         error("socket: %.100s", strerror(errno));          memset(&addr, 0, sizeof(addr));
                 memset(&addr, 0, sizeof(addr));          addr.sun_family = AF_UNIX;
                 addr.sun_family = AF_UNIX;          snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, dnr);
                 snprintf(addr.sun_path, sizeof addr.sun_path, *path, dnr);          if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0)
                 if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0)                  return sock;
                         return sock;          close(sock);
                 close(sock);  
         }  
         error("connect %.100s: %.100s", addr.sun_path, strerror(errno));          error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
         return -1;          return -1;
 }  }
Line 2540 
Line 2438 
                 /* Connect to the unix domain socket. */                  /* Connect to the unix domain socket. */
                 if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {                  if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {
                         error("Could not parse display number from DISPLAY: %.100s",                          error("Could not parse display number from DISPLAY: %.100s",
                               display);                              display);
                         return -1;                          return -1;
                 }                  }
                 /* Create a socket. */                  /* Create a socket. */
Line 2555 
Line 2453 
          * Connect to an inet socket.  The DISPLAY value is supposedly           * Connect to an inet socket.  The DISPLAY value is supposedly
          * hostname:d[.s], where hostname may also be numeric IP address.           * hostname:d[.s], where hostname may also be numeric IP address.
          */           */
         strncpy(buf, display, sizeof(buf));          strlcpy(buf, display, sizeof(buf));
         buf[sizeof(buf) - 1] = 0;  
         cp = strchr(buf, ':');          cp = strchr(buf, ':');
         if (!cp) {          if (!cp) {
                 error("Could not find ':' in DISPLAY: %.100s", display);                  error("Could not find ':' in DISPLAY: %.100s", display);
Line 2566 
Line 2463 
         /* buf now contains the host name.  But first we parse the display number. */          /* buf now contains the host name.  But first we parse the display number. */
         if (sscanf(cp + 1, "%d", &display_number) != 1) {          if (sscanf(cp + 1, "%d", &display_number) != 1) {
                 error("Could not parse display number from DISPLAY: %.100s",                  error("Could not parse display number from DISPLAY: %.100s",
                       display);                      display);
                 return -1;                  return -1;
         }          }
   
Line 2602 
Line 2499 
                     strerror(errno));                      strerror(errno));
                 return -1;                  return -1;
         }          }
           set_nodelay(sock);
         return sock;          return sock;
 }  }
   
Line 2612 
Line 2510 
  */   */
   
 void  void
 x11_input_open(int type, int plen, void *ctxt)  x11_input_open(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c = NULL;          Channel *c = NULL;
         int remote_id, sock = 0;          int remote_id, sock = 0;
Line 2627 
Line 2525 
         } else {          } else {
                 remote_host = xstrdup("unknown (remote did not supply name)");                  remote_host = xstrdup("unknown (remote did not supply name)");
         }          }
         packet_done();          packet_check_eom();
   
         /* Obtain a connection to the real X display. */          /* Obtain a connection to the real X display. */
         sock = x11_connect_display();          sock = x11_connect_display();
Line 2636 
Line 2534 
                 c = channel_new("connected x11 socket",                  c = channel_new("connected x11 socket",
                     SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,                      SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,
                     remote_host, 1);                      remote_host, 1);
                 if (c == NULL) {                  c->remote_id = remote_id;
                         error("x11_input_open: channel_new failed");                  c->force_drain = 1;
                         close(sock);  
                 } else {  
                         c->remote_id = remote_id;  
                         c->force_drain = 1;  
                 }  
         }          }
         if (c == NULL) {          if (c == NULL) {
                 /* Send refusal to the remote host. */                  /* Send refusal to the remote host. */
Line 2659 
Line 2552 
   
 /* dummy protocol handler that denies SSH-1 requests (agent/x11) */  /* dummy protocol handler that denies SSH-1 requests (agent/x11) */
 void  void
 deny_input_open(int type, int plen, void *ctxt)  deny_input_open(int type, u_int32_t seq, void *ctxt)
 {  {
         int rchan = packet_get_int();          int rchan = packet_get_int();
         switch(type){          switch (type) {
         case SSH_SMSG_AGENT_OPEN:          case SSH_SMSG_AGENT_OPEN:
                 error("Warning: ssh server tried agent forwarding.");                  error("Warning: ssh server tried agent forwarding.");
                 break;                  break;
Line 2670 
Line 2563 
                 error("Warning: ssh server tried X11 forwarding.");                  error("Warning: ssh server tried X11 forwarding.");
                 break;                  break;
         default:          default:
                 error("deny_input_open: type %d plen %d", type, plen);                  error("deny_input_open: type %d", type);
                 break;                  break;
         }          }
         error("Warning: this is probably a break in attempt by a malicious server.");          error("Warning: this is probably a break in attempt by a malicious server.");
Line 2754 
Line 2647 
 /* Sends a message to the server to request authentication fd forwarding. */  /* Sends a message to the server to request authentication fd forwarding. */
   
 void  void
 auth_request_forwarding()  auth_request_forwarding(void)
 {  {
         packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);          packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
         packet_send();          packet_send();
Line 2768 
Line 2661 
  */   */
   
 char *  char *
 auth_get_socket_name()  auth_get_socket_name(void)
 {  {
         return auth_sock_name;          return auth_sock_name;
 }  }
Line 2839 
Line 2732 
         /* Bind it to the name. */          /* Bind it to the name. */
         memset(&sunaddr, 0, sizeof(sunaddr));          memset(&sunaddr, 0, sizeof(sunaddr));
         sunaddr.sun_family = AF_UNIX;          sunaddr.sun_family = AF_UNIX;
         strncpy(sunaddr.sun_path, auth_sock_name,          strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
                 sizeof(sunaddr.sun_path));  
   
         if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)          if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
                 packet_disconnect("bind: %.100s", strerror(errno));                  packet_disconnect("bind: %.100s", strerror(errno));
Line 2857 
Line 2749 
             SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,              SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
             CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,              CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
             0, xstrdup("auth socket"), 1);              0, xstrdup("auth socket"), 1);
         if (nc == NULL) {  
                 error("auth_input_request_forwarding: channel_new failed");  
                 auth_sock_cleanup_proc(pw);  
                 fatal_remove_cleanup(auth_sock_cleanup_proc, pw);  
                 close(sock);  
                 return 0;  
         }  
         strlcpy(nc->path, auth_sock_name, sizeof(nc->path));          strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
         return 1;          return 1;
 }  }
Line 2871 
Line 2756 
 /* This is called to process an SSH_SMSG_AGENT_OPEN message. */  /* This is called to process an SSH_SMSG_AGENT_OPEN message. */
   
 void  void
 auth_input_open_request(int type, int plen, void *ctxt)  auth_input_open_request(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c = NULL;          Channel *c = NULL;
         int remote_id, sock;          int remote_id, sock;
         char *name;          char *name;
   
         packet_integrity_check(plen, 4, type);  
   
         /* Read the remote channel number from the message. */          /* Read the remote channel number from the message. */
         remote_id = packet_get_int();          remote_id = packet_get_int();
           packet_check_eom();
   
         /*          /*
          * Get a connection to the local authentication agent (this may again           * Get a connection to the local authentication agent (this may again
Line 2898 
Line 2782 
                 name = xstrdup("authentication agent connection");                  name = xstrdup("authentication agent connection");
                 c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,                  c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
                     -1, 0, 0, 0, name, 1);                      -1, 0, 0, 0, name, 1);
                 if (c == NULL) {                  c->remote_id = remote_id;
                         error("auth_input_open_request: channel_new failed");                  c->force_drain = 1;
                         xfree(name);  
                         close(sock);  
                 } else {  
                         c->remote_id = remote_id;  
                         c->force_drain = 1;  
                 }  
         }          }
         if (c == NULL) {          if (c == NULL) {
                 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);                  packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);

Legend:
Removed from v.1.72.2.7  
changed lines
  Added in v.1.72.2.8