[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.172 and 1.172.2.5

version 1.172, 2002/03/25 21:13:51 version 1.172.2.5, 2003/04/03 22:35:17
Line 46 
Line 46 
 #include "ssh2.h"  #include "ssh2.h"
 #include "packet.h"  #include "packet.h"
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "uidswap.h"  
 #include "log.h"  #include "log.h"
 #include "misc.h"  #include "misc.h"
 #include "channels.h"  #include "channels.h"
Line 129 
Line 128 
   
 #define NUM_SOCKS       10  #define NUM_SOCKS       10
   
 /* Name and directory of socket for authentication agent forwarding. */  
 static char *auth_sock_name = NULL;  
 static char *auth_sock_dir = NULL;  
   
 /* AF_UNSPEC or AF_INET or AF_INET6 */  /* AF_UNSPEC or AF_INET or AF_INET6 */
 static int IPv4or6 = AF_UNSPEC;  static int IPv4or6 = AF_UNSPEC;
   
Line 210 
Line 205 
   
 Channel *  Channel *
 channel_new(char *ctype, int type, int rfd, int wfd, int efd,  channel_new(char *ctype, int type, int rfd, int wfd, int efd,
     int window, int maxpack, int extusage, char *remote_name, int nonblock)      u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
 {  {
         int i, found;          int i, found;
         Channel *c;          Channel *c;
Line 234 
Line 229 
                 /* There are no free slots.  Take last+1 slot and expand the array.  */                  /* There are no free slots.  Take last+1 slot and expand the array.  */
                 found = channels_alloc;                  found = channels_alloc;
                 channels_alloc += 10;                  channels_alloc += 10;
                   if (channels_alloc > 10000)
                           fatal("channel_new: internal error: channels_alloc %d "
                               "too big.", channels_alloc);
                 debug2("channel: expanding %d", channels_alloc);                  debug2("channel: expanding %d", channels_alloc);
                 channels = xrealloc(channels, channels_alloc * sizeof(Channel *));                  channels = xrealloc(channels, channels_alloc * sizeof(Channel *));
                 for (i = found; i < channels_alloc; i++)                  for (i = found; i < channels_alloc; i++)
Line 414 
Line 412 
 #if 0  #if 0
                         if (!compat20 &&                          if (!compat20 &&
                             buffer_len(&c->input) > packet_get_maxsize()) {                              buffer_len(&c->input) > packet_get_maxsize()) {
                                 debug("channel %d: big input buffer %d",                                  debug2("channel %d: big input buffer %d",
                                     c->self, buffer_len(&c->input));                                      c->self, buffer_len(&c->input));
                                 return 0;                                  return 0;
                         }                          }
 #endif  #endif
                         if (buffer_len(&c->output) > packet_get_maxsize()) {                          if (buffer_len(&c->output) > packet_get_maxsize()) {
                                 debug("channel %d: big output buffer %d > %d",                                  debug2("channel %d: big output buffer %d > %d",
                                     c->self, buffer_len(&c->output),                                      c->self, buffer_len(&c->output),
                                     packet_get_maxsize());                                      packet_get_maxsize());
                                 return 0;                                  return 0;
Line 574 
Line 572 
 channel_send_open(int id)  channel_send_open(int id)
 {  {
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         if (c == NULL) {          if (c == NULL) {
                 log("channel_send_open: %d: bad id", id);                  log("channel_send_open: %d: bad id", id);
                 return;                  return;
         }          }
         debug("send channel open %d", id);          debug2("channel %d: send open", id);
         packet_start(SSH2_MSG_CHANNEL_OPEN);          packet_start(SSH2_MSG_CHANNEL_OPEN);
         packet_put_cstring(c->ctype);          packet_put_cstring(c->ctype);
         packet_put_int(c->self);          packet_put_int(c->self);
Line 588 
Line 587 
 }  }
   
 void  void
 channel_request_start(int local_id, char *service, int wantconfirm)  channel_request_start(int id, char *service, int wantconfirm)
 {  {
         Channel *c = channel_lookup(local_id);          Channel *c = channel_lookup(id);
   
         if (c == NULL) {          if (c == NULL) {
                 log("channel_request_start: %d: unknown channel id", local_id);                  log("channel_request_start: %d: unknown channel id", id);
                 return;                  return;
         }          }
         debug("channel request %d: %s", local_id, service) ;          debug("channel %d: request %s", 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);
Line 605 
Line 605 
 channel_register_confirm(int id, channel_callback_fn *fn)  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_comfirm: %d: bad id", id);                  log("channel_register_comfirm: %d: bad id", id);
                 return;                  return;
Line 615 
Line 616 
 channel_register_cleanup(int id, channel_callback_fn *fn)  channel_register_cleanup(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_cleanup: %d: bad id", id);                  log("channel_register_cleanup: %d: bad id", id);
                 return;                  return;
Line 625 
Line 627 
 channel_cancel_cleanup(int id)  channel_cancel_cleanup(int id)
 {  {
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         if (c == NULL) {          if (c == NULL) {
                 log("channel_cancel_cleanup: %d: bad id", id);                  log("channel_cancel_cleanup: %d: bad id", id);
                 return;                  return;
Line 635 
Line 638 
 channel_register_filter(int id, channel_filter_fn *fn)  channel_register_filter(int id, channel_filter_fn *fn)
 {  {
         Channel *c = channel_lookup(id);          Channel *c = channel_lookup(id);
   
         if (c == NULL) {          if (c == NULL) {
                 log("channel_register_filter: %d: bad id", id);                  log("channel_register_filter: %d: bad id", id);
                 return;                  return;
Line 647 
Line 651 
     int extusage, int nonblock, u_int window_max)      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);
Line 707 
Line 712 
                         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 817 
Line 822 
 channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)  channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         int ret = x11_open_helper(&c->output);          int ret = x11_open_helper(&c->output);
   
         if (ret == 1) {          if (ret == 1) {
                 /* Start normal processing for the channel. */                  /* Start normal processing for the channel. */
                 c->type = SSH_CHANNEL_OPEN;                  c->type = SSH_CHANNEL_OPEN;
Line 868 
Line 874 
 static int  static int
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)  channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         u_char *p, *host;          char *p, *host;
         int len, have, i, found;          int len, have, i, found;
         char username[256];          char username[256];
         struct {          struct {
Line 1397 
Line 1403 
 channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)  channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         int len;          int len;
   
         /* Send buffered output data to the socket. */          /* Send buffered output data to the socket. */
         if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {          if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
                 len = write(c->sock, buffer_ptr(&c->output),                  len = write(c->sock, buffer_ptr(&c->output),
Line 1474 
Line 1481 
 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 1573 
Line 1581 
 void  void
 channel_output_poll(void)  channel_output_poll(void)
 {  {
         int len, i;  
         Channel *c;          Channel *c;
           int i;
           u_int len;
   
         for (i = 0; i < channels_alloc; i++) {          for (i = 0; i < channels_alloc; i++) {
                 c = channels[i];                  c = channels[i];
Line 1641 
Line 1650 
                          * 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 1652 
Line 1661 
                     c->remote_window > 0 &&                      c->remote_window > 0 &&
                     (len = buffer_len(&c->extended)) > 0 &&                      (len = buffer_len(&c->extended)) > 0 &&
                     c->extended_usage == CHAN_EXTENDED_READ) {                      c->extended_usage == CHAN_EXTENDED_READ) {
                         debug2("channel %d: rwin %d elen %d euse %d",                          debug2("channel %d: rwin %u elen %u euse %d",
                             c->self, c->remote_window, buffer_len(&c->extended),                              c->self, c->remote_window, buffer_len(&c->extended),
                             c->extended_usage);                              c->extended_usage);
                         if (len > c->remote_window)                          if (len > c->remote_window)
Line 1722 
Line 1731 
 channel_input_extended_data(int type, u_int32_t seq, void *ctxt)  channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
 {  {
         int id;          int id;
         int tcode;  
         char *data;          char *data;
         u_int data_len;          u_int data_len, tcode;
         Channel *c;          Channel *c;
   
         /* Get the channel number and verify it. */          /* Get the channel number and verify it. */
Line 1879 
Line 1887 
                         c->confirm(c->self, NULL);                          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 %u rmax %u", c->self,
                     c->remote_window, c->remote_maxpacket);                      c->remote_window, c->remote_maxpacket);
         }          }
         packet_check_eom();          packet_check_eom();
Line 1936 
Line 1944 
 channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)  channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c;          Channel *c;
         int id, adjust;          int id;
           u_int adjust;
   
         if (!compat20)          if (!compat20)
                 return;                  return;
Line 1952 
Line 1961 
         }          }
         adjust = packet_get_int();          adjust = packet_get_int();
         packet_check_eom();          packet_check_eom();
         debug2("channel %d: rcvd adjust %d", id, adjust);          debug2("channel %d: rcvd adjust %u", id, adjust);
         c->remote_window += adjust;          c->remote_window += adjust;
 }  }
   
Line 1982 
Line 1991 
                 c->remote_id = remote_id;                  c->remote_id = remote_id;
         }          }
         if (c == NULL) {          if (c == NULL) {
                   xfree(originator_string);
                 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);                  packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
                 packet_put_int(remote_id);                  packet_put_int(remote_id);
                 packet_send();                  packet_send();
Line 2007 
Line 2017 
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         const char *host;          const char *host;
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         struct linger linger;  
   
         success = 0;          success = 0;
         host = (type == SSH_CHANNEL_RPORT_LISTENER) ?          host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
Line 2050 
Line 2059 
                         continue;                          continue;
                 }                  }
                 /*                  /*
                  * Set socket options.  We would like the socket to disappear                   * Set socket options.
                  * as soon as it has been closed for whatever reason.                   * Allow local port reuse in TIME_WAIT.
                  */                   */
                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));                  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
                 linger.l_onoff = 1;                      sizeof(on)) == -1)
                 linger.l_linger = 5;                          error("setsockopt SO_REUSEADDR: %s", strerror(errno));
                 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 2126 
Line 2135 
                 const char *address_to_bind = "0.0.0.0";                  const char *address_to_bind = "0.0.0.0";
                 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(0);                     /* boolean: want reply */                  packet_put_char(1);                     /* boolean: want reply */
                 packet_put_cstring(address_to_bind);                  packet_put_cstring(address_to_bind);
                 packet_put_int(listen_port);                  packet_put_int(listen_port);
                 packet_send();                  packet_send();
Line 2261 
Line 2270 
                 }                  }
                 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));                          if (ai->ai_next == NULL)
                                   error("socket: %.100s", strerror(errno));
                           else
                                   verbose("socket: %.100s", strerror(errno));
                         continue;                          continue;
                 }                  }
                 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)                  if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
Line 2327 
Line 2339 
   
 /*  /*
  * Creates an internet domain socket for listening for X11 connections.   * Creates an internet domain socket for listening for X11 connections.
  * Returns a suitable display number for the DISPLAY variable, or -1 if   * Returns 0 and a suitable display number for the DISPLAY variable
  * an error occurs.   * stored in display_numberp , or -1 if an error occurs.
  */   */
 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)      int single_connection, u_int *display_numberp)
 {  {
         Channel *nc = NULL;          Channel *nc = NULL;
         int display_number, sock;          int display_number, sock;
Line 2365 
Line 2377 
                         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));
                                 close(sock);                                  close(sock);
   
                                   if (ai->ai_next)
                                           continue;
   
                                 for (n = 0; n < num_socks; n++) {                                  for (n = 0; n < num_socks; n++) {
                                         close(socks[n]);                                          close(socks[n]);
                                 }                                  }
