summaryrefslogtreecommitdiff
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
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
-rw-r--r--channels.c477
-rw-r--r--channels.h26
-rw-r--r--mux.c6
-rw-r--r--servconf.c138
-rw-r--r--servconf.h16
-rw-r--r--session.c27
-rw-r--r--ssh.c6
7 files changed, 439 insertions, 257 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 }
diff --git a/channels.h b/channels.h
index 126b04345..1aeafe94e 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.130 2017/09/21 19:16:53 markus Exp $ */ 1/* $OpenBSD: channels.h,v 1.131 2018/06/06 18:22:41 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -63,6 +63,15 @@
63 63
64#define CHANNEL_CANCEL_PORT_STATIC -1 64#define CHANNEL_CANCEL_PORT_STATIC -1
65 65
66/* TCP forwarding */
67#define FORWARD_DENY 0
68#define FORWARD_REMOTE (1)
69#define FORWARD_LOCAL (1<<1)
70#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
71
72#define FORWARD_ADM 0x100
73#define FORWARD_USER 0x101
74
66struct ssh; 75struct ssh;
67struct Channel; 76struct Channel;
68typedef struct Channel Channel; 77typedef struct Channel Channel;
@@ -283,16 +292,11 @@ int channel_find_open(struct ssh *);
283struct Forward; 292struct Forward;
284struct ForwardOptions; 293struct ForwardOptions;
285void channel_set_af(struct ssh *, int af); 294void channel_set_af(struct ssh *, int af);
286void channel_permit_all_opens(struct ssh *); 295void channel_permit_all(struct ssh *, int);
287void channel_add_permitted_opens(struct ssh *, char *, int); 296void channel_add_permission(struct ssh *, int, int, char *, int);
288int channel_add_adm_permitted_opens(struct ssh *, char *, int); 297void channel_clear_permission(struct ssh *, int, int);
289void channel_copy_adm_permitted_opens(struct ssh *, 298void channel_disable_admin(struct ssh *, int);
290 const struct fwd_perm_list *); 299void channel_update_permission(struct ssh *, int, int);
291void channel_disable_adm_local_opens(struct ssh *);
292void channel_update_permitted_opens(struct ssh *, int, int);
293void channel_clear_permitted_opens(struct ssh *);
294void channel_clear_adm_permitted_opens(struct ssh *);
295void channel_print_adm_permitted_opens(struct ssh *);
296Channel *channel_connect_to_port(struct ssh *, const char *, u_short, 300Channel *channel_connect_to_port(struct ssh *, const char *, u_short,
297 char *, char *, int *, const char **); 301 char *, char *, int *, const char **);
298Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); 302Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
diff --git a/mux.c b/mux.c
index 5ae454410..c591cb154 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.69 2017/09/20 05:19:00 dtucker Exp $ */ 1/* $OpenBSD: mux.c,v 1.70 2018/06/06 18:22:41 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -634,7 +634,7 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
634 buffer_put_int(&out, MUX_S_REMOTE_PORT); 634 buffer_put_int(&out, MUX_S_REMOTE_PORT);
635 buffer_put_int(&out, fctx->rid); 635 buffer_put_int(&out, fctx->rid);
636 buffer_put_int(&out, rfwd->allocated_port); 636 buffer_put_int(&out, rfwd->allocated_port);
637 channel_update_permitted_opens(ssh, rfwd->handle, 637 channel_update_permission(ssh, rfwd->handle,
638 rfwd->allocated_port); 638 rfwd->allocated_port);
639 } else { 639 } else {
640 buffer_put_int(&out, MUX_S_OK); 640 buffer_put_int(&out, MUX_S_OK);
@@ -643,7 +643,7 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
643 goto out; 643 goto out;
644 } else { 644 } else {
645 if (rfwd->listen_port == 0) 645 if (rfwd->listen_port == 0)
646 channel_update_permitted_opens(ssh, rfwd->handle, -1); 646 channel_update_permission(ssh, rfwd->handle, -1);
647 if (rfwd->listen_path != NULL) 647 if (rfwd->listen_path != NULL)
648 xasprintf(&failmsg, "remote port forwarding failed for " 648 xasprintf(&failmsg, "remote port forwarding failed for "
649 "listen path %s", rfwd->listen_path); 649 "listen path %s", rfwd->listen_path);
diff --git a/servconf.c b/servconf.c
index 5ca84515f..b75faf3f8 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.328 2018/04/10 00:10:49 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.329 2018/06/06 18:22:41 djm Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -160,6 +160,7 @@ initialize_server_options(ServerOptions *options)
160 options->num_accept_env = 0; 160 options->num_accept_env = 0;
161 options->permit_tun = -1; 161 options->permit_tun = -1;
162 options->permitted_opens = NULL; 162 options->permitted_opens = NULL;
163 options->permitted_remote_opens = NULL;
163 options->adm_forced_command = NULL; 164 options->adm_forced_command = NULL;
164 options->chroot_directory = NULL; 165 options->chroot_directory = NULL;
165 options->authorized_keys_command = NULL; 166 options->authorized_keys_command = NULL;
@@ -462,7 +463,7 @@ typedef enum {
462 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 463 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
463 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 464 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
464 sAcceptEnv, sPermitTunnel, 465 sAcceptEnv, sPermitTunnel,
465 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 466 sMatch, sPermitOpen, sPermitRemoteOpen, sForceCommand, sChrootDirectory,
466 sUsePrivilegeSeparation, sAllowAgentForwarding, 467 sUsePrivilegeSeparation, sAllowAgentForwarding,
467 sHostCertificate, 468 sHostCertificate,
468 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 469 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
@@ -597,6 +598,7 @@ static struct {
597 { "permituserrc", sPermitUserRC, SSHCFG_ALL }, 598 { "permituserrc", sPermitUserRC, SSHCFG_ALL },
598 { "match", sMatch, SSHCFG_ALL }, 599 { "match", sMatch, SSHCFG_ALL },
599 { "permitopen", sPermitOpen, SSHCFG_ALL }, 600 { "permitopen", sPermitOpen, SSHCFG_ALL },
601 { "permitremoteopen", sPermitRemoteOpen, SSHCFG_ALL },
600 { "forcecommand", sForceCommand, SSHCFG_ALL }, 602 { "forcecommand", sForceCommand, SSHCFG_ALL },
601 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 603 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
602 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 604 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
@@ -632,6 +634,20 @@ static struct {
632 { -1, NULL } 634 { -1, NULL }
633}; 635};
634 636
637/* Returns an opcode name from its number */
638
639static const char *
640lookup_opcode_name(ServerOpCodes code)
641{
642 u_int i;
643
644 for (i = 0; keywords[i].name != NULL; i++)
645 if (keywords[i].opcode == code)
646 return(keywords[i].name);
647 return "UNKNOWN";
648}
649
650
635/* 651/*
636 * Returns the number of the token pointed to by cp or sBadOption. 652 * Returns the number of the token pointed to by cp or sBadOption.
637 */ 653 */
@@ -814,43 +830,59 @@ process_queued_listen_addrs(ServerOptions *options)
814} 830}
815 831
816/* 832/*
817 * Inform channels layer of permitopen options from configuration. 833 * Inform channels layer of permitopen options for a single forwarding
834 * direction (local/remote).
818 */ 835 */
819void 836static void
820process_permitopen(struct ssh *ssh, ServerOptions *options) 837process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
838 char **opens, u_int num_opens)
821{ 839{
822 u_int i; 840 u_int i;
823 int port; 841 int port;
824 char *host, *arg, *oarg; 842 char *host, *arg, *oarg;
843 int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
844 const char *what = lookup_opcode_name(opcode);
825 845
826 channel_clear_adm_permitted_opens(ssh); 846 channel_clear_permission(ssh, FORWARD_ADM, where);
827 if (options->num_permitted_opens == 0) 847 if (num_opens == 0)
828 return; /* permit any */ 848 return; /* permit any */
829 849
830 /* handle keywords: "any" / "none" */ 850 /* handle keywords: "any" / "none" */
831 if (options->num_permitted_opens == 1 && 851 if (num_opens == 1 && strcmp(opens[0], "any") == 0)
832 strcmp(options->permitted_opens[0], "any") == 0)
833 return; 852 return;
834 if (options->num_permitted_opens == 1 && 853 if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
835 strcmp(options->permitted_opens[0], "none") == 0) { 854 channel_disable_admin(ssh, where);
836 channel_disable_adm_local_opens(ssh);
837 return; 855 return;
838 } 856 }
839 /* Otherwise treat it as a list of permitted host:port */ 857 /* Otherwise treat it as a list of permitted host:port */
840 for (i = 0; i < options->num_permitted_opens; i++) { 858 for (i = 0; i < num_opens; i++) {
841 oarg = arg = xstrdup(options->permitted_opens[i]); 859 oarg = arg = xstrdup(opens[i]);
842 host = hpdelim(&arg); 860 host = hpdelim(&arg);
843 if (host == NULL) 861 if (host == NULL)
844 fatal("%s: missing host in PermitOpen", __func__); 862 fatal("%s: missing host in %s", __func__, what);
845 host = cleanhostname(host); 863 host = cleanhostname(host);
846 if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 864 if (arg == NULL || ((port = permitopen_port(arg)) < 0))
847 fatal("%s: bad port number in PermitOpen", __func__); 865 fatal("%s: bad port number in %s", __func__, what);
848 /* Send it to channels layer */ 866 /* Send it to channels layer */
849 channel_add_adm_permitted_opens(ssh, host, port); 867 channel_add_permission(ssh, FORWARD_ADM,
868 where, host, port);
850 free(oarg); 869 free(oarg);
851 } 870 }
852} 871}
853 872
873/*
874 * Inform channels layer of permitopen options from configuration.
875 */
876void
877process_permitopen(struct ssh *ssh, ServerOptions *options)
878{
879 process_permitopen_list(ssh, sPermitOpen,
880 options->permitted_opens, options->num_permitted_opens);
881 process_permitopen_list(ssh, sPermitRemoteOpen,
882 options->permitted_remote_opens,
883 options->num_permitted_remote_opens);
884}
885
854struct connection_info * 886struct connection_info *
855get_connection_info(int populate, int use_dns) 887get_connection_info(int populate, int use_dns)
856{ 888{
@@ -1144,12 +1176,12 @@ process_server_config_line(ServerOptions *options, char *line,
1144 const char *filename, int linenum, int *activep, 1176 const char *filename, int linenum, int *activep,
1145 struct connection_info *connectinfo) 1177 struct connection_info *connectinfo)
1146{ 1178{
1147 char *cp, **charptr, *arg, *arg2, *p; 1179 char *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
1148 int cmdline = 0, *intptr, value, value2, n, port; 1180 int cmdline = 0, *intptr, value, value2, n, port;
1149 SyslogFacility *log_facility_ptr; 1181 SyslogFacility *log_facility_ptr;
1150 LogLevel *log_level_ptr; 1182 LogLevel *log_level_ptr;
1151 ServerOpCodes opcode; 1183 ServerOpCodes opcode;
1152 u_int i, flags = 0; 1184 u_int i, *uintptr, uvalue, flags = 0;
1153 size_t len; 1185 size_t len;
1154 long long val64; 1186 long long val64;
1155 const struct multistate *multistate_ptr; 1187 const struct multistate *multistate_ptr;
@@ -1799,36 +1831,49 @@ process_server_config_line(ServerOptions *options, char *line,
1799 *activep = value; 1831 *activep = value;
1800 break; 1832 break;
1801 1833
1834 case sPermitRemoteOpen:
1802 case sPermitOpen: 1835 case sPermitOpen:
1836 if (opcode == sPermitRemoteOpen) {
1837 uintptr = &options->num_permitted_remote_opens;
1838 chararrayptr = &options->permitted_remote_opens;
1839 } else {
1840 uintptr = &options->num_permitted_opens;
1841 chararrayptr = &options->permitted_opens;
1842 }
1803 arg = strdelim(&cp); 1843 arg = strdelim(&cp);
1804 if (!arg || *arg == '\0') 1844 if (!arg || *arg == '\0')
1805 fatal("%s line %d: missing PermitOpen specification", 1845 fatal("%s line %d: missing %s specification",
1806 filename, linenum); 1846 filename, linenum, lookup_opcode_name(opcode));
1807 value = options->num_permitted_opens; /* modified later */ 1847 uvalue = *uintptr; /* modified later */
1808 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { 1848 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
1809 if (*activep && value == 0) { 1849 if (*activep && uvalue == 0) {
1810 options->num_permitted_opens = 1; 1850 *uintptr = 1;
1811 options->permitted_opens = xcalloc(1, 1851 *chararrayptr = xcalloc(1,
1812 sizeof(*options->permitted_opens)); 1852 sizeof(**chararrayptr));
1813 options->permitted_opens[0] = xstrdup(arg); 1853 (*chararrayptr)[0] = xstrdup(arg);
1814 } 1854 }
1815 break; 1855 break;
1816 } 1856 }
1817 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1857 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1818 arg2 = xstrdup(arg); 1858 arg2 = xstrdup(arg);
1819 p = hpdelim(&arg); 1859 p = hpdelim(&arg);
1820 if (p == NULL) 1860 /* XXX support bare port number for PermitRemoteOpen */
1821 fatal("%s line %d: missing host in PermitOpen", 1861 if (p == NULL) {
1822 filename, linenum); 1862 fatal("%s line %d: missing host in %s",
1863 filename, linenum,
1864 lookup_opcode_name(opcode));
1865 }
1823 p = cleanhostname(p); 1866 p = cleanhostname(p);
1824 if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 1867 if (arg == NULL ||
1825 fatal("%s line %d: bad port number in " 1868 ((port = permitopen_port(arg)) < 0)) {
1826 "PermitOpen", filename, linenum); 1869 fatal("%s line %d: bad port number in %s",
1827 if (*activep && value == 0) { 1870 filename, linenum,
1871 lookup_opcode_name(opcode));
1872 }
1873 if (*activep && uvalue == 0) {
1828 array_append(filename, linenum, 1874 array_append(filename, linenum,
1829 "PermitOpen", 1875 lookup_opcode_name(opcode),
1830 &options->permitted_opens, 1876 chararrayptr, uintptr, arg2);
1831 &options->num_permitted_opens, arg2);
1832 } 1877 }
1833 free(arg2); 1878 free(arg2);
1834 } 1879 }
@@ -2307,17 +2352,6 @@ fmt_intarg(ServerOpCodes code, int val)
2307 } 2352 }
2308} 2353}
2309 2354
2310static const char *
2311lookup_opcode_name(ServerOpCodes code)
2312{
2313 u_int i;
2314
2315 for (i = 0; keywords[i].name != NULL; i++)
2316 if (keywords[i].opcode == code)
2317 return(keywords[i].name);
2318 return "UNKNOWN";
2319}
2320
2321static void 2355static void
2322dump_cfg_int(ServerOpCodes code, int val) 2356dump_cfg_int(ServerOpCodes code, int val)
2323{ 2357{
@@ -2562,4 +2596,12 @@ dump_config(ServerOptions *o)
2562 printf(" %s", o->permitted_opens[i]); 2596 printf(" %s", o->permitted_opens[i]);
2563 } 2597 }
2564 printf("\n"); 2598 printf("\n");
2599 printf("permitremoteopen");
2600 if (o->num_permitted_remote_opens == 0)
2601 printf(" any");
2602 else {
2603 for (i = 0; i < o->num_permitted_remote_opens; i++)
2604 printf(" %s", o->permitted_remote_opens[i]);
2605 }
2606 printf("\n");
2565} 2607}
diff --git a/servconf.h b/servconf.h
index 6d2553c38..62acd8938 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.131 2018/04/13 03:57:26 dtucker Exp $ */ 1/* $OpenBSD: servconf.h,v 1.132 2018/06/06 18:22:41 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -32,12 +32,6 @@
32#define PRIVSEP_ON 1 32#define PRIVSEP_ON 1
33#define PRIVSEP_NOSANDBOX 2 33#define PRIVSEP_NOSANDBOX 2
34 34
35/* AllowTCPForwarding */
36#define FORWARD_DENY 0
37#define FORWARD_REMOTE (1)
38#define FORWARD_LOCAL (1<<1)
39#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
40
41/* PermitOpen */ 35/* PermitOpen */
42#define PERMITOPEN_ANY 0 36#define PERMITOPEN_ANY 0
43#define PERMITOPEN_NONE -2 37#define PERMITOPEN_NONE -2
@@ -187,8 +181,10 @@ typedef struct {
187 181
188 int permit_tun; 182 int permit_tun;
189 183
190 char **permitted_opens; 184 char **permitted_opens; /* May also be one of PERMITOPEN_* */
191 u_int num_permitted_opens; /* May also be one of PERMITOPEN_* */ 185 u_int num_permitted_opens;
186 char **permitted_remote_opens; /* May also be one of PERMITOPEN_* */
187 u_int num_permitted_remote_opens;
192 188
193 char *chroot_directory; 189 char *chroot_directory;
194 char *revoked_keys_file; 190 char *revoked_keys_file;
@@ -252,6 +248,8 @@ struct connection_info {
252 M_CP_STRARRAYOPT(accept_env, num_accept_env); \ 248 M_CP_STRARRAYOPT(accept_env, num_accept_env); \
253 M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ 249 M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
254 M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ 250 M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \
251 M_CP_STRARRAYOPT(permitted_remote_opens, \
252 num_permitted_remote_opens); \
255 } while (0) 253 } while (0)
256 254
257struct connection_info *get_connection_info(int, int); 255struct connection_info *get_connection_info(int, int);
diff --git a/session.c b/session.c
index 5ceebff51..3a3fd841a 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.295 2018/06/01 03:33:53 djm Exp $ */ 1/* $OpenBSD: session.c,v 1.296 2018/06/06 18:22:41 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -298,7 +298,7 @@ set_permitopen_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
298 298
299 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) 299 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
300 return; 300 return;
301 channel_clear_permitted_opens(ssh); 301 channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL);
302 for (i = 0; i < auth_opts->npermitopen; i++) { 302 for (i = 0; i < auth_opts->npermitopen; i++) {
303 tmp = cp = xstrdup(auth_opts->permitopen[i]); 303 tmp = cp = xstrdup(auth_opts->permitopen[i]);
304 /* This shouldn't fail as it has already been checked */ 304 /* This shouldn't fail as it has already been checked */
@@ -308,7 +308,8 @@ set_permitopen_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
308 if (cp == NULL || (port = permitopen_port(cp)) < 0) 308 if (cp == NULL || (port = permitopen_port(cp)) < 0)
309 fatal("%s: internal error: permitopen port", 309 fatal("%s: internal error: permitopen port",
310 __func__); 310 __func__);
311 channel_add_permitted_opens(ssh, host, port); 311 channel_add_permission(ssh, FORWARD_USER, FORWARD_LOCAL,
312 host, port);
312 free(tmp); 313 free(tmp);
313 } 314 }
314} 315}
@@ -323,13 +324,21 @@ do_authenticated(struct ssh *ssh, Authctxt *authctxt)
323 /* setup the channel layer */ 324 /* setup the channel layer */
324 /* XXX - streamlocal? */ 325 /* XXX - streamlocal? */
325 set_permitopen_from_authopts(ssh, auth_opts); 326 set_permitopen_from_authopts(ssh, auth_opts);
326 if (!auth_opts->permit_port_forwarding_flag ||
327 options.disable_forwarding ||
328 (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
329 channel_disable_adm_local_opens(ssh);
330 else
331 channel_permit_all_opens(ssh);
332 327
328 if (!auth_opts->permit_port_forwarding_flag ||
329 options.disable_forwarding) {
330 channel_disable_admin(ssh, FORWARD_LOCAL);
331 channel_disable_admin(ssh, FORWARD_REMOTE);
332 } else {
333 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
334 channel_disable_admin(ssh, FORWARD_LOCAL);
335 else
336 channel_permit_all(ssh, FORWARD_LOCAL);
337 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0)
338 channel_disable_admin(ssh, FORWARD_REMOTE);
339 else
340 channel_permit_all(ssh, FORWARD_REMOTE);
341 }
333 auth_debug_send(); 342 auth_debug_send();
334 343
335 prepare_auth_info_file(authctxt->pw, authctxt->session_info); 344 prepare_auth_info_file(authctxt->pw, authctxt->session_info);
diff --git a/ssh.c b/ssh.c
index d25960bce..a8505a0ee 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.479 2018/06/01 03:33:53 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.480 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
@@ -1654,10 +1654,10 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
1654 logit("Allocated port %u for remote forward to %s:%d", 1654 logit("Allocated port %u for remote forward to %s:%d",
1655 rfwd->allocated_port, 1655 rfwd->allocated_port,
1656 rfwd->connect_host, rfwd->connect_port); 1656 rfwd->connect_host, rfwd->connect_port);
1657 channel_update_permitted_opens(ssh, 1657 channel_update_permission(ssh,
1658 rfwd->handle, rfwd->allocated_port); 1658 rfwd->handle, rfwd->allocated_port);
1659 } else { 1659 } else {
1660 channel_update_permitted_opens(ssh, rfwd->handle, -1); 1660 channel_update_permission(ssh, rfwd->handle, -1);
1661 } 1661 }
1662 } 1662 }
1663 1663