[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.380 and 1.381

version 1.380, 2018/04/10 00:10:49 version 1.381, 2018/06/06 18:22:41
Line 76 
Line 76 
 #include "key.h"  #include "key.h"
 #include "authfd.h"  #include "authfd.h"
 #include "pathnames.h"  #include "pathnames.h"
   #include "match.h"
   
 /* -- agent forwarding */  /* -- agent forwarding */
 #define NUM_SOCKS       10  #define NUM_SOCKS       10
Line 91 
Line 92 
 /* Maximum number of fake X11 displays to try. */  /* Maximum number of fake X11 displays to try. */
 #define MAX_DISPLAYS  1000  #define MAX_DISPLAYS  1000
   
   /* Per-channel callback for pre/post select() actions */
   typedef void chan_fn(struct ssh *, Channel *c,
       fd_set *readset, fd_set *writeset);
   
 /*  /*
  * Data structure for storing which hosts are permitted for forward requests.   * Data structure for storing which hosts are permitted for forward requests.
  * The local sides of any remote forwards are stored in this array to prevent   * The local sides of any remote forwards are stored in this array to prevent
Line 100 
Line 105 
 /* XXX: streamlocal wants a path instead of host:port */  /* XXX: streamlocal wants a path instead of host:port */
 /*      Overload host_to_connect; we could just make this match Forward */  /*      Overload host_to_connect; we could just make this match Forward */
 /*      XXX - can we use listen_host instead of listen_path? */  /*      XXX - can we use listen_host instead of listen_path? */
 typedef struct {  struct permission {
         char *host_to_connect;          /* Connect to 'host'. */          char *host_to_connect;          /* Connect to 'host'. */
         int 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. */
         char *listen_path;              /* Remote side should listen path. */          char *listen_path;              /* Remote side should listen path. */
         int listen_port;                /* Remote side should listen port. */          int listen_port;                /* Remote side should listen port. */
         Channel *downstream;            /* Downstream mux*/          Channel *downstream;            /* Downstream mux*/
 } ForwardPermission;  };
   
 typedef void chan_fn(struct ssh *, Channel *c,  /*
     fd_set *readset, fd_set *writeset);   * Stores the forwarding permission state for a single direction (local or
    * remote).
    */
   struct permission_set {
           /*
            * List of all local permitted host/port pairs to allow for the
            * user.
            */
           u_int num_permitted_user;
           struct permission *permitted_user;
   
           /*
            * List of all permitted host/port pairs to allow for the admin.
            */
           u_int num_permitted_admin;
           struct permission *permitted_admin;
   
           /*
            * If this is true, all opens/listens are permitted.  This is the
            * case on the server on which we have to trust the client anyway,
            * and the user could do anything after logging in.
            */
           int all_permitted;
   };
   
 /* Master structure for channels state */  /* Master structure for channels state */
 struct ssh_channels {  struct ssh_channels {
         /*          /*
Line 143 
Line 171 
         chan_fn **channel_post;          chan_fn **channel_post;
   
         /* -- tcp forwarding */          /* -- tcp forwarding */
           struct permission_set local_perms;
           struct permission_set remote_perms;
   
         /* List of all permitted host/port pairs to connect by the user. */  
         ForwardPermission *permitted_opens;  
   
         /* List of all permitted host/port pairs to connect by the admin. */  
         ForwardPermission *permitted_adm_opens;  
   
         /*  
          * Number of permitted host/port pairs in the array permitted by  
          * the user.  
          */  
         u_int num_permitted_opens;  
   
         /*  
          * Number of permitted host/port pair in the array permitted by  
          * the admin.  
          */  
         u_int num_adm_permitted_opens;  
   
         /*  
          * If this is true, all opens are permitted.  This is the case on  
          * the server on which we have to trust the client anyway, and the  
          * user could do anything after logging in anyway.  
          */  
         int all_opens_permitted;  
   
         /* -- X11 forwarding */          /* -- X11 forwarding */
   
         /* Saved X11 local (client) display. */          /* Saved X11 local (client) display. */
Line 438 
Line 443 
 }  }
   
 static void  static void
 fwd_perm_clear(ForwardPermission *fp)  fwd_perm_clear(struct permission *perm)
 {  {
         free(fp->host_to_connect);          free(perm->host_to_connect);
         free(fp->listen_host);          free(perm->listen_host);
         free(fp->listen_path);          free(perm->listen_path);
         bzero(fp, sizeof(*fp));          bzero(perm, sizeof(*perm));
 }  }
   
 enum { FWDPERM_USER, FWDPERM_ADMIN };  /* Returns an printable name for the specified forwarding permission list */
   static const char *
   fwd_ident(int who, int where)
   {
           if (who == FORWARD_ADM) {
                   if (where == FORWARD_LOCAL)
                           return "admin local";
                   else if (where == FORWARD_REMOTE)
                           return "admin remote";
           } else if (who == FORWARD_USER) {
                   if (where == FORWARD_LOCAL)
                           return "user local";
                   else if (where == FORWARD_REMOTE)
                           return "user remote";
           }
           fatal("Unknown forward permission list %d/%d", who, where);
   }
   
 static int  /* Returns the forwarding permission list for the specified direction */
 fwd_perm_list_add(struct ssh *ssh, int which,  static struct permission_set *
     const char *host_to_connect, int port_to_connect,  permission_set_get(struct ssh *ssh, int where)
     const char *listen_host, const char *listen_path, int listen_port,  
     Channel *downstream)  
 {  {
         ForwardPermission **fpl;          struct ssh_channels *sc = ssh->chanctxt;
         u_int n, *nfpl;  
   
         switch (which) {          switch (where) {
         case FWDPERM_USER:          case FORWARD_LOCAL:
                 fpl = &ssh->chanctxt->permitted_opens;                  return &sc->local_perms;
                 nfpl = &ssh->chanctxt->num_permitted_opens;  
                 break;                  break;
         case FWDPERM_ADMIN:          case FORWARD_REMOTE:
                 fpl = &ssh->chanctxt->permitted_adm_opens;                  return &sc->remote_perms;
                 nfpl = &ssh->chanctxt->num_adm_permitted_opens;  
                 break;                  break;
         default:          default:
                 fatal("%s: invalid list %d", __func__, which);                  fatal("%s: invalid forwarding direction %d", __func__, where);
         }          }
   }
   
         if (*nfpl >= INT_MAX)  /* Reutrns pointers to the specified forwarding list and its element count */
                 fatal("%s: overflow", __func__);  static void
   permission_set_get_array(struct ssh *ssh, int who, int where,
       struct permission ***permpp, u_int **npermpp)
   {
           struct permission_set *pset = permission_set_get(ssh, where);
   
         *fpl = xrecallocarray(*fpl, *nfpl, *nfpl + 1, sizeof(**fpl));          switch (who) {
         n = (*nfpl)++;          case FORWARD_USER:
                   *permpp = &pset->permitted_user;
                   *npermpp = &pset->num_permitted_user;
                   break;
           case FORWARD_ADM:
                   *permpp = &pset->permitted_admin;
                   *npermpp = &pset->num_permitted_admin;
                   break;
           default:
                   fatal("%s: invalid forwarding client %d", __func__, who);
           }
   }
   
   /* Adds an entry to the spcified forwarding list */
   static int
   permission_set_add(struct ssh *ssh, int who, int where,
       const char *host_to_connect, int port_to_connect,
       const char *listen_host, const char *listen_path, int listen_port,
       Channel *downstream)
   {
           struct permission **permp;
           u_int n, *npermp;
   
           permission_set_get_array(ssh, who, where, &permp, &npermp);
   
           if (*npermp >= INT_MAX)
                   fatal("%s: %s overflow", __func__, fwd_ident(who, where));
   
           *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
           n = (*npermp)++;
 #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s))  #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s))
         (*fpl)[n].host_to_connect = MAYBE_DUP(host_to_connect);          (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);
         (*fpl)[n].port_to_connect = port_to_connect;          (*permp)[n].port_to_connect = port_to_connect;
         (*fpl)[n].listen_host = MAYBE_DUP(listen_host);          (*permp)[n].listen_host = MAYBE_DUP(listen_host);
         (*fpl)[n].listen_path = MAYBE_DUP(listen_path);          (*permp)[n].listen_path = MAYBE_DUP(listen_path);
         (*fpl)[n].listen_port = listen_port;          (*permp)[n].listen_port = listen_port;
         (*fpl)[n].downstream = downstream;          (*permp)[n].downstream = downstream;
 #undef MAYBE_DUP  #undef MAYBE_DUP
         return (int)n;          return (int)n;
 }  }
Line 490 
Line 540 
 mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)  mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
         ForwardPermission *fp;          struct permission_set *pset = &sc->local_perms;
           struct permission *perm;
         int r;          int r;
         u_int i;          u_int i;
   
         for (i = 0; i < sc->num_permitted_opens; i++) {          for (i = 0; i < pset->num_permitted_user; i++) {
                 fp = &sc->permitted_opens[i];                  perm = &pset->permitted_user[i];
                 if (fp->downstream != c)                  if (perm->downstream != c)
                         continue;                          continue;
   
                 /* cancel on the server, since mux client is gone */                  /* cancel on the server, since mux client is gone */
                 debug("channel %d: cleanup remote forward for %s:%u",                  debug("channel %d: cleanup remote forward for %s:%u",
                     c->self, fp->listen_host, fp->listen_port);                      c->self, perm->listen_host, perm->listen_port);
                 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||                  if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
                     (r = sshpkt_put_cstring(ssh,                      (r = sshpkt_put_cstring(ssh,
                     "cancel-tcpip-forward")) != 0 ||                      "cancel-tcpip-forward")) != 0 ||
                     (r = sshpkt_put_u8(ssh, 0)) != 0 ||                      (r = sshpkt_put_u8(ssh, 0)) != 0 ||
                     (r = sshpkt_put_cstring(ssh,                      (r = sshpkt_put_cstring(ssh,
                     channel_rfwd_bind_host(fp->listen_host))) != 0 ||                      channel_rfwd_bind_host(perm->listen_host))) != 0 ||
                     (r = sshpkt_put_u32(ssh, fp->listen_port)) != 0 ||                      (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
                     (r = sshpkt_send(ssh)) != 0) {                      (r = sshpkt_send(ssh)) != 0) {
                         fatal("%s: channel %i: %s", __func__,                          fatal("%s: channel %i: %s", __func__,
                             c->self, ssh_err(r));                              c->self, ssh_err(r));
                 }                  }
                 fwd_perm_clear(fp); /* unregister */                  fwd_perm_clear(perm); /* unregister */
         }          }
 }  }
   
