[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.335 and 1.336

version 1.335, 2014/07/05 23:11:48 version 1.336, 2014/07/15 15:54:14
Line 40 
Line 40 
  */   */
   
 #include <sys/types.h>  #include <sys/types.h>
   #include <sys/stat.h>
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
 #include <sys/un.h>  #include <sys/un.h>
 #include <sys/socket.h>  #include <sys/socket.h>
Line 103 
Line 104 
  * a corrupt remote server from accessing arbitrary TCP/IP ports on our local   * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
  * network (which might be behind a firewall).   * network (which might be behind a firewall).
  */   */
   /* XXX: streamlocal wants a path instead of host:port */
   /*      Overload host_to_connect; we could just make this match Forward */
   /*      XXX - can we use listen_host instead of listen_path? */
 typedef struct {  typedef struct {
         char *host_to_connect;          /* Connect to 'host'. */          char *host_to_connect;          /* Connect to 'host'. */
         u_short port_to_connect;        /* Connect to 'port'. */          int port_to_connect;            /* Connect to 'port'. */
         char *listen_host;              /* Remote side should listen address. */          char *listen_host;              /* Remote side should listen address. */
         u_short listen_port;            /* Remote side should listen port. */          char *listen_path;              /* Remote side should listen path. */
           int listen_port;                /* Remote side should listen port. */
 } ForwardPermission;  } ForwardPermission;
   
 /* List of all permitted host/port pairs to connect by the user. */  /* List of all permitted host/port pairs to connect by the user. */
Line 466 
Line 471 
                         case SSH_CHANNEL_PORT_LISTENER:                          case SSH_CHANNEL_PORT_LISTENER:
                         case SSH_CHANNEL_RPORT_LISTENER:                          case SSH_CHANNEL_RPORT_LISTENER:
                         case SSH_CHANNEL_X11_LISTENER:                          case SSH_CHANNEL_X11_LISTENER:
                           case SSH_CHANNEL_UNIX_LISTENER:
                           case SSH_CHANNEL_RUNIX_LISTENER:
                                 channel_close_fd(&c->sock);                                  channel_close_fd(&c->sock);
                                 channel_free(c);                                  channel_free(c);
                                 break;                                  break;
Line 528 
Line 535 
                 case SSH_CHANNEL_CONNECTING:                  case SSH_CHANNEL_CONNECTING:
                 case SSH_CHANNEL_ZOMBIE:                  case SSH_CHANNEL_ZOMBIE:
                 case SSH_CHANNEL_ABANDONED:                  case SSH_CHANNEL_ABANDONED:
                   case SSH_CHANNEL_UNIX_LISTENER:
                   case SSH_CHANNEL_RUNIX_LISTENER:
                         continue;                          continue;
                 case SSH_CHANNEL_LARVAL:                  case SSH_CHANNEL_LARVAL:
                         if (!compat20)                          if (!compat20)
Line 574 
Line 583 
                 case SSH_CHANNEL_CONNECTING:                  case SSH_CHANNEL_CONNECTING:
                 case SSH_CHANNEL_ZOMBIE:                  case SSH_CHANNEL_ZOMBIE:
                 case SSH_CHANNEL_ABANDONED:                  case SSH_CHANNEL_ABANDONED:
                   case SSH_CHANNEL_UNIX_LISTENER:
                   case SSH_CHANNEL_RUNIX_LISTENER:
                         continue;                          continue;
                 case SSH_CHANNEL_LARVAL:                  case SSH_CHANNEL_LARVAL:
                 case SSH_CHANNEL_AUTH_SOCKET:                  case SSH_CHANNEL_AUTH_SOCKET:
Line 624 
Line 635 
                 case SSH_CHANNEL_ABANDONED:                  case SSH_CHANNEL_ABANDONED:
                 case SSH_CHANNEL_MUX_CLIENT:                  case SSH_CHANNEL_MUX_CLIENT:
                 case SSH_CHANNEL_MUX_LISTENER:                  case SSH_CHANNEL_MUX_LISTENER:
                   case SSH_CHANNEL_UNIX_LISTENER:
                   case SSH_CHANNEL_RUNIX_LISTENER:
                         continue;                          continue;
                 case SSH_CHANNEL_LARVAL:                  case SSH_CHANNEL_LARVAL:
                 case SSH_CHANNEL_OPENING:                  case SSH_CHANNEL_OPENING:
Line 1379 
Line 1392 
 static void  static void
 port_open_helper(Channel *c, char *rtype)  port_open_helper(Channel *c, char *rtype)
 {  {
         int direct;  
         char buf[1024];          char buf[1024];
         char *local_ipaddr = get_local_ipaddr(c->sock);          char *local_ipaddr = get_local_ipaddr(c->sock);
         int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);          int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
Line 1393 
Line 1405 
                 remote_port = 65535;                  remote_port = 65535;
         }          }
   
         direct = (strcmp(rtype, "direct-tcpip") == 0);  
   
         snprintf(buf, sizeof buf,          snprintf(buf, sizeof buf,
             "%s: listening port %d for %.100s port %d, "              "%s: listening port %d for %.100s port %d, "
             "connect from %.200s port %d to %.100s port %d",              "connect from %.200s port %d to %.100s port %d",
Line 1410 
Line 1420 
                 packet_put_int(c->self);                  packet_put_int(c->self);
                 packet_put_int(c->local_window_max);                  packet_put_int(c->local_window_max);
                 packet_put_int(c->local_maxpacket);                  packet_put_int(c->local_maxpacket);
                 if (direct) {                  if (strcmp(rtype, "direct-tcpip") == 0) {
                         /* target host, port */                          /* target host, port */
                         packet_put_cstring(c->path);                          packet_put_cstring(c->path);
                         packet_put_int(c->host_port);                          packet_put_int(c->host_port);
                   } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
                           /* target path */
                           packet_put_cstring(c->path);
                   } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
                           /* listen path */
                           packet_put_cstring(c->path);
                 } else {                  } else {
                         /* listen address, port */                          /* listen address, port */
                         packet_put_cstring(c->path);                          packet_put_cstring(c->path);
                         packet_put_int(local_port);                          packet_put_int(local_port);
                 }                  }
                 /* originator host and port */                  if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
                 packet_put_cstring(remote_ipaddr);                          /* reserved for future owner/mode info */
                 packet_put_int((u_int)remote_port);                          packet_put_cstring("");
                   } else {
                           /* originator host and port */
                           packet_put_cstring(remote_ipaddr);
                           packet_put_int((u_int)remote_port);
                   }
                 packet_send();                  packet_send();
         } else {          } else {
                 packet_start(SSH_MSG_PORT_OPEN);                  packet_start(SSH_MSG_PORT_OPEN);
Line 1471 
Line 1492 
                 if (c->type == SSH_CHANNEL_RPORT_LISTENER) {                  if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
                         nextstate = SSH_CHANNEL_OPENING;                          nextstate = SSH_CHANNEL_OPENING;
                         rtype = "forwarded-tcpip";                          rtype = "forwarded-tcpip";
                   } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
                           nextstate = SSH_CHANNEL_OPENING;
                           rtype = "forwarded-streamlocal@openssh.com";
                   } else if (c->host_port == PORT_STREAMLOCAL) {
                           nextstate = SSH_CHANNEL_OPENING;
                           rtype = "direct-streamlocal@openssh.com";
                   } else if (c->host_port == 0) {
                           nextstate = SSH_CHANNEL_DYNAMIC;
                           rtype = "dynamic-tcpip";
                 } else {                  } else {
                         if (c->host_port == 0) {                          nextstate = SSH_CHANNEL_OPENING;
                                 nextstate = SSH_CHANNEL_DYNAMIC;                          rtype = "direct-tcpip";
                                 rtype = "dynamic-tcpip";  
                         } else {  
                                 nextstate = SSH_CHANNEL_OPENING;  
                                 rtype = "direct-tcpip";  
                         }  
                 }                  }
   
                 addrlen = sizeof(addr);                  addrlen = sizeof(addr);
