summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2018-08-24 12:49:36 +0100
committerColin Watson <cjwatson@debian.org>2018-08-24 12:49:36 +0100
commite6547182a54f0f268ee36e7c99319eeddffbaff2 (patch)
tree417527229ad3f3764ba71ea383f478a168895087 /channels.c
parented6ae9c1a014a08ff5db3d768f01f2e427eeb476 (diff)
parent71508e06fab14bc415a79a08f5535ad7bffa93d9 (diff)
Import openssh_7.8p1.orig.tar.gz
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c495
1 files changed, 313 insertions, 182 deletions
diff --git a/channels.c b/channels.c
index bdee1f386..e90f7fea9 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.379 2018/02/05 05:36:49 tb Exp $ */ 1/* $OpenBSD: channels.c,v 1.384 2018/07/27 12:03:17 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -79,9 +79,10 @@
79#include "channels.h" 79#include "channels.h"
80#include "compat.h" 80#include "compat.h"
81#include "canohost.h" 81#include "canohost.h"
82#include "key.h" 82#include "sshkey.h"
83#include "authfd.h" 83#include "authfd.h"
84#include "pathnames.h" 84#include "pathnames.h"
85#include "match.h"
85 86
86/* -- agent forwarding */ 87/* -- agent forwarding */
87#define NUM_SOCKS 10 88#define NUM_SOCKS 10
@@ -97,6 +98,10 @@
97/* Maximum number of fake X11 displays to try. */ 98/* Maximum number of fake X11 displays to try. */
98#define MAX_DISPLAYS 1000 99#define MAX_DISPLAYS 1000
99 100
101/* Per-channel callback for pre/post select() actions */
102typedef void chan_fn(struct ssh *, Channel *c,
103 fd_set *readset, fd_set *writeset);
104
100/* 105/*
101 * Data structure for storing which hosts are permitted for forward requests. 106 * Data structure for storing which hosts are permitted for forward requests.
102 * The local sides of any remote forwards are stored in this array to prevent 107 * The local sides of any remote forwards are stored in this array to prevent
@@ -106,17 +111,40 @@
106/* XXX: streamlocal wants a path instead of host:port */ 111/* XXX: streamlocal wants a path instead of host:port */
107/* Overload host_to_connect; we could just make this match Forward */ 112/* Overload host_to_connect; we could just make this match Forward */
108/* XXX - can we use listen_host instead of listen_path? */ 113/* XXX - can we use listen_host instead of listen_path? */
109typedef struct { 114struct permission {
110 char *host_to_connect; /* Connect to 'host'. */ 115 char *host_to_connect; /* Connect to 'host'. */
111 int port_to_connect; /* Connect to 'port'. */ 116 int port_to_connect; /* Connect to 'port'. */
112 char *listen_host; /* Remote side should listen address. */ 117 char *listen_host; /* Remote side should listen address. */
113 char *listen_path; /* Remote side should listen path. */ 118 char *listen_path; /* Remote side should listen path. */
114 int listen_port; /* Remote side should listen port. */ 119 int listen_port; /* Remote side should listen port. */
115 Channel *downstream; /* Downstream mux*/ 120 Channel *downstream; /* Downstream mux*/
116} ForwardPermission; 121};
117 122
118typedef void chan_fn(struct ssh *, Channel *c, 123/*
119 fd_set *readset, fd_set *writeset); 124 * Stores the forwarding permission state for a single direction (local or
125 * remote).
126 */
127struct permission_set {
128 /*
129 * List of all local permitted host/port pairs to allow for the
130 * user.
131 */
132 u_int num_permitted_user;
133 struct permission *permitted_user;
134
135 /*
136 * List of all permitted host/port pairs to allow for the admin.
137 */
138 u_int num_permitted_admin;
139 struct permission *permitted_admin;
140
141 /*
142 * If this is true, all opens/listens are permitted. This is the
143 * case on the server on which we have to trust the client anyway,
144 * and the user could do anything after logging in.
145 */
146 int all_permitted;
147};
120 148
121/* Master structure for channels state */ 149/* Master structure for channels state */
122struct ssh_channels { 150struct ssh_channels {
@@ -149,31 +177,8 @@ struct ssh_channels {
149 chan_fn **channel_post; 177 chan_fn **channel_post;
150 178
151 /* -- tcp forwarding */ 179 /* -- tcp forwarding */
152 180 struct permission_set local_perms;
153 /* List of all permitted host/port pairs to connect by the user. */ 181 struct permission_set remote_perms;
154 ForwardPermission *permitted_opens;
155
156 /* List of all permitted host/port pairs to connect by the admin. */
157 ForwardPermission *permitted_adm_opens;
158
159 /*
160 * Number of permitted host/port pairs in the array permitted by
161 * the user.
162 */
163 u_int num_permitted_opens;
164
165 /*
166 * Number of permitted host/port pair in the array permitted by
167 * the admin.
168 */
169 u_int num_adm_permitted_opens;
170
171 /*
172 * If this is true, all opens are permitted. This is the case on
173 * the server on which we have to trust the client anyway, and the
174 * user could do anything after logging in anyway.
175 */
176 int all_opens_permitted;
177 182
178 /* -- X11 forwarding */ 183 /* -- X11 forwarding */
179 184
@@ -448,50 +453,95 @@ channel_close_fds(struct ssh *ssh, Channel *c)
448} 453}
449 454
450static void 455static void
451fwd_perm_clear(ForwardPermission *fp) 456fwd_perm_clear(struct permission *perm)
452{ 457{
453 free(fp->host_to_connect); 458 free(perm->host_to_connect);
454 free(fp->listen_host); 459 free(perm->listen_host);
455 free(fp->listen_path); 460 free(perm->listen_path);
456 bzero(fp, sizeof(*fp)); 461 bzero(perm, sizeof(*perm));
457} 462}
458 463
459enum { FWDPERM_USER, FWDPERM_ADMIN }; 464/* Returns an printable name for the specified forwarding permission list */
465static const char *
466fwd_ident(int who, int where)
467{
468 if (who == FORWARD_ADM) {
469 if (where == FORWARD_LOCAL)
470 return "admin local";
471 else if (where == FORWARD_REMOTE)
472 return "admin remote";
473 } else if (who == FORWARD_USER) {
474 if (where == FORWARD_LOCAL)
475 return "user local";
476 else if (where == FORWARD_REMOTE)
477 return "user remote";
478 }
479 fatal("Unknown forward permission list %d/%d", who, where);
480}
460 481
461static int 482/* Returns the forwarding permission list for the specified direction */
462fwd_perm_list_add(struct ssh *ssh, int which, 483static struct permission_set *
463 const char *host_to_connect, int port_to_connect, 484permission_set_get(struct ssh *ssh, int where)
464 const char *listen_host, const char *listen_path, int listen_port,
465 Channel *downstream)
466{ 485{
467 ForwardPermission **fpl; 486 struct ssh_channels *sc = ssh->chanctxt;
468 u_int n, *nfpl;
469 487
470 switch (which) { 488 switch (where) {
471 case FWDPERM_USER: 489 case FORWARD_LOCAL:
472 fpl = &ssh->chanctxt->permitted_opens; 490 return &sc->local_perms;
473 nfpl = &ssh->chanctxt->num_permitted_opens;
474 break; 491 break;
475 case FWDPERM_ADMIN: 492 case FORWARD_REMOTE:
476 fpl = &ssh->chanctxt->permitted_adm_opens; 493 return &sc->remote_perms;
477 nfpl = &ssh->chanctxt->num_adm_permitted_opens;
478 break; 494 break;
479 default: 495 default:
480 fatal("%s: invalid list %d", __func__, which); 496 fatal("%s: invalid forwarding direction %d", __func__, where);
481 } 497 }
498}
482 499
483 if (*nfpl >= INT_MAX) 500/* Reutrns pointers to the specified forwarding list and its element count */
484 fatal("%s: overflow", __func__); 501static void
502permission_set_get_array(struct ssh *ssh, int who, int where,
503 struct permission ***permpp, u_int **npermpp)
504{
505 struct permission_set *pset = permission_set_get(ssh, where);
485 506
486 *fpl = xrecallocarray(*fpl, *nfpl, *nfpl + 1, sizeof(**fpl)); 507 switch (who) {
487 n = (*nfpl)++; 508 case FORWARD_USER:
509 *permpp = &pset->permitted_user;
510 *npermpp = &pset->num_permitted_user;
511 break;
512 case FORWARD_ADM:
513 *permpp = &pset->permitted_admin;
514 *npermpp = &pset->num_permitted_admin;
515 break;
516 default:
517 fatal("%s: invalid forwarding client %d", __func__, who);
518 }
519}
520
521/* Adds an entry to the spcified forwarding list */
522static int
523permission_set_add(struct ssh *ssh, int who, int where,
524 const char *host_to_connect, int port_to_connect,
525 const char *listen_host, const char *listen_path, int listen_port,
526 Channel *downstream)
527{
528 struct permission **permp;
529 u_int n, *npermp;
530
531 permission_set_get_array(ssh, who, where, &permp, &npermp);
532
533 if (*npermp >= INT_MAX)
534 fatal("%s: %s overflow", __func__, fwd_ident(who, where));
535
536 *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
537 n = (*npermp)++;
488#define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) 538#define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s))
489 (*fpl)[n].host_to_connect = MAYBE_DUP(host_to_connect); 539 (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);
490 (*fpl)[n].port_to_connect = port_to_connect; 540 (*permp)[n].port_to_connect = port_to_connect;
491 (*fpl)[n].listen_host = MAYBE_DUP(listen_host); 541 (*permp)[n].listen_host = MAYBE_DUP(listen_host);
492 (*fpl)[n].listen_path = MAYBE_DUP(listen_path); 542 (*permp)[n].listen_path = MAYBE_DUP(listen_path);
493 (*fpl)[n].listen_port = listen_port; 543 (*permp)[n].listen_port = listen_port;
494 (*fpl)[n].downstream = downstream; 544 (*permp)[n].downstream = downstream;
495#undef MAYBE_DUP 545#undef MAYBE_DUP
496 return (int)n; 546 return (int)n;
497} 547}
@@ -500,30 +550,31 @@ static void
500mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) 550mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
501{ 551{
502 struct ssh_channels *sc = ssh->chanctxt; 552 struct ssh_channels *sc = ssh->chanctxt;
503 ForwardPermission *fp; 553 struct permission_set *pset = &sc->local_perms;
554 struct permission *perm;
504 int r; 555 int r;
505 u_int i; 556 u_int i;
506 557
507 for (i = 0; i < sc->num_permitted_opens; i++) { 558 for (i = 0; i < pset->num_permitted_user; i++) {
508 fp = &sc->permitted_opens[i]; 559 perm = &pset->permitted_user[i];
509 if (fp->downstream != c) 560 if (perm->downstream != c)
510 continue; 561 continue;
511 562
512 /* cancel on the server, since mux client is gone */ 563 /* cancel on the server, since mux client is gone */
513 debug("channel %d: cleanup remote forward for %s:%u", 564 debug("channel %d: cleanup remote forward for %s:%u",
514 c->self, fp->listen_host, fp->listen_port); 565 c->self, perm->listen_host, perm->listen_port);
515 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || 566 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
516 (r = sshpkt_put_cstring(ssh, 567 (r = sshpkt_put_cstring(ssh,
517 "cancel-tcpip-forward")) != 0 || 568 "cancel-tcpip-forward")) != 0 ||
518 (r = sshpkt_put_u8(ssh, 0)) != 0 || 569 (r = sshpkt_put_u8(ssh, 0)) != 0 ||
519 (r = sshpkt_put_cstring(ssh, 570 (r = sshpkt_put_cstring(ssh,
520 channel_rfwd_bind_host(fp->listen_host))) != 0 || 571 channel_rfwd_bind_host(perm->listen_host))) != 0 ||
521 (r = sshpkt_put_u32(ssh, fp->listen_port)) != 0 || 572 (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
522 (r = sshpkt_send(ssh)) != 0) { 573 (r = sshpkt_send(ssh)) != 0) {
523 fatal("%s: channel %i: %s", __func__, 574 fatal("%s: channel %i: %s", __func__,
524 c->self, ssh_err(r)); 575 c->self, ssh_err(r));
525 } 576 }
526 fwd_perm_clear(fp); /* unregister */ 577 fwd_perm_clear(perm); /* unregister */
527 } 578 }
528} 579}
529 580
@@ -557,9 +608,11 @@ channel_free(struct ssh *ssh, Channel *c)
557 if (c->type == SSH_CHANNEL_MUX_CLIENT) 608 if (c->type == SSH_CHANNEL_MUX_CLIENT)
558 mux_remove_remote_forwardings(ssh, c); 609 mux_remove_remote_forwardings(ssh, c);
559 610
560 s = channel_open_message(ssh); 611 if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {
561 debug3("channel %d: status: %s", c->self, s); 612 s = channel_open_message(ssh);
562 free(s); 613 debug3("channel %d: status: %s", c->self, s);
614 free(s);
615 }
563 616
564 channel_close_fds(ssh, c); 617 channel_close_fds(ssh, c);
565 sshbuf_free(c->input); 618 sshbuf_free(c->input);
@@ -2599,7 +2652,7 @@ channel_output_poll(struct ssh *ssh)
2599 * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID 2652 * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
2600 * with the newly allocated channel ID. 2653 * with the newly allocated channel ID.
2601 * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY 2654 * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
2602 * channels and procesed by channel_proxy_upstream(). The local channel ID 2655 * channels and processed by channel_proxy_upstream(). The local channel ID
2603 * is then translated back to the original mux client ID. 2656 * is then translated back to the original mux client ID.
2604 * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE 2657 * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
2605 * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels. 2658 * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
@@ -2610,7 +2663,7 @@ channel_output_poll(struct ssh *ssh)
2610 * channel. E.g. client_request_forwarded_tcpip() needs to figure 2663 * channel. E.g. client_request_forwarded_tcpip() needs to figure
2611 * out whether the request is addressed to the local client or a 2664 * out whether the request is addressed to the local client or a
2612 * specific downstream client based on the listen-address/port. 2665 * specific downstream client based on the listen-address/port.
2613 * 6) Agent and X11-Forwarding have a similar problem and are currenly 2666 * 6) Agent and X11-Forwarding have a similar problem and are currently
2614 * not supported as the matching session/channel cannot be identified 2667 * not supported as the matching session/channel cannot be identified
2615 * easily. 2668 * easily.
2616 */ 2669 */
@@ -2729,7 +2782,7 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
2729 goto out; 2782 goto out;
2730 } 2783 }
2731 /* Record that connection to this host/port is permitted. */ 2784 /* Record that connection to this host/port is permitted. */
2732 fwd_perm_list_add(ssh, FWDPERM_USER, "<mux>", -1, 2785 permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1,
2733 listen_host, NULL, (int)listen_port, downstream); 2786 listen_host, NULL, (int)listen_port, downstream);
2734 listen_host = NULL; 2787 listen_host = NULL;
2735 break; 2788 break;
@@ -2787,7 +2840,7 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
2787 /* 2840 /*
2788 * When receiving packets from the peer we need to check whether we 2841 * When receiving packets from the peer we need to check whether we
2789 * need to forward the packets to the mux client. In this case we 2842 * need to forward the packets to the mux client. In this case we
2790 * restore the orignal channel id and keep track of CLOSE messages, 2843 * restore the original channel id and keep track of CLOSE messages,
2791 * so we can cleanup the channel. 2844 * so we can cleanup the channel.
2792 */ 2845 */
2793 if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY) 2846 if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)
@@ -3637,11 +3690,78 @@ channel_setup_local_fwd_listener(struct ssh *ssh,
3637 } 3690 }
3638} 3691}
3639 3692
3693/* Matches a remote forwarding permission against a requested forwarding */
3694static int
3695remote_open_match(struct permission *allowed_open, struct Forward *fwd)
3696{
3697 int ret;
3698 char *lhost;
3699
3700 /* XXX add ACLs for streamlocal */
3701 if (fwd->listen_path != NULL)
3702 return 1;
3703
3704 if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)
3705 return 0;
3706
3707 if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&
3708 allowed_open->listen_port != fwd->listen_port)
3709 return 0;
3710
3711 /* Match hostnames case-insensitively */
3712 lhost = xstrdup(fwd->listen_host);
3713 lowercase(lhost);
3714 ret = match_pattern(lhost, allowed_open->listen_host);
3715 free(lhost);
3716
3717 return ret;
3718}
3719
3720/* Checks whether a requested remote forwarding is permitted */
3721static int
3722check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
3723{
3724 struct ssh_channels *sc = ssh->chanctxt;
3725 struct permission_set *pset = &sc->remote_perms;
3726 u_int i, permit, permit_adm = 1;
3727 struct permission *perm;
3728
3729 /* XXX apply GatewayPorts override before checking? */
3730
3731 permit = pset->all_permitted;
3732 if (!permit) {
3733 for (i = 0; i < pset->num_permitted_user; i++) {
3734 perm = &pset->permitted_user[i];
3735 if (remote_open_match(perm, fwd)) {
3736 permit = 1;
3737 break;
3738 }
3739 }
3740 }
3741
3742 if (pset->num_permitted_admin > 0) {
3743 permit_adm = 0;
3744 for (i = 0; i < pset->num_permitted_admin; i++) {
3745 perm = &pset->permitted_admin[i];
3746 if (remote_open_match(perm, fwd)) {
3747 permit_adm = 1;
3748 break;
3749 }
3750 }
3751 }
3752
3753 return permit && permit_adm;
3754}
3755
3640/* protocol v2 remote port fwd, used by sshd */ 3756/* protocol v2 remote port fwd, used by sshd */
3641int 3757int
3642channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, 3758channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
3643 int *allocated_listen_port, struct ForwardOptions *fwd_opts) 3759 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
3644{ 3760{
3761 if (!check_rfwd_permission(ssh, fwd)) {
3762 packet_send_debug("port forwarding refused");
3763 return 0;
3764 }
3645 if (fwd->listen_path != NULL) { 3765 if (fwd->listen_path != NULL) {
3646 return channel_setup_fwd_listener_streamlocal(ssh, 3766 return channel_setup_fwd_listener_streamlocal(ssh,
3647 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); 3767 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
@@ -3671,7 +3791,7 @@ channel_rfwd_bind_host(const char *listen_host)
3671 * Initiate forwarding of connections to port "port" on remote host through 3791 * Initiate forwarding of connections to port "port" on remote host through
3672 * the secure channel to host:port from local side. 3792 * the secure channel to host:port from local side.
3673 * Returns handle (index) for updating the dynamic listen port with 3793 * Returns handle (index) for updating the dynamic listen port with
3674 * channel_update_permitted_opens(). 3794 * channel_update_permission().
3675 */ 3795 */
3676int 3796int
3677channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) 3797channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
@@ -3724,7 +3844,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
3724 listen_host = xstrdup(fwd->listen_host); 3844 listen_host = xstrdup(fwd->listen_host);
3725 listen_port = fwd->listen_port; 3845 listen_port = fwd->listen_port;
3726 } 3846 }
3727 idx = fwd_perm_list_add(ssh, FWDPERM_USER, 3847 idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL,
3728 host_to_connect, port_to_connect, 3848 host_to_connect, port_to_connect,
3729 listen_host, listen_path, listen_port, NULL); 3849 listen_host, listen_path, listen_port, NULL);
3730 } 3850 }
@@ -3732,7 +3852,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
3732} 3852}
3733 3853
3734static int 3854static int
3735open_match(ForwardPermission *allowed_open, const char *requestedhost, 3855open_match(struct permission *allowed_open, const char *requestedhost,
3736 int requestedport) 3856 int requestedport)
3737{ 3857{
3738 if (allowed_open->host_to_connect == NULL) 3858 if (allowed_open->host_to_connect == NULL)
@@ -3753,7 +3873,7 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
3753 * and what we've sent to the remote server (channel_rfwd_bind_host) 3873 * and what we've sent to the remote server (channel_rfwd_bind_host)
3754 */ 3874 */
3755static int 3875static int
3756open_listen_match_tcpip(ForwardPermission *allowed_open, 3876open_listen_match_tcpip(struct permission *allowed_open,
3757 const char *requestedhost, u_short requestedport, int translate) 3877 const char *requestedhost, u_short requestedport, int translate)
3758{ 3878{
3759 const char *allowed_host; 3879 const char *allowed_host;
@@ -3768,14 +3888,14 @@ open_listen_match_tcpip(ForwardPermission *allowed_open,
3768 allowed_host = translate ? 3888 allowed_host = translate ?
3769 channel_rfwd_bind_host(allowed_open->listen_host) : 3889 channel_rfwd_bind_host(allowed_open->listen_host) :
3770 allowed_open->listen_host; 3890 allowed_open->listen_host;
3771 if (allowed_host == NULL || 3891 if (allowed_host == NULL || requestedhost == NULL ||
3772 strcmp(allowed_host, requestedhost) != 0) 3892 strcmp(allowed_host, requestedhost) != 0)
3773 return 0; 3893 return 0;
3774 return 1; 3894 return 1;
3775} 3895}
3776 3896
3777static int 3897static int
3778open_listen_match_streamlocal(ForwardPermission *allowed_open, 3898open_listen_match_streamlocal(struct permission *allowed_open,
3779 const char *requestedpath) 3899 const char *requestedpath)
3780{ 3900{
3781 if (allowed_open->host_to_connect == NULL) 3901 if (allowed_open->host_to_connect == NULL)
@@ -3797,17 +3917,18 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
3797 const char *host, u_short port) 3917 const char *host, u_short port)
3798{ 3918{
3799 struct ssh_channels *sc = ssh->chanctxt; 3919 struct ssh_channels *sc = ssh->chanctxt;
3920 struct permission_set *pset = &sc->local_perms;
3800 int r; 3921 int r;
3801 u_int i; 3922 u_int i;
3802 ForwardPermission *fp; 3923 struct permission *perm;
3803 3924
3804 for (i = 0; i < sc->num_permitted_opens; i++) { 3925 for (i = 0; i < pset->num_permitted_user; i++) {
3805 fp = &sc->permitted_opens[i]; 3926 perm = &pset->permitted_user[i];
3806 if (open_listen_match_tcpip(fp, host, port, 0)) 3927 if (open_listen_match_tcpip(perm, host, port, 0))
3807 break; 3928 break;
3808 fp = NULL; 3929 perm = NULL;
3809 } 3930 }
3810 if (fp == NULL) { 3931 if (perm == NULL) {
3811 debug("%s: requested forward not found", __func__); 3932 debug("%s: requested forward not found", __func__);
3812 return -1; 3933 return -1;
3813 } 3934 }
@@ -3819,7 +3940,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
3819 (r = sshpkt_send(ssh)) != 0) 3940 (r = sshpkt_send(ssh)) != 0)
3820 fatal("%s: send cancel: %s", __func__, ssh_err(r)); 3941 fatal("%s: send cancel: %s", __func__, ssh_err(r));
3821 3942
3822 fwd_perm_clear(fp); /* unregister */ 3943 fwd_perm_clear(perm); /* unregister */
3823 3944
3824 return 0; 3945 return 0;
3825} 3946}
@@ -3832,17 +3953,18 @@ static int
3832channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) 3953channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
3833{ 3954{
3834 struct ssh_channels *sc = ssh->chanctxt; 3955 struct ssh_channels *sc = ssh->chanctxt;
3956 struct permission_set *pset = &sc->local_perms;
3835 int r; 3957 int r;
3836 u_int i; 3958 u_int i;
3837 ForwardPermission *fp; 3959 struct permission *perm;
3838 3960
3839 for (i = 0; i < sc->num_permitted_opens; i++) { 3961 for (i = 0; i < pset->num_permitted_user; i++) {
3840 fp = &sc->permitted_opens[i]; 3962 perm = &pset->permitted_user[i];
3841 if (open_listen_match_streamlocal(fp, path)) 3963 if (open_listen_match_streamlocal(perm, path))
3842 break; 3964 break;
3843 fp = NULL; 3965 perm = NULL;
3844 } 3966 }
3845 if (fp == NULL) { 3967 if (perm == NULL) {
3846 debug("%s: requested forward not found", __func__); 3968 debug("%s: requested forward not found", __func__);
3847 return -1; 3969 return -1;
3848 } 3970 }
@@ -3854,7 +3976,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
3854 (r = sshpkt_send(ssh)) != 0) 3976 (r = sshpkt_send(ssh)) != 0)
3855 fatal("%s: send cancel: %s", __func__, ssh_err(r)); 3977 fatal("%s: send cancel: %s", __func__, ssh_err(r));
3856 3978
3857 fwd_perm_clear(fp); /* unregister */ 3979 fwd_perm_clear(perm); /* unregister */
3858 3980
3859 return 0; 3981 return 0;
3860} 3982}
@@ -3876,25 +3998,64 @@ channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd)
3876} 3998}
3877 3999
3878/* 4000/*
3879 * Permits opening to any host/port if permitted_opens[] is empty. This is 4001 * Permits opening to any host/port if permitted_user[] is empty. This is
3880 * usually called by the server, because the user could connect to any port 4002 * usually called by the server, because the user could connect to any port
3881 * anyway, and the server has no way to know but to trust the client anyway. 4003 * anyway, and the server has no way to know but to trust the client anyway.
3882 */ 4004 */
3883void 4005void
3884channel_permit_all_opens(struct ssh *ssh) 4006channel_permit_all(struct ssh *ssh, int where)
3885{ 4007{
3886 if (ssh->chanctxt->num_permitted_opens == 0) 4008 struct permission_set *pset = permission_set_get(ssh, where);
3887 ssh->chanctxt->all_opens_permitted = 1; 4009
4010 if (pset->num_permitted_user == 0)
4011 pset->all_permitted = 1;
3888} 4012}
3889 4013
4014/*
4015 * Permit the specified host/port for forwarding.
4016 */
3890void 4017void
3891channel_add_permitted_opens(struct ssh *ssh, char *host, int port) 4018channel_add_permission(struct ssh *ssh, int who, int where,
4019 char *host, int port)
3892{ 4020{
3893 struct ssh_channels *sc = ssh->chanctxt; 4021 int local = where == FORWARD_LOCAL;
4022 struct permission_set *pset = permission_set_get(ssh, where);
4023
4024 debug("allow %s forwarding to host %s port %d",
4025 fwd_ident(who, where), host, port);
4026 /*
4027 * Remote forwards set listen_host/port, local forwards set
4028 * host/port_to_connect.
4029 */
4030 permission_set_add(ssh, who, where,
4031 local ? host : 0, local ? port : 0,
4032 local ? NULL : host, NULL, local ? 0 : port, NULL);
4033 pset->all_permitted = 0;
4034}
3894 4035
3895 debug("allow port forwarding to host %s port %d", host, port); 4036/*
3896 fwd_perm_list_add(ssh, FWDPERM_USER, host, port, NULL, NULL, 0, NULL); 4037 * Administratively disable forwarding.
3897 sc->all_opens_permitted = 0; 4038 */
4039void
4040channel_disable_admin(struct ssh *ssh, int where)
4041{
4042 channel_clear_permission(ssh, FORWARD_ADM, where);
4043 permission_set_add(ssh, FORWARD_ADM, where,
4044 NULL, 0, NULL, NULL, 0, NULL);
4045}
4046
4047/*
4048 * Clear a list of permitted opens.
4049 */
4050void
4051channel_clear_permission(struct ssh *ssh, int who, int where)
4052{
4053 struct permission **permp;
4054 u_int *npermp;
4055
4056 permission_set_get_array(ssh, who, where, &permp, &npermp);
4057 *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
4058 *npermp = 0;
3898} 4059}
3899 4060
3900/* 4061/*
@@ -3903,63 +4064,28 @@ channel_add_permitted_opens(struct ssh *ssh, char *host, int port)
3903 * passed then they entry will be invalidated. 4064 * passed then they entry will be invalidated.
3904 */ 4065 */
3905void 4066void
3906channel_update_permitted_opens(struct ssh *ssh, int idx, int newport) 4067channel_update_permission(struct ssh *ssh, int idx, int newport)
3907{ 4068{
3908 struct ssh_channels *sc = ssh->chanctxt; 4069 struct permission_set *pset = &ssh->chanctxt->local_perms;
3909 4070
3910 if (idx < 0 || (u_int)idx >= sc->num_permitted_opens) { 4071 if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
3911 debug("%s: index out of range: %d num_permitted_opens %d", 4072 debug("%s: index out of range: %d num_permitted_user %d",
3912 __func__, idx, sc->num_permitted_opens); 4073 __func__, idx, pset->num_permitted_user);
3913 return; 4074 return;
3914 } 4075 }
3915 debug("%s allowed port %d for forwarding to host %s port %d", 4076 debug("%s allowed port %d for forwarding to host %s port %d",
3916 newport > 0 ? "Updating" : "Removing", 4077 newport > 0 ? "Updating" : "Removing",
3917 newport, 4078 newport,
3918 sc->permitted_opens[idx].host_to_connect, 4079 pset->permitted_user[idx].host_to_connect,
3919 sc->permitted_opens[idx].port_to_connect); 4080 pset->permitted_user[idx].port_to_connect);
3920 if (newport <= 0) 4081 if (newport <= 0)
3921 fwd_perm_clear(&sc->permitted_opens[idx]); 4082 fwd_perm_clear(&pset->permitted_user[idx]);
3922 else { 4083 else {
3923 sc->permitted_opens[idx].listen_port = 4084 pset->permitted_user[idx].listen_port =
3924 (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; 4085 (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
3925 } 4086 }
3926} 4087}
3927 4088
3928int
3929channel_add_adm_permitted_opens(struct ssh *ssh, char *host, int port)
3930{
3931 debug("config allows port forwarding to host %s port %d", host, port);
3932 return fwd_perm_list_add(ssh, FWDPERM_ADMIN, host, port,
3933 NULL, NULL, 0, NULL);
3934}
3935
3936void
3937channel_disable_adm_local_opens(struct ssh *ssh)
3938{
3939 channel_clear_adm_permitted_opens(ssh);
3940 fwd_perm_list_add(ssh, FWDPERM_ADMIN, NULL, 0, NULL, NULL, 0, NULL);
3941}
3942
3943void
3944channel_clear_permitted_opens(struct ssh *ssh)
3945{
3946 struct ssh_channels *sc = ssh->chanctxt;
3947
3948 sc->permitted_opens = xrecallocarray(sc->permitted_opens,
3949 sc->num_permitted_opens, 0, sizeof(*sc->permitted_opens));
3950 sc->num_permitted_opens = 0;
3951}
3952
3953void
3954channel_clear_adm_permitted_opens(struct ssh *ssh)
3955{
3956 struct ssh_channels *sc = ssh->chanctxt;
3957
3958 sc->permitted_adm_opens = xrecallocarray(sc->permitted_adm_opens,
3959 sc->num_adm_permitted_opens, 0, sizeof(*sc->permitted_adm_opens));
3960 sc->num_adm_permitted_opens = 0;
3961}
3962
3963/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ 4089/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
3964int 4090int
3965permitopen_port(const char *p) 4091permitopen_port(const char *p)
@@ -4148,19 +4274,21 @@ channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
4148 u_short listen_port, char *ctype, char *rname) 4274 u_short listen_port, char *ctype, char *rname)
4149{ 4275{
4150 struct ssh_channels *sc = ssh->chanctxt; 4276 struct ssh_channels *sc = ssh->chanctxt;
4277 struct permission_set *pset = &sc->local_perms;
4151 u_int i; 4278 u_int i;
4152 ForwardPermission *fp; 4279 struct permission *perm;
4153 4280
4154 for (i = 0; i < sc->num_permitted_opens; i++) { 4281 for (i = 0; i < pset->num_permitted_user; i++) {
4155 fp = &sc->permitted_opens[i]; 4282 perm = &pset->permitted_user[i];
4156 if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) { 4283 if (open_listen_match_tcpip(perm,
4157 if (fp->downstream) 4284 listen_host, listen_port, 1)) {
4158 return fp->downstream; 4285 if (perm->downstream)
4159 if (fp->port_to_connect == 0) 4286 return perm->downstream;
4287 if (perm->port_to_connect == 0)
4160 return rdynamic_connect_prepare(ssh, 4288 return rdynamic_connect_prepare(ssh,
4161 ctype, rname); 4289 ctype, rname);
4162 return connect_to(ssh, 4290 return connect_to(ssh,
4163 fp->host_to_connect, fp->port_to_connect, 4291 perm->host_to_connect, perm->port_to_connect,
4164 ctype, rname); 4292 ctype, rname);
4165 } 4293 }
4166 } 4294 }
@@ -4174,14 +4302,15 @@ channel_connect_by_listen_path(struct ssh *ssh, const char *path,
4174 char *ctype, char *rname) 4302 char *ctype, char *rname)
4175{ 4303{
4176 struct ssh_channels *sc = ssh->chanctxt; 4304 struct ssh_channels *sc = ssh->chanctxt;
4305 struct permission_set *pset = &sc->local_perms;
4177 u_int i; 4306 u_int i;
4178 ForwardPermission *fp; 4307 struct permission *perm;
4179 4308
4180 for (i = 0; i < sc->num_permitted_opens; i++) { 4309 for (i = 0; i < pset->num_permitted_user; i++) {
4181 fp = &sc->permitted_opens[i]; 4310 perm = &pset->permitted_user[i];
4182 if (open_listen_match_streamlocal(fp, path)) { 4311 if (open_listen_match_streamlocal(perm, path)) {
4183 return connect_to(ssh, 4312 return connect_to(ssh,
4184 fp->host_to_connect, fp->port_to_connect, 4313 perm->host_to_connect, perm->port_to_connect,
4185 ctype, rname); 4314 ctype, rname);
4186 } 4315 }
4187 } 4316 }
@@ -4196,28 +4325,29 @@ channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
4196 char *ctype, char *rname, int *reason, const char **errmsg) 4325 char *ctype, char *rname, int *reason, const char **errmsg)
4197{ 4326{
4198 struct ssh_channels *sc = ssh->chanctxt; 4327 struct ssh_channels *sc = ssh->chanctxt;
4328 struct permission_set *pset = &sc->local_perms;
4199 struct channel_connect cctx; 4329 struct channel_connect cctx;
4200 Channel *c; 4330 Channel *c;
4201 u_int i, permit, permit_adm = 1; 4331 u_int i, permit, permit_adm = 1;
4202 int sock; 4332 int sock;
4203 ForwardPermission *fp; 4333 struct permission *perm;
4204 4334
4205 permit = sc->all_opens_permitted; 4335 permit = pset->all_permitted;
4206 if (!permit) { 4336 if (!permit) {
4207 for (i = 0; i < sc->num_permitted_opens; i++) { 4337 for (i = 0; i < pset->num_permitted_user; i++) {
4208 fp = &sc->permitted_opens[i]; 4338 perm = &pset->permitted_user[i];
4209 if (open_match(fp, host, port)) { 4339 if (open_match(perm, host, port)) {
4210 permit = 1; 4340 permit = 1;
4211 break; 4341 break;
4212 } 4342 }
4213 } 4343 }
4214 } 4344 }
4215 4345
4216 if (sc->num_adm_permitted_opens > 0) { 4346 if (pset->num_permitted_admin > 0) {
4217 permit_adm = 0; 4347 permit_adm = 0;
4218 for (i = 0; i < sc->num_adm_permitted_opens; i++) { 4348 for (i = 0; i < pset->num_permitted_admin; i++) {
4219 fp = &sc->permitted_adm_opens[i]; 4349 perm = &pset->permitted_admin[i];
4220 if (open_match(fp, host, port)) { 4350 if (open_match(perm, host, port)) {
4221 permit_adm = 1; 4351 permit_adm = 1;
4222 break; 4352 break;
4223 } 4353 }
@@ -4255,25 +4385,26 @@ channel_connect_to_path(struct ssh *ssh, const char *path,
4255 char *ctype, char *rname) 4385 char *ctype, char *rname)
4256{ 4386{
4257 struct ssh_channels *sc = ssh->chanctxt; 4387 struct ssh_channels *sc = ssh->chanctxt;
4388 struct permission_set *pset = &sc->local_perms;
4258 u_int i, permit, permit_adm = 1; 4389 u_int i, permit, permit_adm = 1;
4259 ForwardPermission *fp; 4390 struct permission *perm;
4260 4391
4261 permit = sc->all_opens_permitted; 4392 permit = pset->all_permitted;
4262 if (!permit) { 4393 if (!permit) {
4263 for (i = 0; i < sc->num_permitted_opens; i++) { 4394 for (i = 0; i < pset->num_permitted_user; i++) {
4264 fp = &sc->permitted_opens[i]; 4395 perm = &pset->permitted_user[i];
4265 if (open_match(fp, path, PORT_STREAMLOCAL)) { 4396 if (open_match(perm, path, PORT_STREAMLOCAL)) {
4266 permit = 1; 4397 permit = 1;
4267 break; 4398 break;
4268 } 4399 }
4269 } 4400 }
4270 } 4401 }
4271 4402
4272 if (sc->num_adm_permitted_opens > 0) { 4403 if (pset->num_permitted_admin > 0) {
4273 permit_adm = 0; 4404 permit_adm = 0;
4274 for (i = 0; i < sc->num_adm_permitted_opens; i++) { 4405 for (i = 0; i < pset->num_permitted_admin; i++) {
4275 fp = &sc->permitted_adm_opens[i]; 4406 perm = &pset->permitted_admin[i];
4276 if (open_match(fp, path, PORT_STREAMLOCAL)) { 4407 if (open_match(perm, path, PORT_STREAMLOCAL)) {
4277 permit_adm = 1; 4408 permit_adm = 1;
4278 break; 4409 break;
4279 } 4410 }