Line 2698 
Line 2749 
                         goto out;                          goto out;
                 }                  }
                 /* Record that connection to this host/port is permitted. */                  /* Record that connection to this host/port is permitted. */
                 fwd_perm_list_add(ssh, FWDPERM_USER, "<mux>", -1,                  permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1,
                     listen_host, NULL, (int)listen_port, downstream);                      listen_host, NULL, (int)listen_port, downstream);
                 listen_host = NULL;                  listen_host = NULL;
                 break;                  break;
Line 3598 
Line 3649 
         }          }
 }  }
   
   /* Matches a remote forwarding permission against a requested forwarding */
   static int
   remote_open_match(struct permission *allowed_open, struct Forward *fwd)
   {
           int ret;
           char *lhost;
   
           /* XXX add ACLs for streamlocal */
           if (fwd->listen_path != NULL)
                   return 1;
   
           if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)
                   return 0;
   
           if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&
               allowed_open->listen_port != fwd->listen_port)
                   return 0;
   
           /* Match hostnames case-insensitively */
           lhost = xstrdup(fwd->listen_host);
           lowercase(lhost);
           ret = match_pattern(lhost, allowed_open->listen_host);
           free(lhost);
   
           return ret;
   }
   
   /* Checks whether a requested remote forwarding is permitted */
   static int
   check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
   {
           struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->remote_perms;
           u_int i, permit, permit_adm = 1;
           struct permission *perm;
   
           /* XXX apply GatewayPorts override before checking? */
   
           permit = pset->all_permitted;
           if (!permit) {
                   for (i = 0; i < pset->num_permitted_user; i++) {
                           perm = &pset->permitted_user[i];
                           if (remote_open_match(perm, fwd)) {
                                   permit = 1;
                                   break;
                           }
                   }
           }
   
           if (pset->num_permitted_admin > 0) {
                   permit_adm = 0;
                   for (i = 0; i < pset->num_permitted_admin; i++) {
                           perm = &pset->permitted_admin[i];
                           if (remote_open_match(perm, fwd)) {
                                   permit_adm = 1;
                                   break;
                           }
                   }
           }
   
           return permit && permit_adm;
   }
   
 /* protocol v2 remote port fwd, used by sshd */  /* protocol v2 remote port fwd, used by sshd */
 int  int
 channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,  channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
     int *allocated_listen_port, struct ForwardOptions *fwd_opts)      int *allocated_listen_port, struct ForwardOptions *fwd_opts)
 {  {
           if (!check_rfwd_permission(ssh, fwd)) {
                   packet_send_debug("port forwarding refused");
                   return 0;
           }
         if (fwd->listen_path != NULL) {          if (fwd->listen_path != NULL) {
                 return channel_setup_fwd_listener_streamlocal(ssh,                  return channel_setup_fwd_listener_streamlocal(ssh,
                     SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);                      SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
Line 3632 
Line 3750 
  * 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.
  * Returns handle (index) for updating the dynamic listen port with   * Returns handle (index) for updating the dynamic listen port with
  * channel_update_permitted_opens().   * channel_update_permission().
  */   */
 int  int
 channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)  channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
Line 3685 
Line 3803 
                                 listen_host = xstrdup(fwd->listen_host);                                  listen_host = xstrdup(fwd->listen_host);
                         listen_port = fwd->listen_port;                          listen_port = fwd->listen_port;
                 }                  }
                 idx = fwd_perm_list_add(ssh, FWDPERM_USER,                  idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL,
                     host_to_connect, port_to_connect,                      host_to_connect, port_to_connect,
                     listen_host, listen_path, listen_port, NULL);                      listen_host, listen_path, listen_port, NULL);
         }          }