Line 1491 
Line 1516 
                                 c->notbefore = monotime() + 1;                                  c->notbefore = monotime() + 1;
                         return;                          return;
                 }                  }
                 set_nodelay(newsock);                  if (c->host_port != PORT_STREAMLOCAL)
                           set_nodelay(newsock);
                 nc = channel_new(rtype, nextstate, newsock, newsock, -1,                  nc = channel_new(rtype, nextstate, newsock, newsock, -1,
                     c->local_window_max, c->local_maxpacket, 0, rtype, 1);                      c->local_window_max, c->local_maxpacket, 0, rtype, 1);
                 nc->listening_port = c->listening_port;                  nc->listening_port = c->listening_port;
Line 1963 
Line 1989 
         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;
           channel_pre[SSH_CHANNEL_UNIX_LISTENER] =        &channel_pre_listener;
           channel_pre[SSH_CHANNEL_RUNIX_LISTENER] =       &channel_pre_listener;
         channel_pre[SSH_CHANNEL_X11_LISTENER] =         &channel_pre_listener;          channel_pre[SSH_CHANNEL_X11_LISTENER] =         &channel_pre_listener;
         channel_pre[SSH_CHANNEL_AUTH_SOCKET] =          &channel_pre_listener;          channel_pre[SSH_CHANNEL_AUTH_SOCKET] =          &channel_pre_listener;
         channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;          channel_pre[SSH_CHANNEL_CONNECTING] =           &channel_pre_connecting;
Line 1973 
Line 2001 
         channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open;          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_UNIX_LISTENER] =       &channel_post_port_listener;
           channel_post[SSH_CHANNEL_RUNIX_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;
Line 2613 
Line 2643 
                 originator_string = xstrdup("unknown (remote did not supply name)");                  originator_string = xstrdup("unknown (remote did not supply name)");
         }          }
         packet_check_eom();          packet_check_eom();
         c = channel_connect_to(host, host_port,          c = channel_connect_to_port(host, host_port,
             "connected socket", originator_string);              "connected socket", originator_string);
         free(originator_string);          free(originator_string);
         free(host);          free(host);
