summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-06-06 18:22:41 +0000
committerDamien Miller <djm@mindrot.org>2018-06-07 04:27:20 +1000
commit115063a6647007286cc8ca70abfd2a7585f26ccc (patch)
tree7bd8d46ae55ff7fc1f8699740d2d2e106c3d5fe8 /channels.c
parent7703ae5f5d42eb302ded51705166ff6e19c92892 (diff)
upstream: Add a PermitListen directive to control which server-side
addresses may be listened on when the client requests remote forwarding (ssh -R). This is the converse of the existing PermitOpen directive and this includes some refactoring to share much of its implementation. feedback and ok markus@ OpenBSD-Commit-ID: 15a931238c61a3f2ac74ea18a98c933e358e277f
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c477
1 files changed, 303 insertions, 174 deletions
diff --git a/channels.c b/channels.c
index 65d9dbd5f..1b40d7da6 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.380 2018/04/10 00:10:49 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.381 2018/06/06 18:22:41 djm 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
@@ -82,6 +82,7 @@
82#include "key.h" 82#include "key.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
@@ -2729,7 +2780,7 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
2729 goto out; 2780 goto out;
2730 } 2781 }
2731 /* Record that connection to this host/port is permitted. */ 2782 /* Record that connection to this host/port is permitted. */
2732 fwd_perm_list_add(ssh, FWDPERM_USER, "<mux>", -1, 2783 permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1,
2733 listen_host, NULL, (int)listen_port, downstream); 2784 listen_host, NULL, (int)listen_port, downstream);
2734 listen_host = NULL; 2785 listen_host = NULL;
2735 break; 2786 break;
@@ -3637,11 +3688,78 @@ channel_setup_local_fwd_listener(struct ssh *ssh,
3637 } 3688 }
3638} 3689}
3639 3690
3691/* Matches a remote forwarding permission against a requested forwarding */
3692static int
3693remote_open_match(struct permission *allowed_open, struct Forward *fwd)
3694{
3695 int ret;
3696 char *lhost;
3697
3698 /* XXX add ACLs for streamlocal */
3699 if (fwd->listen_path != NULL)
3700 return 1;
3701
3702 if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)
3703 return 0;
3704
3705 if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&
3706 allowed_open->listen_port != fwd->listen_port)
3707 return 0;
3708
3709 /* Match hostnames case-insensitively */
3710 lhost = xstrdup(fwd->listen_host);
3711 lowercase(lhost);
3712 ret = match_pattern(lhost, allowed_open->listen_host);
3713 free(lhost);
3714
3715 return ret;
3716}
3717
3718/* Checks whether a requested remote forwarding is permitted */
3719static int
3720check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
3721{
3722 struct ssh_channels *sc = ssh->chanctxt;
3723 struct permission_set *pset = &sc->remote_perms;
3724 u_int i, permit, permit_adm = 1;
3725 struct permission *perm;
3726
3727 /* XXX apply GatewayPorts override before checking? */
3728
3729 permit = pset->all_permitted;
3730 if (!permit) {
3731 for (i = 0; i < pset->num_permitted_user; i++) {
3732 perm = &pset->permitted_user[i];
3733 if (remote_open_match(perm, fwd)) {
3734 permit = 1;
3735 break;
3736 }
3737 }
3738 }
3739
3740 if (pset->num_permitted_admin > 0) {
3741 permit_adm = 0;
3742 for (i = 0; i < pset->num_permitted_admin; i++) {
3743 perm = &pset->permitted_admin[i];
3744 if (remote_open_match(perm, fwd)) {
3745 permit_adm = 1;
3746 break;
3747 }
3748 }
3749 }
3750
3751 return permit && permit_adm;
3752}
3753
3640/* protocol v2 remote port fwd, used by sshd */ 3754/* protocol v2 remote port fwd, used by sshd */
3641int 3755int
3642channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, 3756channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
3643 int *allocated_listen_port, struct ForwardOptions *fwd_opts) 3757 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
3644{ 3758{
3759 if (!check_rfwd_permission(ssh, fwd)) {
3760 packet_send_debug("port forwarding refused");
3761 return 0;
3762 }
3645 if (fwd->listen_path != NULL) { 3763 if (fwd->listen_path != NULL) {
3646 return channel_setup_fwd_listener_streamlocal(ssh, 3764 return channel_setup_fwd_listener_streamlocal(ssh,
3647 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); 3765 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
@@ -3671,7 +3789,7 @@ channel_rfwd_bind_host(const char *listen_host)
3671 * Initiate forwarding of connections to port "port" on remote host through 3789 * Initiate forwarding of connections to port "port" on remote host through
3672 * the secure channel to host:port from local side. 3790 * the secure channel to host:port from local side.
3673 * Returns handle (index) for updating the dynamic listen port with 3791 * Returns handle (index) for updating the dynamic listen port with
3674 * channel_update_permitted_opens(). 3792 * channel_update_permission().
3675 */ 3793 */
3676int 3794int
3677channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) 3795channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
@@ -3724,7 +3842,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
3724 listen_host = xstrdup(fwd->listen_host); 3842 listen_host = xstrdup(fwd->listen_host);
3725 listen_port = fwd->listen_port; 3843 listen_port = fwd->listen_port;
3726 } 3844 }
3727 idx = fwd_perm_list_add(ssh, FWDPERM_USER, 3845 idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL,
3728 host_to_connect, port_to_connect, 3846 host_to_connect, port_to_connect,
3729 listen_host, listen_path, listen_port, NULL); 3847 listen_host, listen_path, listen_port, NULL);
3730 } 3848 }
@@ -3732,7 +3850,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
3732} 3850}
3733 3851
3734static int 3852static int
3735open_match(ForwardPermission *allowed_open, const char *requestedhost, 3853open_match(struct permission *allowed_open, const char *requestedhost,
3736 int requestedport) 3854 int requestedport)
3737{ 3855{
3738 if (allowed_open->host_to_connect == NULL) 3856 if (allowed_open->host_to_connect == NULL)
@@ -3753,7 +3871,7 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
3753 * and what we've sent to the remote server (channel_rfwd_bind_host) 3871 * and what we've sent to the remote server (channel_rfwd_bind_host)
3754 */ 3872 */
3755static int 3873static int
3756open_listen_match_tcpip(ForwardPermission *allowed_open, 3874open_listen_match_tcpip(struct permission *allowed_open,
3757 const char *requestedhost, u_short requestedport, int translate) 3875 const char *requestedhost, u_short requestedport, int translate)
3758{ 3876{
3759 const char *allowed_host; 3877 const char *allowed_host;
@@ -3775,7 +3893,7 @@ open_listen_match_tcpip(ForwardPermission *allowed_open,
3775} 3893}
3776 3894
3777static int 3895static int
3778open_listen_match_streamlocal(ForwardPermission *allowed_open, 3896open_listen_match_streamlocal(struct permission *allowed_open,
3779 const char *requestedpath) 3897 const char *requestedpath)
3780{ 3898{
3781 if (allowed_open->host_to_connect == NULL) 3899 if (allowed_open->host_to_connect == NULL)
@@ -3797,17 +3915,18 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
3797 const char *host, u_short port) 3915 const char *host, u_short port)
3798{ 3916{
3799 struct ssh_channels *sc = ssh->chanctxt; 3917 struct ssh_channels *sc = ssh->chanctxt;
3918 struct permission_set *pset = &sc->local_perms;
3800 int r; 3919 int r;
3801 u_int i; 3920 u_int i;
3802 ForwardPermission *fp; 3921 struct permission *perm;
3803 3922
3804 for (i = 0; i < sc->num_permitted_opens; i++) { 3923 for (i = 0; i < pset->num_permitted_user; i++) {
3805 fp = &sc->permitted_opens[i]; 3924 perm = &pset->permitted_user[i];
3806 if (open_listen_match_tcpip(fp, host, port, 0)) 3925 if (open_listen_match_tcpip(perm, host, port, 0))
3807 break; 3926 break;
3808 fp = NULL; 3927 perm = NULL;
3809 } 3928 }
3810 if (fp == NULL) { 3929 if (perm == NULL) {
3811 debug("%s: requested forward not found", __func__); 3930 debug("%s: requested forward not found", __func__);
3812 return -1; 3931 return -1;
3813 } 3932 }
@@ -3819,7 +3938,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
3819 (r = sshpkt_send(ssh)) != 0) 3938 (r = sshpkt_send(ssh)) != 0)
3820 fatal("%s: send cancel: %s", __func__, ssh_err(r)); 3939 fatal("%s: send cancel: %s", __func__, ssh_err(r));
3821 3940
3822 fwd_perm_clear(fp); /* unregister */ 3941 fwd_perm_clear(perm); /* unregister */
3823 3942
3824 return 0; 3943 return 0;
3825} 3944}
@@ -3832,17 +3951,18 @@ static int
3832channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) 3951channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
3833{ 3952{
3834 struct ssh_channels *sc = ssh->chanctxt; 3953 struct ssh_channels *sc = ssh->chanctxt;
3954 struct permission_set *pset = &sc->local_perms;
3835 int r; 3955 int r;
3836 u_int i; 3956 u_int i;
3837 ForwardPermission *fp; 3957 struct permission *perm;
3838 3958
3839 for (i = 0; i < sc->num_permitted_opens; i++) { 3959 for (i = 0; i < pset->num_permitted_user; i++) {
3840 fp = &sc->permitted_opens[i]; 3960 perm = &pset->permitted_user[i];
3841 if (open_listen_match_streamlocal(fp, path)) 3961 if (open_listen_match_streamlocal(perm, path))
3842 break; 3962 break;
3843 fp = NULL; 3963 perm = NULL;
3844 } 3964 }
3845 if (fp == NULL) { 3965 if (perm == NULL) {
3846 debug("%s: requested forward not found", __func__); 3966 debug("%s: requested forward not found", __func__);
3847 return -1; 3967 return -1;
3848 } 3968 }
@@ -3854,7 +3974,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
3854 (r = sshpkt_send(ssh)) != 0) 3974 (r = sshpkt_send(ssh)) != 0)
3855 fatal("%s: send cancel: %s", __func__, ssh_err(r)); 3975 fatal("%s: send cancel: %s", __func__, ssh_err(r));
3856 3976
3857 fwd_perm_clear(fp); /* unregister */ 3977 fwd_perm_clear(perm); /* unregister */
3858 3978
3859 return 0; 3979 return 0;
3860} 3980}
@@ -3876,25 +3996,64 @@ channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd)
3876} 3996}
3877 3997
3878/* 3998/*
3879 * Permits opening to any host/port if permitted_opens[] is empty. This is 3999 * 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 4000 * 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. 4001 * anyway, and the server has no way to know but to trust the client anyway.
3882 */ 4002 */
3883void 4003void
3884channel_permit_all_opens(struct ssh *ssh) 4004channel_permit_all(struct ssh *ssh, int where)
3885{ 4005{
3886 if (ssh->chanctxt->num_permitted_opens == 0) 4006 struct permission_set *pset = permission_set_get(ssh, where);
3887 ssh->chanctxt->all_opens_permitted = 1; 4007
4008 if (pset->num_permitted_user == 0)
4009 pset->all_permitted = 1;
3888} 4010}
3889 4011
4012/*
4013 * Permit the specified host/port for forwarding.
4014 */
3890void 4015void
3891channel_add_permitted_opens(struct ssh *ssh, char *host, int port) 4016channel_add_permission(struct ssh *ssh, int who, int where,
4017 char *host, int port)
3892{ 4018{
3893 struct ssh_channels *sc = ssh->chanctxt; 4019 int local = where == FORWARD_LOCAL;
4020 struct permission_set *pset = permission_set_get(ssh, where);
3894 4021
3895 debug("allow port forwarding to host %s port %d", host, port); 4022 debug("allow %s forwarding to host %s port %d",
3896 fwd_perm_list_add(ssh, FWDPERM_USER, host, port, NULL, NULL, 0, NULL); 4023 fwd_ident(who, where), host, port);
3897 sc->all_opens_permitted = 0; 4024 /*
4025 * Remote forwards set listen_host/port, local forwards set
4026 * host/port_to_connect.
4027 */
4028 permission_set_add(ssh, who, where,
4029 local ? host : 0, local ? port : 0,
4030 local ? NULL : host, NULL, local ? 0 : port, NULL);
4031 pset->all_permitted = 0;
4032}
4033
4034/*
4035 * Administratively disable forwarding.
4036 */
4037void
4038channel_disable_admin(struct ssh *ssh, int where)
4039{
4040 channel_clear_permission(ssh, FORWARD_ADM, where);
4041 permission_set_add(ssh, FORWARD_ADM, where,
4042 NULL, 0, NULL, NULL, 0, NULL);
4043}
4044
4045/*
4046 * Clear a list of permitted opens.
4047 */
4048void
4049channel_clear_permission(struct ssh *ssh, int who, int where)
4050{
4051 struct permission **permp;
4052 u_int *npermp;
4053
4054 permission_set_get_array(ssh, who, where, &permp, &npermp);
4055 *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
4056 *npermp = 0;
3898} 4057}
3899 4058
3900/* 4059/*
@@ -3903,63 +4062,28 @@ channel_add_permitted_opens(struct ssh *ssh, char *host, int port)
3903 * passed then they entry will be invalidated. 4062 * passed then they entry will be invalidated.
3904 */ 4063 */
3905void 4064void
3906channel_update_permitted_opens(struct ssh *ssh, int idx, int newport) 4065channel_update_permission(struct ssh *ssh, int idx, int newport)
3907{ 4066{
3908 struct ssh_channels *sc = ssh->chanctxt; 4067 struct permission_set *pset = &ssh->chanctxt->local_perms;
3909 4068
3910 if (idx < 0 || (u_int)idx >= sc->num_permitted_opens) { 4069 if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
3911 debug("%s: index out of range: %d num_permitted_opens %d", 4070 debug("%s: index out of range: %d num_permitted_user %d",
3912 __func__, idx, sc->num_permitted_opens); 4071 __func__, idx, pset->num_permitted_user);
3913 return; 4072 return;
3914 } 4073 }
3915 debug("%s allowed port %d for forwarding to host %s port %d", 4074 debug("%s allowed port %d for forwarding to host %s port %d",
3916 newport > 0 ? "Updating" : "Removing", 4075 newport > 0 ? "Updating" : "Removing",
3917 newport, 4076 newport,
3918 sc->permitted_opens[idx].host_to_connect, 4077 pset->permitted_user[idx].host_to_connect,
3919 sc->permitted_opens[idx].port_to_connect); 4078 pset->permitted_user[idx].port_to_connect);
3920 if (newport <= 0) 4079 if (newport <= 0)
3921 fwd_perm_clear(&sc->permitted_opens[idx]); 4080 fwd_perm_clear(&pset->permitted_user[idx]);
3922 else { 4081 else {
3923 sc->permitted_opens[idx].listen_port = 4082 pset->permitted_user[idx].listen_port =
3924 (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; 4083 (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
3925 } 4084 }
3926} 4085}
3927 4086
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 */ 4087/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
3964int 4088int
3965permitopen_port(const char *p) 4089permitopen_port(const char *p)
@@ -4148,19 +4272,21 @@ channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
4148 u_short listen_port, char *ctype, char *rname) 4272 u_short listen_port, char *ctype, char *rname)
4149{ 4273{
4150 struct ssh_channels *sc = ssh->chanctxt; 4274 struct ssh_channels *sc = ssh->chanctxt;
4275 struct permission_set *pset = &sc->local_perms;
4151 u_int i; 4276 u_int i;
4152 ForwardPermission *fp; 4277 struct permission *perm;
4153 4278
4154 for (i = 0; i < sc->num_permitted_opens; i++) { 4279 for (i = 0; i < pset->num_permitted_user; i++) {
4155 fp = &sc->permitted_opens[i]; 4280 perm = &pset->permitted_user[i];
4156 if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) { 4281 if (open_listen_match_tcpip(perm,
4157 if (fp->downstream) 4282 listen_host, listen_port, 1)) {
4158 return fp->downstream; 4283 if (perm->downstream)
4159 if (fp->port_to_connect == 0) 4284 return perm->downstream;
4285 if (perm->port_to_connect == 0)
4160 return rdynamic_connect_prepare(ssh, 4286 return rdynamic_connect_prepare(ssh,
4161 ctype, rname); 4287 ctype, rname);
4162 return connect_to(ssh, 4288 return connect_to(ssh,
4163 fp->host_to_connect, fp->port_to_connect, 4289 perm->host_to_connect, perm->port_to_connect,
4164 ctype, rname); 4290 ctype, rname);
4165 } 4291 }
4166 } 4292 }
@@ -4174,14 +4300,15 @@ channel_connect_by_listen_path(struct ssh *ssh, const char *path,
4174 char *ctype, char *rname) 4300 char *ctype, char *rname)
4175{ 4301{
4176 struct ssh_channels *sc = ssh->chanctxt; 4302 struct ssh_channels *sc = ssh->chanctxt;
4303 struct permission_set *pset = &sc->local_perms;
4177 u_int i; 4304 u_int i;
4178 ForwardPermission *fp; 4305 struct permission *perm;
4179 4306
4180 for (i = 0; i < sc->num_permitted_opens; i++) { 4307 for (i = 0; i < pset->num_permitted_user; i++) {
4181 fp = &sc->permitted_opens[i]; 4308 perm = &pset->permitted_user[i];
4182 if (open_listen_match_streamlocal(fp, path)) { 4309 if (open_listen_match_streamlocal(perm, path)) {
4183 return connect_to(ssh, 4310 return connect_to(ssh,
4184 fp->host_to_connect, fp->port_to_connect, 4311 perm->host_to_connect, perm->port_to_connect,
4185 ctype, rname); 4312 ctype, rname);
4186 } 4313 }
4187 } 4314 }
@@ -4196,28 +4323,29 @@ channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
4196 char *ctype, char *rname, int *reason, const char **errmsg) 4323 char *ctype, char *rname, int *reason, const char **errmsg)
4197{ 4324{
4198 struct ssh_channels *sc = ssh->chanctxt; 4325 struct ssh_channels *sc = ssh->chanctxt;
4326 struct permission_set *pset = &sc->local_perms;
4199 struct channel_connect cctx; 4327 struct channel_connect cctx;
4200 Channel *c; 4328 Channel *c;
4201 u_int i, permit, permit_adm = 1; 4329 u_int i, permit, permit_adm = 1;
4202 int sock; 4330 int sock;
4203 ForwardPermission *fp; 4331 struct permission *perm;
4204 4332
4205 permit = sc->all_opens_permitted; 4333 permit = pset->all_permitted;
4206 if (!permit) { 4334 if (!permit) {
4207 for (i = 0; i < sc->num_permitted_opens; i++) { 4335 for (i = 0; i < pset->num_permitted_user; i++) {
4208 fp = &sc->permitted_opens[i]; 4336 perm = &pset->permitted_user[i];
4209 if (open_match(fp, host, port)) { 4337 if (open_match(perm, host, port)) {
4210 permit = 1; 4338 permit = 1;
4211 break; 4339 break;
4212 } 4340 }
4213 } 4341 }
4214 } 4342 }
4215 4343
4216 if (sc->num_adm_permitted_opens > 0) { 4344 if (pset->num_permitted_admin > 0) {
4217 permit_adm = 0; 4345 permit_adm = 0;
4218 for (i = 0; i < sc->num_adm_permitted_opens; i++) { 4346 for (i = 0; i < pset->num_permitted_admin; i++) {
4219 fp = &sc->permitted_adm_opens[i]; 4347 perm = &pset->permitted_admin[i];
4220 if (open_match(fp, host, port)) { 4348 if (open_match(perm, host, port)) {
4221 permit_adm = 1; 4349 permit_adm = 1;
4222 break; 4350 break;
4223 } 4351 }
@@ -4255,25 +4383,26 @@ channel_connect_to_path(struct ssh *ssh, const char *path,
4255 char *ctype, char *rname) 4383 char *ctype, char *rname)
4256{ 4384{
4257 struct ssh_channels *sc = ssh->chanctxt; 4385 struct ssh_channels *sc = ssh->chanctxt;
4386 struct permission_set *pset = &sc->local_perms;
4258 u_int i, permit, permit_adm = 1; 4387 u_int i, permit, permit_adm = 1;
4259 ForwardPermission *fp; 4388 struct permission *perm;
4260 4389
4261 permit = sc->all_opens_permitted; 4390 permit = pset->all_permitted;
4262 if (!permit) { 4391 if (!permit) {
4263 for (i = 0; i < sc->num_permitted_opens; i++) { 4392 for (i = 0; i < pset->num_permitted_user; i++) {
4264 fp = &sc->permitted_opens[i]; 4393 perm = &pset->permitted_user[i];
4265 if (open_match(fp, path, PORT_STREAMLOCAL)) { 4394 if (open_match(perm, path, PORT_STREAMLOCAL)) {
4266 permit = 1; 4395 permit = 1;
4267 break; 4396 break;
4268 } 4397 }
4269 } 4398 }
4270 } 4399 }
4271 4400
4272 if (sc->num_adm_permitted_opens > 0) { 4401 if (pset->num_permitted_admin > 0) {
4273 permit_adm = 0; 4402 permit_adm = 0;
4274 for (i = 0; i < sc->num_adm_permitted_opens; i++) { 4403 for (i = 0; i < pset->num_permitted_admin; i++) {
4275 fp = &sc->permitted_adm_opens[i]; 4404 perm = &pset->permitted_admin[i];
4276 if (open_match(fp, path, PORT_STREAMLOCAL)) { 4405 if (open_match(perm, path, PORT_STREAMLOCAL)) {
4277 permit_adm = 1; 4406 permit_adm = 1;
4278 break; 4407 break;
4279 } 4408 }