Line 3693 
Line 3811 
 }  }
   
 static int  static int
 open_match(ForwardPermission *allowed_open, const char *requestedhost,  open_match(struct permission *allowed_open, const char *requestedhost,
     int requestedport)      int requestedport)
 {  {
         if (allowed_open->host_to_connect == NULL)          if (allowed_open->host_to_connect == NULL)
Line 3714 
Line 3832 
  * 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_tcpip(ForwardPermission *allowed_open,  open_listen_match_tcpip(struct permission *allowed_open,
     const char *requestedhost, u_short requestedport, int translate)      const char *requestedhost, u_short requestedport, int translate)
 {  {
         const char *allowed_host;          const char *allowed_host;
Line 3736 
Line 3854 
 }  }
   
 static int  static int
 open_listen_match_streamlocal(ForwardPermission *allowed_open,  open_listen_match_streamlocal(struct permission *allowed_open,
     const char *requestedpath)      const char *requestedpath)
 {  {
         if (allowed_open->host_to_connect == NULL)          if (allowed_open->host_to_connect == NULL)
Line 3758 
Line 3876 
     const char *host, u_short port)      const char *host, u_short port)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         int r;          int r;
         u_int i;          u_int i;
         ForwardPermission *fp;          struct permission *perm;
   
         for (i = 0; i < sc->num_permitted_opens; i++) {          for (i = 0; i < pset->num_permitted_user; i++) {
                 fp = &sc->permitted_opens[i];                  perm = &pset->permitted_user[i];
                 if (open_listen_match_tcpip(fp, host, port, 0))                  if (open_listen_match_tcpip(perm, host, port, 0))
                         break;                          break;
                 fp = NULL;                  perm = NULL;
         }          }
         if (fp == NULL) {          if (perm == NULL) {
                 debug("%s: requested forward not found", __func__);                  debug("%s: requested forward not found", __func__);
                 return -1;                  return -1;
         }          }
Line 3780 
Line 3899 
             (r = sshpkt_send(ssh)) != 0)              (r = sshpkt_send(ssh)) != 0)
                 fatal("%s: send cancel: %s", __func__, ssh_err(r));                  fatal("%s: send cancel: %s", __func__, ssh_err(r));
   
         fwd_perm_clear(fp); /* unregister */          fwd_perm_clear(perm); /* unregister */
   
         return 0;          return 0;
 }  }