Line 2680 
Line 2710 
  */   */
 static const char *  static const char *
 channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,  channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
     int is_client, int gateway_ports)      int is_client, struct ForwardOptions *fwd_opts)
 {  {
         const char *addr = NULL;          const char *addr = NULL;
         int wildcard = 0;          int wildcard = 0;
   
         if (listen_addr == NULL) {          if (listen_addr == NULL) {
                 /* No address specified: default to gateway_ports setting */                  /* No address specified: default to gateway_ports setting */
                 if (gateway_ports)                  if (fwd_opts->gateway_ports)
                         wildcard = 1;                          wildcard = 1;
         } else if (gateway_ports || is_client) {          } else if (fwd_opts->gateway_ports || is_client) {
                 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&                  if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
                     strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||                      strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
                     *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||                      *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
                     (!is_client && gateway_ports == 1)) {                      (!is_client && fwd_opts->gateway_ports == 1)) {
                         wildcard = 1;                          wildcard = 1;
                         /*                          /*
                          * Notify client if they requested a specific listen                           * Notify client if they requested a specific listen
Line 2727 
Line 2757 
 }  }
   
 static int  static int
 channel_setup_fwd_listener(int type, const char *listen_addr,  channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
     u_short listen_port, int *allocated_listen_port,      int *allocated_listen_port, struct ForwardOptions *fwd_opts)
     const char *host_to_connect, u_short port_to_connect, int gateway_ports)  
 {  {
         Channel *c;          Channel *c;
         int sock, r, success = 0, wildcard = 0, is_client;          int sock, r, success = 0, wildcard = 0, is_client;
Line 2739 
Line 2768 
         in_port_t *lport_p;          in_port_t *lport_p;
   
         host = (type == SSH_CHANNEL_RPORT_LISTENER) ?          host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
             listen_addr : host_to_connect;              fwd->listen_host : fwd->connect_host;
         is_client = (type == SSH_CHANNEL_PORT_LISTENER);          is_client = (type == SSH_CHANNEL_PORT_LISTENER);
   
         if (host == NULL) {          if (host == NULL) {
Line 2752 
Line 2781 
         }          }
   
         /* Determine the bind address, cf. channel_fwd_bind_addr() comment */          /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
         addr = channel_fwd_bind_addr(listen_addr, &wildcard,          addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
             is_client, gateway_ports);              is_client, fwd_opts);
         debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",          debug3("%s: type %d wildcard %d addr %s", __func__,
             type, wildcard, (addr == NULL) ? "NULL" : addr);              type, wildcard, (addr == NULL) ? "NULL" : addr);
   
         /*          /*
Line 2765 
Line 2794 
         hints.ai_family = IPv4or6;          hints.ai_family = IPv4or6;
         hints.ai_flags = wildcard ? AI_PASSIVE : 0;          hints.ai_flags = wildcard ? AI_PASSIVE : 0;
         hints.ai_socktype = SOCK_STREAM;          hints.ai_socktype = SOCK_STREAM;
         snprintf(strport, sizeof strport, "%d", listen_port);          snprintf(strport, sizeof strport, "%d", fwd->listen_port);
         if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {          if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
                 if (addr == NULL) {                  if (addr == NULL) {
                         /* This really shouldn't happen */                          /* This really shouldn't happen */
                         packet_disconnect("getaddrinfo: fatal error: %s",                          packet_disconnect("getaddrinfo: fatal error: %s",
                             ssh_gai_strerror(r));                              ssh_gai_strerror(r));
                 } else {                  } else {
                         error("channel_setup_fwd_listener: "                          error("%s: getaddrinfo(%.64s): %s", __func__, addr,
                             "getaddrinfo(%.64s): %s", addr,  
                             ssh_gai_strerror(r));                              ssh_gai_strerror(r));
                 }                  }
                 return 0;                  return 0;
Line 2797 
Line 2825 
                  * If allocating a port for -R forwards, then use the                   * If allocating a port for -R forwards, then use the
                  * same port for all address families.                   * same port for all address families.
                  */                   */
                 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&                  if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
                     allocated_listen_port != NULL && *allocated_listen_port > 0)                      allocated_listen_port != NULL && *allocated_listen_port > 0)
                         *lport_p = htons(*allocated_listen_port);                          *lport_p = htons(*allocated_listen_port);
   
                 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_setup_fwd_listener: getnameinfo failed");                          error("%s: getnameinfo failed", __func__);
                         continue;                          continue;
                 }                  }
                 /* Create a port to listen for the host. */                  /* Create a port to listen for the host. */