Line 2404 
Line 2420 
         }          }
   
         /* Return the display number for the DISPLAY environment variable. */          /* Return the display number for the DISPLAY environment variable. */
         return display_number;          *display_numberp = display_number;
           return (0);
 }  }
   
 static int  static int
Line 2559 
Line 2576 
                 /* Send refusal to the remote host. */                  /* Send refusal to the remote host. */
                 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);                  packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
                 packet_put_int(remote_id);                  packet_put_int(remote_id);
                   xfree(remote_host);
         } else {          } else {
                 /* Send a confirmation to the remote host. */                  /* Send a confirmation to the remote host. */
                 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);                  packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
Line 2573 
Line 2591 
 deny_input_open(int type, u_int32_t seq, 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.");
Line 2670 
Line 2689 
         packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);          packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
         packet_send();          packet_send();
         packet_write_wait();          packet_write_wait();
 }  
   
 /*  
  * Returns the name of the forwarded authentication socket.  Returns NULL if  
  * there is no forwarded authentication socket.  The returned value points to  
  * a static buffer.  
  */  
   
 char *  
 auth_get_socket_name(void)  
 {  
         return auth_sock_name;  
 }  
   
 /* removes the agent forwarding socket */  
   
 void  
 auth_sock_cleanup_proc(void *_pw)  
 {  
         struct passwd *pw = _pw;  
   
         if (auth_sock_name) {  
                 temporarily_use_uid(pw);  
                 unlink(auth_sock_name);  
                 rmdir(auth_sock_dir);  
                 auth_sock_name = NULL;  
                 restore_uid();  
         }  
 }  
   
 /*  
  * This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.  
  * This starts forwarding authentication requests.  
  */  
   
 int  
 auth_input_request_forwarding(struct passwd * pw)  
 {  
         Channel *nc;  
         int sock;  
         struct sockaddr_un sunaddr;  
   
         if (auth_get_socket_name() != NULL) {  
                 error("authentication forwarding requested twice.");  
                 return 0;  
         }  
   
         /* Temporarily drop privileged uid for mkdir/bind. */  
         temporarily_use_uid(pw);  
   
         /* Allocate a buffer for the socket name, and format the name. */  
         auth_sock_name = xmalloc(MAXPATHLEN);  
         auth_sock_dir = xmalloc(MAXPATHLEN);  
         strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);  
   
         /* Create private directory for socket */  
         if (mkdtemp(auth_sock_dir) == NULL) {  
                 packet_send_debug("Agent forwarding disabled: "  
                     "mkdtemp() failed: %.100s", strerror(errno));  
                 restore_uid();  
                 xfree(auth_sock_name);  
                 xfree(auth_sock_dir);  
                 auth_sock_name = NULL;  
                 auth_sock_dir = NULL;  
                 return 0;  
         }  
         snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%d",  
                  auth_sock_dir, (int) getpid());  
   
         /* delete agent socket on fatal() */  
         fatal_add_cleanup(auth_sock_cleanup_proc, pw);  
   
         /* Create the socket. */  
         sock = socket(AF_UNIX, SOCK_STREAM, 0);  
         if (sock < 0)  
                 packet_disconnect("socket: %.100s", strerror(errno));  
   
         /* Bind it to the name. */  
         memset(&sunaddr, 0, sizeof(sunaddr));  
         sunaddr.sun_family = AF_UNIX;  
         strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));  
   
         if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)  
                 packet_disconnect("bind: %.100s", strerror(errno));  
   
         /* Restore the privileged uid. */  
         restore_uid();  
   
         /* Start listening on the socket. */  
         if (listen(sock, 5) < 0)  
                 packet_disconnect("listen: %.100s", strerror(errno));  
   
         /* Allocate a channel for the authentication agent socket. */  
         nc = channel_new("auth socket",  
             SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,  
             CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,  
             0, xstrdup("auth socket"), 1);  
         strlcpy(nc->path, auth_sock_name, sizeof(nc->path));  
         return 1;  
 }  }
   
 /* This is called to process an SSH_SMSG_AGENT_OPEN message. */  /* This is called to process an SSH_SMSG_AGENT_OPEN message. */

Legend:
Removed from v.1.172  
changed lines
  Added in v.1.172.2.5