Line 3793 
Line 3912 
 channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)  channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         int r;          int r;
         u_int i;          u_int i;
         ForwardPermission *fp;          struct permission *perm;
   
         for (i = 0; i < sc->num_permitted_opens; i++) {          for (i = 0; i < pset->num_permitted_user; i++) {
                 fp = &sc->permitted_opens[i];                  perm = &pset->permitted_user[i];
                 if (open_listen_match_streamlocal(fp, path))                  if (open_listen_match_streamlocal(perm, path))
                         break;                          break;
                 fp = NULL;                  perm = NULL;
         }          }
         if (fp == NULL) {          if (perm == NULL) {
                 debug("%s: requested forward not found", __func__);                  debug("%s: requested forward not found", __func__);
                 return -1;                  return -1;
         }          }
Line 3815 
Line 3935 
             (r = sshpkt_send(ssh)) != 0)              (r = sshpkt_send(ssh)) != 0)
                 fatal("%s: send cancel: %s", __func__, ssh_err(r));                  fatal("%s: send cancel: %s", __func__, ssh_err(r));
   
         fwd_perm_clear(fp); /* unregister */          fwd_perm_clear(perm); /* unregister */
   
         return 0;          return 0;
 }  }
Line 3837 
Line 3957 
 }  }
   
 /*  /*
  * Permits opening to any host/port if permitted_opens[] is empty.  This is   * Permits opening to any host/port if permitted_user[] is empty.  This is
  * usually called by the server, because the user could connect to any port   * usually called by the server, because the user could connect to any port
  * anyway, and the server has no way to know but to trust the client anyway.   * anyway, and the server has no way to know but to trust the client anyway.
  */   */
 void  void
 channel_permit_all_opens(struct ssh *ssh)  channel_permit_all(struct ssh *ssh, int where)
 {  {
         if (ssh->chanctxt->num_permitted_opens == 0)          struct permission_set *pset = permission_set_get(ssh, where);
                 ssh->chanctxt->all_opens_permitted = 1;  
           if (pset->num_permitted_user == 0)
                   pset->all_permitted = 1;
 }  }
   
   /*
    * Permit the specified host/port for forwarding.
    */
 void  void
 channel_add_permitted_opens(struct ssh *ssh, char *host, int port)  channel_add_permission(struct ssh *ssh, int who, int where,
       char *host, int port)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          int local = where == FORWARD_LOCAL;
           struct permission_set *pset = permission_set_get(ssh, where);
   
         debug("allow port forwarding to host %s port %d", host, port);          debug("allow %s forwarding to host %s port %d",
         fwd_perm_list_add(ssh, FWDPERM_USER, host, port, NULL, NULL, 0, NULL);              fwd_ident(who, where), host, port);
         sc->all_opens_permitted = 0;          /*
            * Remote forwards set listen_host/port, local forwards set
            * host/port_to_connect.
            */
           permission_set_add(ssh, who, where,
               local ? host : 0, local ? port : 0,
               local ? NULL : host, NULL, local ? 0 : port, NULL);
           pset->all_permitted = 0;
 }  }
   
 /*  /*
    * Administratively disable forwarding.
    */
   void
   channel_disable_admin(struct ssh *ssh, int where)
   {
           channel_clear_permission(ssh, FORWARD_ADM, where);
           permission_set_add(ssh, FORWARD_ADM, where,
               NULL, 0, NULL, NULL, 0, NULL);
   }
   
   /*
    * Clear a list of permitted opens.
    */
   void
   channel_clear_permission(struct ssh *ssh, int who, int where)
   {
           struct permission **permp;
           u_int *npermp;
   
           permission_set_get_array(ssh, who, where, &permp, &npermp);
           *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
           *npermp = 0;
   }
   
   /*
  * Update the listen port for a dynamic remote forward, after   * Update the listen port for a dynamic remote forward, after
  * the actual 'newport' has been allocated. If 'newport' < 0 is   * the actual 'newport' has been allocated. If 'newport' < 0 is
  * passed then they entry will be invalidated.   * passed then they entry will be invalidated.
  */   */
 void  void
 channel_update_permitted_opens(struct ssh *ssh, int idx, int newport)  channel_update_permission(struct ssh *ssh, int idx, int newport)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct permission_set *pset = &ssh->chanctxt->local_perms;
   
         if (idx < 0 || (u_int)idx >= sc->num_permitted_opens) {          if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
                 debug("%s: index out of range: %d num_permitted_opens %d",                  debug("%s: index out of range: %d num_permitted_user %d",
                     __func__, idx, sc->num_permitted_opens);                      __func__, idx, pset->num_permitted_user);
                 return;                  return;
         }          }
         debug("%s allowed port %d for forwarding to host %s port %d",          debug("%s allowed port %d for forwarding to host %s port %d",
             newport > 0 ? "Updating" : "Removing",              newport > 0 ? "Updating" : "Removing",
             newport,              newport,
             sc->permitted_opens[idx].host_to_connect,              pset->permitted_user[idx].host_to_connect,
             sc->permitted_opens[idx].port_to_connect);              pset->permitted_user[idx].port_to_connect);
         if (newport <= 0)          if (newport <= 0)
                 fwd_perm_clear(&sc->permitted_opens[idx]);                  fwd_perm_clear(&pset->permitted_user[idx]);
         else {          else {
                 sc->permitted_opens[idx].listen_port =                  pset->permitted_user[idx].listen_port =
                     (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;                      (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
         }          }
 }  }
   
 int  
 channel_add_adm_permitted_opens(struct ssh *ssh, char *host, int port)  
 {  
         debug("config allows port forwarding to host %s port %d", host, port);  
         return fwd_perm_list_add(ssh, FWDPERM_ADMIN, host, port,  
             NULL, NULL, 0, NULL);  
 }  
   
 void  
 channel_disable_adm_local_opens(struct ssh *ssh)  
 {  
         channel_clear_adm_permitted_opens(ssh);  
         fwd_perm_list_add(ssh, FWDPERM_ADMIN, NULL, 0, NULL, NULL, 0, NULL);  
 }  
   
 void  
 channel_clear_permitted_opens(struct ssh *ssh)  
 {  
         struct ssh_channels *sc = ssh->chanctxt;  
   
         sc->permitted_opens = xrecallocarray(sc->permitted_opens,  
             sc->num_permitted_opens, 0, sizeof(*sc->permitted_opens));  
         sc->num_permitted_opens = 0;  
 }  
   
 void  
 channel_clear_adm_permitted_opens(struct ssh *ssh)  
 {  
         struct ssh_channels *sc = ssh->chanctxt;  
   
         sc->permitted_adm_opens = xrecallocarray(sc->permitted_adm_opens,  
             sc->num_adm_permitted_opens, 0, sizeof(*sc->permitted_adm_opens));  
         sc->num_adm_permitted_opens = 0;  
 }  
   
 /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */  /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
 int  int
 permitopen_port(const char *p)  permitopen_port(const char *p)