Line 2834 
Line 2862 
                 }                  }
   
                 /*                  /*
                  * listen_port == 0 requests a dynamically allocated port -                   * fwd->listen_port == 0 requests a dynamically allocated port -
                  * record what we got.                   * record what we got.
                  */                   */
                 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&                  if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
                     allocated_listen_port != NULL &&                      allocated_listen_port != NULL &&
                     *allocated_listen_port == 0) {                      *allocated_listen_port == 0) {
                         *allocated_listen_port = get_sock_port(sock, 1);                          *allocated_listen_port = get_sock_port(sock, 1);
Line 2850 
Line 2878 
                     CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,                      CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
                     0, "port listener", 1);                      0, "port listener", 1);
                 c->path = xstrdup(host);                  c->path = xstrdup(host);
                 c->host_port = port_to_connect;                  c->host_port = fwd->connect_port;
                 c->listening_addr = addr == NULL ? NULL : xstrdup(addr);                  c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
                 if (listen_port == 0 && allocated_listen_port != NULL &&                  if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
                     !(datafellows & SSH_BUG_DYNAMIC_RPORT))                      !(datafellows & SSH_BUG_DYNAMIC_RPORT))
                         c->listening_port = *allocated_listen_port;                          c->listening_port = *allocated_listen_port;
                 else                  else
                         c->listening_port = listen_port;                          c->listening_port = fwd->listen_port;
                 success = 1;                  success = 1;
         }          }
         if (success == 0)          if (success == 0)
                 error("channel_setup_fwd_listener: cannot listen to port: %d",                  error("%s: cannot listen to port: %d", __func__,
                     listen_port);                      fwd->listen_port);
         freeaddrinfo(aitop);          freeaddrinfo(aitop);
         return success;          return success;
 }  }
   
 int  static int
 channel_cancel_rport_listener(const char *host, u_short port)  channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
       struct ForwardOptions *fwd_opts)
 {  {
           struct sockaddr_un sunaddr;
           const char *path;
           Channel *c;
           int port, sock;
           mode_t omask;
   
           switch (type) {
           case SSH_CHANNEL_UNIX_LISTENER:
                   if (fwd->connect_path != NULL) {
                           if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
                                   error("Local connecting path too long: %s",
                                       fwd->connect_path);
                                   return 0;
                           }
                           path = fwd->connect_path;
                           port = PORT_STREAMLOCAL;
                   } else {
                           if (fwd->connect_host == NULL) {
                                   error("No forward host name.");
                                   return 0;
                           }
                           if (strlen(fwd->connect_host) >= NI_MAXHOST) {
                                   error("Forward host name too long.");
                                   return 0;
                           }
                           path = fwd->connect_host;
                           port = fwd->connect_port;
                   }
                   break;
           case SSH_CHANNEL_RUNIX_LISTENER:
                   path = fwd->listen_path;
                   port = PORT_STREAMLOCAL;
                   break;
           default:
                   error("%s: unexpected channel type %d", __func__, type);
                   return 0;
           }
   
           if (fwd->listen_path == NULL) {
                   error("No forward path name.");
                   return 0;
           }
           if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
                   error("Local listening path too long: %s", fwd->listen_path);
                   return 0;
           }
   
           debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
   
           /* Start a Unix domain listener. */
           omask = umask(fwd_opts->streamlocal_bind_mask);
           sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
               fwd_opts->streamlocal_bind_unlink);
           umask(omask);
           if (sock < 0)
                   return 0;
   
           debug("Local forwarding listening on path %s.", fwd->listen_path);
   
           /* Allocate a channel number for the socket. */
           c = channel_new("unix listener", type, sock, sock, -1,
               CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
               0, "unix listener", 1);
           c->path = xstrdup(path);
           c->host_port = port;
           c->listening_port = PORT_STREAMLOCAL;
           c->listening_addr = xstrdup(fwd->listen_path);
           return 1;
   }
   
   static int
   channel_cancel_rport_listener_tcpip(const char *host, u_short port)
   {
         u_int i;          u_int i;
         int found = 0;          int found = 0;
   
Line 2886 
Line 2988 
         return (found);          return (found);
 }  }
   
   static int
   channel_cancel_rport_listener_streamlocal(const char *path)
   {
           u_int i;
           int found = 0;
   
           for (i = 0; i < channels_alloc; i++) {
                   Channel *c = channels[i];
                   if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
                           continue;
                   if (c->path == NULL)
                           continue;
                   if (strcmp(c->path, path) == 0) {
                           debug2("%s: close channel %d", __func__, i);
                           channel_free(c);
                           found = 1;
                   }
           }
   
           return (found);
   }
   
 int  int
 channel_cancel_lport_listener(const char *lhost, u_short lport,  channel_cancel_rport_listener(struct Forward *fwd)
     int cport, int gateway_ports)  
 {  {
           if (fwd->listen_path != NULL)
                   return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
           else
                   return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
   }
   
   static int
   channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
       int cport, struct ForwardOptions *fwd_opts)
   {
         u_int i;          u_int i;
         int found = 0;          int found = 0;
         const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports);          const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
   
         for (i = 0; i < channels_alloc; i++) {          for (i = 0; i < channels_alloc; i++) {
                 Channel *c = channels[i];                  Channel *c = channels[i];
Line 2921 
Line 3054 
         return (found);          return (found);
 }  }
   
   static int
   channel_cancel_lport_listener_streamlocal(const char *path)
   {
           u_int i;
           int found = 0;
   
           if (path == NULL) {
                   error("%s: no path specified.", __func__);
                   return 0;
           }
   
           for (i = 0; i < channels_alloc; i++) {
                   Channel *c = channels[i];
                   if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
                           continue;
                   if (c->listening_addr == NULL)
                           continue;
                   if (strcmp(c->listening_addr, path) == 0) {
                           debug2("%s: close channel %d", __func__, i);
                           channel_free(c);
                           found = 1;
                   }
           }
   
           return (found);
   }
   
   int
   channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
   {
           if (fwd->listen_path != NULL)
                   return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
           else
                   return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
   }
   
 /* protocol local port fwd, used by ssh (and sshd in v1) */  /* protocol local port fwd, used by ssh (and sshd in v1) */
 int  int
 channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,  channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
     const char *host_to_connect, u_short port_to_connect, int gateway_ports)  
 {  {
         return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,          if (fwd->listen_path != NULL) {
             listen_host, listen_port, NULL, host_to_connect, port_to_connect,                  return channel_setup_fwd_listener_streamlocal(
             gateway_ports);                      SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
           } else {
                   return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
                       fwd, NULL, fwd_opts);
           }
 }  }
   
 /* protocol v2 remote port fwd, used by sshd */  /* protocol v2 remote port fwd, used by sshd */
 int  int
 channel_setup_remote_fwd_listener(const char *listen_address,  channel_setup_remote_fwd_listener(struct Forward *fwd,
     u_short listen_port, int *allocated_listen_port, int gateway_ports)      int *allocated_listen_port, struct ForwardOptions *fwd_opts)
 {  {
         return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,          if (fwd->listen_path != NULL) {
             listen_address, listen_port, allocated_listen_port,                  return channel_setup_fwd_listener_streamlocal(
             NULL, 0, gateway_ports);                      SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
           } else {
                   return channel_setup_fwd_listener_tcpip(
                       SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
                       fwd_opts);
           }
 }  }
   
 /*  /*
Line 2969 
Line 3146 
  * channel_update_permitted_opens().   * channel_update_permitted_opens().
  */   */
 int  int
 channel_request_remote_forwarding(const char *listen_host, u_short listen_port,  channel_request_remote_forwarding(struct Forward *fwd)
     const char *host_to_connect, u_short port_to_connect)  
 {  {
         int type, success = 0, idx = -1;          int type, success = 0, idx = -1;
   
         /* Send the forward request to the remote side. */          /* Send the forward request to the remote side. */
         if (compat20) {          if (compat20) {
                 packet_start(SSH2_MSG_GLOBAL_REQUEST);                  packet_start(SSH2_MSG_GLOBAL_REQUEST);
                 packet_put_cstring("tcpip-forward");                  if (fwd->listen_path != NULL) {
                 packet_put_char(1);             /* boolean: want reply */                      packet_put_cstring("streamlocal-forward@openssh.com");
                 packet_put_cstring(channel_rfwd_bind_host(listen_host));                      packet_put_char(1);         /* boolean: want reply */
                 packet_put_int(listen_port);                      packet_put_cstring(fwd->listen_path);
                   } else {
                       packet_put_cstring("tcpip-forward");
                       packet_put_char(1);         /* boolean: want reply */
                       packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
                       packet_put_int(fwd->listen_port);
                   }
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
                 /* Assume that server accepts the request */                  /* Assume that server accepts the request */
                 success = 1;                  success = 1;
         } else {          } else if (fwd->listen_path == NULL) {
                 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);                  packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
                 packet_put_int(listen_port);                  packet_put_int(fwd->listen_port);
                 packet_put_cstring(host_to_connect);                  packet_put_cstring(fwd->connect_host);
                 packet_put_int(port_to_connect);                  packet_put_int(fwd->connect_port);
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
   
Line 3006 
Line 3188 
                         packet_disconnect("Protocol error for port forward request:"                          packet_disconnect("Protocol error for port forward request:"
                             "received packet type %d.", type);                              "received packet type %d.", type);
                 }                  }
           } else {
                   logit("Warning: Server does not support remote stream local forwarding.");
         }          }
         if (success) {          if (success) {
                 /* Record that connection to this host/port is permitted. */                  /* Record that connection to this host/port is permitted. */
                 permitted_opens = xrealloc(permitted_opens,                  permitted_opens = xrealloc(permitted_opens,
                     num_permitted_opens + 1, sizeof(*permitted_opens));                      num_permitted_opens + 1, sizeof(*permitted_opens));
                 idx = num_permitted_opens++;                  idx = num_permitted_opens++;
                 permitted_opens[idx].host_to_connect = xstrdup(host_to_connect);                  if (fwd->connect_path != NULL) {
                 permitted_opens[idx].port_to_connect = port_to_connect;                          permitted_opens[idx].host_to_connect =
                 permitted_opens[idx].listen_host = listen_host ?                              xstrdup(fwd->connect_path);
                     xstrdup(listen_host) : NULL;                          permitted_opens[idx].port_to_connect =
                 permitted_opens[idx].listen_port = listen_port;                              PORT_STREAMLOCAL;
                   } else {
                           permitted_opens[idx].host_to_connect =
                               xstrdup(fwd->connect_host);
                           permitted_opens[idx].port_to_connect =
                               fwd->connect_port;
                   }
                   if (fwd->listen_path != NULL) {
                           permitted_opens[idx].listen_host = NULL;
                           permitted_opens[idx].listen_path =
                               xstrdup(fwd->listen_path);
                           permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
                   } else {
                           permitted_opens[idx].listen_host =
                               fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
                           permitted_opens[idx].listen_path = NULL;
                           permitted_opens[idx].listen_port = fwd->listen_port;
                   }
         }          }
         return (idx);          return (idx);
 }  }
   
 static int  static int
 open_match(ForwardPermission *allowed_open, const char *requestedhost,  open_match(ForwardPermission *allowed_open, const char *requestedhost,
     u_short requestedport)      int requestedport)
 {  {
         if (allowed_open->host_to_connect == NULL)          if (allowed_open->host_to_connect == NULL)
                 return 0;                  return 0;
Line 3036 
Line 3237 
 }  }
   
 /*  /*
  * Note that in he listen host/port case   * Note that in the listen host/port case
  * we don't support FWD_PERMIT_ANY_PORT and   * we don't support FWD_PERMIT_ANY_PORT and
  * need to translate between the configured-host (listen_host)   * need to translate between the configured-host (listen_host)
  * and what we've sent to the remote server (channel_rfwd_bind_host)   * and what we've sent to the remote server (channel_rfwd_bind_host)
  */   */
 static int  static int
 open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,  open_listen_match_tcpip(ForwardPermission *allowed_open,
     u_short requestedport, int translate)      const char *requestedhost, u_short requestedport, int translate)
 {  {
         const char *allowed_host;          const char *allowed_host;
   
Line 3063 
Line 3264 
         return 1;          return 1;
 }  }
   
   static int
   open_listen_match_streamlocal(ForwardPermission *allowed_open,
       const char *requestedpath)
   {
           if (allowed_open->host_to_connect == NULL)
                   return 0;
           if (allowed_open->listen_port != PORT_STREAMLOCAL)
                   return 0;
           if (allowed_open->listen_path == NULL ||
               strcmp(allowed_open->listen_path, requestedpath) != 0)
                   return 0;
           return 1;
   }
   
 /*  /*
  * Request cancellation of remote forwarding of connection host:port from   * Request cancellation of remote forwarding of connection host:port from
  * local side.   * local side.
  */   */
 int  static int
 channel_request_rforward_cancel(const char *host, u_short port)  channel_request_rforward_cancel_tcpip(const char *host, u_short port)
 {  {
         int i;          int i;
   
Line 3076 
Line 3291 
                 return -1;                  return -1;
   
         for (i = 0; i < num_permitted_opens; i++) {          for (i = 0; i < num_permitted_opens; i++) {
                 if (open_listen_match(&permitted_opens[i], host, port, 0))                  if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
                         break;                          break;
         }          }
         if (i >= num_permitted_opens) {          if (i >= num_permitted_opens) {
Line 3090 
Line 3305 
         packet_put_int(port);          packet_put_int(port);
         packet_send();          packet_send();
   
         permitted_opens[i].port_to_connect = 0;  
         permitted_opens[i].listen_port = 0;          permitted_opens[i].listen_port = 0;
           permitted_opens[i].port_to_connect = 0;
         free(permitted_opens[i].host_to_connect);          free(permitted_opens[i].host_to_connect);
         permitted_opens[i].host_to_connect = NULL;          permitted_opens[i].host_to_connect = NULL;
         free(permitted_opens[i].listen_host);          free(permitted_opens[i].listen_host);
         permitted_opens[i].listen_host = NULL;          permitted_opens[i].listen_host = NULL;
           permitted_opens[i].listen_path = NULL;
   
         return 0;          return 0;
 }  }
   
 /*  /*
    * Request cancellation of remote forwarding of Unix domain socket
    * path from local side.
    */
   static int
   channel_request_rforward_cancel_streamlocal(const char *path)
   {
           int i;
   
           if (!compat20)
                   return -1;
   
           for (i = 0; i < num_permitted_opens; i++) {
                   if (open_listen_match_streamlocal(&permitted_opens[i], path))
                           break;
           }
           if (i >= num_permitted_opens) {
                   debug("%s: requested forward not found", __func__);
                   return -1;
           }
           packet_start(SSH2_MSG_GLOBAL_REQUEST);
           packet_put_cstring("cancel-streamlocal-forward@openssh.com");
           packet_put_char(0);
           packet_put_cstring(path);
           packet_send();
   
           permitted_opens[i].listen_port = 0;
           permitted_opens[i].port_to_connect = 0;
           free(permitted_opens[i].host_to_connect);
           permitted_opens[i].host_to_connect = NULL;
           permitted_opens[i].listen_host = NULL;
           free(permitted_opens[i].listen_path);
           permitted_opens[i].listen_path = NULL;
   
           return 0;
   }
   
   /*
    * Request cancellation of remote forwarding of a connection from local side.
    */
   int
   channel_request_rforward_cancel(struct Forward *fwd)
   {
           if (fwd->listen_path != NULL) {
                   return (channel_request_rforward_cancel_streamlocal(
                       fwd->listen_path));
           } else {
                   return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
                       fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
           }
   }
   
   /*
  * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates   * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates
  * listening for the port, and sends back a success reply (or disconnect   * listening for the port, and sends back a success reply (or disconnect
  * message if there was an error).   * message if there was an error).
  */   */
 int  int
 channel_input_port_forward_request(int is_root, int gateway_ports)  channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
 {  {
         u_short port, host_port;  
         int success = 0;          int success = 0;
         char *hostname;          struct Forward fwd;
   
         /* Get arguments from the packet. */          /* Get arguments from the packet. */
         port = packet_get_int();          memset(&fwd, 0, sizeof(fwd));
         hostname = packet_get_string(NULL);          fwd.listen_port = packet_get_int();
         host_port = packet_get_int();          fwd.connect_host = packet_get_string(NULL);
           fwd.connect_port = packet_get_int();
   
         /*          /*
          * Check that an unprivileged user is not trying to forward a           * Check that an unprivileged user is not trying to forward a
          * privileged port.           * privileged port.
          */           */
         if (port < IPPORT_RESERVED && !is_root)          if (fwd.listen_port < IPPORT_RESERVED && !is_root)
                 packet_disconnect(                  packet_disconnect(
                     "Requested forwarding of port %d but user is not root.",                      "Requested forwarding of port %d but user is not root.",
                     port);                      fwd.listen_port);
         if (host_port == 0)          if (fwd.connect_port == 0)
                 packet_disconnect("Dynamic forwarding denied.");                  packet_disconnect("Dynamic forwarding denied.");
   
         /* Initiate forwarding */          /* Initiate forwarding */
         success = channel_setup_local_fwd_listener(NULL, port, hostname,          success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
             host_port, gateway_ports);  
   
         /* Free the argument string. */          /* Free the argument string. */
         free(hostname);          free(fwd.connect_host);
   
         return (success ? 0 : -1);          return (success ? 0 : -1);
 }  }
Line 3160 
Line 3427 
         permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);          permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
         permitted_opens[num_permitted_opens].port_to_connect = port;          permitted_opens[num_permitted_opens].port_to_connect = port;
         permitted_opens[num_permitted_opens].listen_host = NULL;          permitted_opens[num_permitted_opens].listen_host = NULL;
           permitted_opens[num_permitted_opens].listen_path = NULL;
         permitted_opens[num_permitted_opens].listen_port = 0;          permitted_opens[num_permitted_opens].listen_port = 0;
         num_permitted_opens++;          num_permitted_opens++;
   
Line 3194 
Line 3462 
                 permitted_opens[idx].host_to_connect = NULL;                  permitted_opens[idx].host_to_connect = NULL;
                 free(permitted_opens[idx].listen_host);                  free(permitted_opens[idx].listen_host);
                 permitted_opens[idx].listen_host = NULL;                  permitted_opens[idx].listen_host = NULL;
                   free(permitted_opens[idx].listen_path);
                   permitted_opens[idx].listen_path = NULL;
         }          }
 }  }
   
Line 3208 
Line 3478 
              = xstrdup(host);               = xstrdup(host);
         permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;          permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
         permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;          permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
           permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
         permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;          permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
         return ++num_adm_permitted_opens;          return ++num_adm_permitted_opens;
 }  }
Line 3229 
Line 3500 
         for (i = 0; i < num_permitted_opens; i++) {          for (i = 0; i < num_permitted_opens; i++) {
                 free(permitted_opens[i].host_to_connect);                  free(permitted_opens[i].host_to_connect);
                 free(permitted_opens[i].listen_host);                  free(permitted_opens[i].listen_host);
                   free(permitted_opens[i].listen_path);
         }          }
         free(permitted_opens);          free(permitted_opens);
         permitted_opens = NULL;          permitted_opens = NULL;
Line 3243 
Line 3515 
         for (i = 0; i < num_adm_permitted_opens; i++) {          for (i = 0; i < num_adm_permitted_opens; i++) {
                 free(permitted_adm_opens[i].host_to_connect);                  free(permitted_adm_opens[i].host_to_connect);
                 free(permitted_adm_opens[i].listen_host);                  free(permitted_adm_opens[i].listen_host);
                   free(permitted_adm_opens[i].listen_path);
         }          }
         free(permitted_adm_opens);          free(permitted_adm_opens);
         permitted_adm_opens = NULL;          permitted_adm_opens = NULL;