Line 4109 
Line 4233 
     u_short listen_port, char *ctype, char *rname)      u_short listen_port, char *ctype, char *rname)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         u_int i;          u_int i;
         ForwardPermission *fp;          struct permission *perm;
   
         for (i = 0; i < sc->num_permitted_opens; i++) {          for (i = 0; i < pset->num_permitted_user; i++) {
                 fp = &sc->permitted_opens[i];                  perm = &pset->permitted_user[i];
                 if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) {                  if (open_listen_match_tcpip(perm,
                         if (fp->downstream)                      listen_host, listen_port, 1)) {
                                 return fp->downstream;                          if (perm->downstream)
                         if (fp->port_to_connect == 0)                                  return perm->downstream;
                           if (perm->port_to_connect == 0)
                                 return rdynamic_connect_prepare(ssh,                                  return rdynamic_connect_prepare(ssh,
                                     ctype, rname);                                      ctype, rname);
                         return connect_to(ssh,                          return connect_to(ssh,
                             fp->host_to_connect, fp->port_to_connect,                              perm->host_to_connect, perm->port_to_connect,
                             ctype, rname);                              ctype, rname);
                 }                  }
         }          }
Line 4135 
Line 4261 
     char *ctype, char *rname)      char *ctype, char *rname)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         u_int i;          u_int i;
         ForwardPermission *fp;          struct permission *perm;
   
         for (i = 0; i < sc->num_permitted_opens; i++) {          for (i = 0; i < pset->num_permitted_user; i++) {
                 fp = &sc->permitted_opens[i];                  perm = &pset->permitted_user[i];
                 if (open_listen_match_streamlocal(fp, path)) {                  if (open_listen_match_streamlocal(perm, path)) {
                         return connect_to(ssh,                          return connect_to(ssh,
                             fp->host_to_connect, fp->port_to_connect,                              perm->host_to_connect, perm->port_to_connect,
                             ctype, rname);                              ctype, rname);
                 }                  }
         }          }