Line 3286 
Line 3559 
 connect_next(struct channel_connect *cctx)  connect_next(struct channel_connect *cctx)
 {  {
         int sock, saved_errno;          int sock, saved_errno;
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          struct sockaddr_un *sunaddr;
           char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
   
         for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {          for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
                 if (cctx->ai->ai_family != AF_INET &&                  switch (cctx->ai->ai_family) {
                     cctx->ai->ai_family != AF_INET6)                  case AF_UNIX:
                           /* unix:pathname instead of host:port */
                           sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
                           strlcpy(ntop, "unix", sizeof(ntop));
                           strlcpy(strport, sunaddr->sun_path, sizeof(strport));
                           break;
                   case AF_INET:
                   case AF_INET6:
                           if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
                               ntop, sizeof(ntop), strport, sizeof(strport),
                               NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                                   error("connect_next: getnameinfo failed");
                                   continue;
                           }
                           break;
                   default:
                         continue;                          continue;
                 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,  
                     ntop, sizeof(ntop), strport, sizeof(strport),  
                     NI_NUMERICHOST|NI_NUMERICSERV) != 0) {  
                         error("connect_next: getnameinfo failed");  
                         continue;  
                 }                  }
                 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,                  if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
                     cctx->ai->ai_protocol)) == -1) {                      cctx->ai->ai_protocol)) == -1) {
Line 3318 
Line 3602 
                         errno = saved_errno;                          errno = saved_errno;
                         continue;       /* fail -- try next */                          continue;       /* fail -- try next */
                 }                  }
                   if (cctx->ai->ai_family != AF_UNIX)
                           set_nodelay(sock);
                 debug("connect_next: host %.100s ([%.100s]:%s) "                  debug("connect_next: host %.100s ([%.100s]:%s) "
                     "in progress, fd=%d", cctx->host, ntop, strport, sock);                      "in progress, fd=%d", cctx->host, ntop, strport, sock);
                 cctx->ai = cctx->ai->ai_next;                  cctx->ai = cctx->ai->ai_next;
                 set_nodelay(sock);  
                 return sock;                  return sock;
         }          }
         return -1;          return -1;