Line 4157 
Line 4284 
     char *ctype, char *rname, int *reason, const char **errmsg)      char *ctype, char *rname, int *reason, const char **errmsg)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         struct channel_connect cctx;          struct channel_connect cctx;
         Channel *c;          Channel *c;
         u_int i, permit, permit_adm = 1;          u_int i, permit, permit_adm = 1;
         int sock;          int sock;
         ForwardPermission *fp;          struct permission *perm;
   
         permit = sc->all_opens_permitted;          permit = pset->all_permitted;
         if (!permit) {          if (!permit) {
                 for (i = 0; i < sc->num_permitted_opens; i++) {                  for (i = 0; i < pset->num_permitted_user; i++) {
                         fp = &sc->permitted_opens[i];                          perm = &pset->permitted_user[i];
                         if (open_match(fp, host, port)) {                          if (open_match(perm, host, port)) {
                                 permit = 1;                                  permit = 1;
                                 break;                                  break;
                         }                          }
                 }                  }
         }          }
   
         if (sc->num_adm_permitted_opens > 0) {          if (pset->num_permitted_admin > 0) {
                 permit_adm = 0;                  permit_adm = 0;
                 for (i = 0; i < sc->num_adm_permitted_opens; i++) {                  for (i = 0; i < pset->num_permitted_admin; i++) {
                         fp = &sc->permitted_adm_opens[i];                          perm = &pset->permitted_admin[i];
                         if (open_match(fp, host, port)) {                          if (open_match(perm, host, port)) {
                                 permit_adm = 1;                                  permit_adm = 1;
                                 break;                                  break;
                         }                          }
Line 4216 
Line 4344 
     char *ctype, char *rname)      char *ctype, char *rname)
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
           struct permission_set *pset = &sc->local_perms;
         u_int i, permit, permit_adm = 1;          u_int i, permit, permit_adm = 1;
         ForwardPermission *fp;          struct permission *perm;
   
         permit = sc->all_opens_permitted;          permit = pset->all_permitted;
         if (!permit) {          if (!permit) {
                 for (i = 0; i < sc->num_permitted_opens; i++) {                  for (i = 0; i < pset->num_permitted_user; i++) {
                         fp = &sc->permitted_opens[i];                          perm = &pset->permitted_user[i];
                         if (open_match(fp, path, PORT_STREAMLOCAL)) {                          if (open_match(perm, path, PORT_STREAMLOCAL)) {
                                 permit = 1;                                  permit = 1;
                                 break;                                  break;
                         }                          }
                 }                  }
         }          }
   
         if (sc->num_adm_permitted_opens > 0) {          if (pset->num_permitted_admin > 0) {
                 permit_adm = 0;                  permit_adm = 0;
                 for (i = 0; i < sc->num_adm_permitted_opens; i++) {                  for (i = 0; i < pset->num_permitted_admin; i++) {
                         fp = &sc->permitted_adm_opens[i];                          perm = &pset->permitted_admin[i];
                         if (open_match(fp, path, PORT_STREAMLOCAL)) {                          if (open_match(perm, path, PORT_STREAMLOCAL)) {
                                 permit_adm = 1;                                  permit_adm = 1;
                                 break;                                  break;
                         }                          }

Legend:
Removed from v.1.380  
changed lines
  Added in v.1.381