Line 3331 
Line 3616 
 channel_connect_ctx_free(struct channel_connect *cctx)  channel_connect_ctx_free(struct channel_connect *cctx)
 {  {
         free(cctx->host);          free(cctx->host);
         if (cctx->aitop)          if (cctx->aitop) {
                 freeaddrinfo(cctx->aitop);                  if (cctx->aitop->ai_family == AF_UNIX)
                           free(cctx->aitop);
                   else
                           freeaddrinfo(cctx->aitop);
           }
         memset(cctx, 0, sizeof(*cctx));          memset(cctx, 0, sizeof(*cctx));
 }  }
   
 /* Return CONNECTING channel to remote host, port */  /* Return CONNECTING channel to remote host:port or local socket path */
 static Channel *  static Channel *
 connect_to(const char *host, u_short port, char *ctype, char *rname)  connect_to(const char *name, int port, char *ctype, char *rname)
 {  {
         struct addrinfo hints;          struct addrinfo hints;
         int gaierr;          int gaierr;
Line 3348 
Line 3637 
         Channel *c;          Channel *c;
   
         memset(&cctx, 0, sizeof(cctx));          memset(&cctx, 0, sizeof(cctx));
         memset(&hints, 0, sizeof(hints));  
         hints.ai_family = IPv4or6;          if (port == PORT_STREAMLOCAL) {
         hints.ai_socktype = SOCK_STREAM;                  struct sockaddr_un *sunaddr;
         snprintf(strport, sizeof strport, "%d", port);                  struct addrinfo *ai;
         if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {  
                 error("connect_to %.100s: unknown host (%s)", host,                  if (strlen(name) > sizeof(sunaddr->sun_path)) {
                     ssh_gai_strerror(gaierr));                          error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
                 return NULL;                          return (NULL);
                   }
   
                   /*
                    * Fake up a struct addrinfo for AF_UNIX connections.
                    * channel_connect_ctx_free() must check ai_family
                    * and use free() not freeaddirinfo() for AF_UNIX.
                    */
                   ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
                   memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
                   ai->ai_addr = (struct sockaddr *)(ai + 1);
                   ai->ai_addrlen = sizeof(*sunaddr);
                   ai->ai_family = AF_UNIX;
                   ai->ai_socktype = SOCK_STREAM;
                   ai->ai_protocol = PF_UNSPEC;
                   sunaddr = (struct sockaddr_un *)ai->ai_addr;
                   sunaddr->sun_family = AF_UNIX;
                   strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
                   cctx.aitop = ai;
           } else {
                   memset(&hints, 0, sizeof(hints));
                   hints.ai_family = IPv4or6;
                   hints.ai_socktype = SOCK_STREAM;
                   snprintf(strport, sizeof strport, "%d", port);
                   if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
                           error("connect_to %.100s: unknown host (%s)", name,
                               ssh_gai_strerror(gaierr));
                           return NULL;
                   }
         }          }
   
         cctx.host = xstrdup(host);          cctx.host = xstrdup(name);
         cctx.port = port;          cctx.port = port;
         cctx.ai = cctx.aitop;          cctx.ai = cctx.aitop;
   
         if ((sock = connect_next(&cctx)) == -1) {          if ((sock = connect_next(&cctx)) == -1) {
                 error("connect to %.100s port %d failed: %s",                  error("connect to %.100s port %d failed: %s",
                     host, port, strerror(errno));                      name, port, strerror(errno));
                 channel_connect_ctx_free(&cctx);                  channel_connect_ctx_free(&cctx);
                 return NULL;                  return NULL;
         }          }
Line 3381 
Line 3698 
         int i;          int i;
   
         for (i = 0; i < num_permitted_opens; i++) {          for (i = 0; i < num_permitted_opens; i++) {
                 if (open_listen_match(&permitted_opens[i], listen_host,                  if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
                     listen_port, 1)) {                      listen_port, 1)) {
                         return connect_to(                          return connect_to(
                             permitted_opens[i].host_to_connect,                              permitted_opens[i].host_to_connect,
Line 3393 
Line 3710 
         return NULL;          return NULL;
 }  }
   
   Channel *
   channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
   {
           int i;
   
           for (i = 0; i < num_permitted_opens; i++) {
                   if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
                           return connect_to(
                               permitted_opens[i].host_to_connect,
                               permitted_opens[i].port_to_connect, ctype, rname);
                   }
           }
           error("WARNING: Server requests forwarding for unknown path %.100s",
               path);
           return NULL;
   }
   
 /* Check if connecting to that port is permitted and connect. */  /* Check if connecting to that port is permitted and connect. */
 Channel *  Channel *
 channel_connect_to(const char *host, u_short port, char *ctype, char *rname)  channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
 {  {
         int i, permit, permit_adm = 1;          int i, permit, permit_adm = 1;
   
Line 3423 
Line 3757 
                 return NULL;                  return NULL;
         }          }
         return connect_to(host, port, ctype, rname);          return connect_to(host, port, ctype, rname);
   }
   
   /* Check if connecting to that path is permitted and connect. */
   Channel *
   channel_connect_to_path(const char *path, char *ctype, char *rname)
   {
           int i, permit, permit_adm = 1;
   
           permit = all_opens_permitted;
           if (!permit) {
                   for (i = 0; i < num_permitted_opens; i++)
                           if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
                                   permit = 1;
                                   break;
                           }
           }
   
           if (num_adm_permitted_opens > 0) {
                   permit_adm = 0;
                   for (i = 0; i < num_adm_permitted_opens; i++)
                           if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
                                   permit_adm = 1;
                                   break;
                           }
           }
   
           if (!permit || !permit_adm) {
                   logit("Received request to connect to path %.100s, "
                       "but the request was denied.", path);
                   return NULL;
           }
           return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
 }  }
   
 void  void

Legend:
Removed from v.1.335  
changed lines
  Added in v.1.336