[openssh-commits] [openssh] 05/06: upstream: ssh: add PermitRemoteOpen for remote dynamic forwarding

git+noreply at mindrot.org git+noreply at mindrot.org
Wed Feb 17 15:08:55 AEDT 2021


This is an automated email from the git hooks/post-receive script.

dtucker pushed a commit to branch master
in repository openssh.

commit da0a9afcc446a30ca49dd216612c41ac3cb1f2d4
Author: markus at openbsd.org <markus at openbsd.org>
Date:   Mon Feb 15 20:43:15 2021 +0000

    upstream: ssh: add PermitRemoteOpen for remote dynamic forwarding
    
    with SOCKS ok djm@, dtucker@
    
    OpenBSD-Commit-ID: 64fe7b6360acc4ea56aa61b66498b5ecc0a96a7c
---
 channels.c   | 21 +++++++++++++++++++-
 readconf.c   | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 readconf.h   |  6 +++++-
 ssh.1        |  5 +++--
 ssh.c        | 43 ++++++++++++++++++++++++++++++++++++++++-
 ssh_config.5 | 41 ++++++++++++++++++++++++++++++++++++++-
 6 files changed, 170 insertions(+), 9 deletions(-)

diff --git a/channels.c b/channels.c
index 4fccd0b3..b60d56c4 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.404 2021/01/27 09:26:53 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.405 2021/02/15 20:43:15 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -4478,9 +4478,28 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
 static int
 rdynamic_connect_finish(struct ssh *ssh, Channel *c)
 {
+	struct ssh_channels *sc = ssh->chanctxt;
+	struct permission_set *pset = &sc->local_perms;
+	struct permission *perm;
 	struct channel_connect cctx;
+	u_int i, permit_adm = 1;
 	int sock;
 
+	if (pset->num_permitted_admin > 0) {
+		permit_adm = 0;
+		for (i = 0; i < pset->num_permitted_admin; i++) {
+			perm = &pset->permitted_admin[i];
+			if (open_match(perm, c->path, c->host_port)) {
+				permit_adm = 1;
+				break;
+			}
+		}
+	}
+	if (!permit_adm) {
+		debug_f("requested forward not permitted");
+		return -1;
+	}
+
 	memset(&cctx, 0, sizeof(cctx));
 	sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
 	    NULL, &cctx, NULL, NULL);
diff --git a/readconf.c b/readconf.c
index c9cd7f70..b0a85097 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.350 2021/01/26 05:32:21 dtucker Exp $ */
+/* $OpenBSD: readconf.c,v 1.351 2021/02/15 20:43:15 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -147,6 +147,7 @@ typedef enum {
 	oPasswordAuthentication,
 	oChallengeResponseAuthentication, oXAuthLocation,
 	oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
+	oPermitRemoteOpen,
 	oCertificateFile, oAddKeysToAgent, oIdentityAgent,
 	oUser, oEscapeChar, oProxyCommand,
 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
@@ -247,6 +248,7 @@ static struct {
 	{ "macs", oMacs },
 	{ "remoteforward", oRemoteForward },
 	{ "localforward", oLocalForward },
+	{ "permitremoteopen", oPermitRemoteOpen },
 	{ "user", oUser },
 	{ "host", oHost },
 	{ "match", oMatch },
@@ -318,6 +320,7 @@ static struct {
 	{ NULL, oBadOption }
 };
 
+static const char *lookup_opcode_name(OpCodes code);
 
 const char *
 kex_default_pk_alg(void)
@@ -912,9 +915,9 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
     const char *original_host, char *line, const char *filename,
     int linenum, int *activep, int flags, int *want_final_pass, int depth)
 {
-	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
 	char **cpptr, ***cppptr, fwdarg[256];
-	u_int i, *uintptr, max_entries = 0;
+	u_int i, *uintptr, uvalue, max_entries = 0;
 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
 	int remotefwd, dynamicfwd;
 	LogLevel *log_level_ptr;
@@ -1482,6 +1485,51 @@ parse_pubkey_algos:
 		}
 		break;
 
+	case oPermitRemoteOpen:
+		uintptr = &options->num_permitted_remote_opens;
+		cppptr = &options->permitted_remote_opens;
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%s line %d: missing %s specification",
+			    filename, linenum, lookup_opcode_name(opcode));
+		uvalue = *uintptr;	/* modified later */
+		if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
+			if (*activep && uvalue == 0) {
+				*uintptr = 1;
+				*cppptr = xcalloc(1, sizeof(**cppptr));
+				(*cppptr)[0] = xstrdup(arg);
+			}
+			break;
+		}
+		for (; arg != NULL && *arg != '\0'; arg = strdelim(&s)) {
+			arg2 = xstrdup(arg);
+			ch = '\0';
+			p = hpdelim2(&arg, &ch);
+			if (p == NULL || ch == '/') {
+				fatal("%s line %d: missing host in %s",
+				    filename, linenum,
+				    lookup_opcode_name(opcode));
+			}
+			p = cleanhostname(p);
+			/*
+			 * don't want to use permitopen_port to avoid
+			 * dependency on channels.[ch] here.
+			 */
+			if (arg == NULL ||
+			    (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
+				fatal("%s line %d: bad port number in %s",
+				    filename, linenum,
+				    lookup_opcode_name(opcode));
+			}
+			if (*activep && uvalue == 0) {
+				opt_array_append(filename, linenum,
+				    lookup_opcode_name(opcode),
+				    cppptr, uintptr, arg2);
+			}
+			free(arg2);
+		}
+		break;
+
 	case oClearAllForwardings:
 		intptr = &options->clear_forwardings;
 		goto parse_flag;
@@ -2173,6 +2221,8 @@ initialize_options(Options * options)
 	options->num_local_forwards = 0;
 	options->remote_forwards = NULL;
 	options->num_remote_forwards = 0;
+	options->permitted_remote_opens = NULL;
+	options->num_permitted_remote_opens = 0;
 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
 	options->log_level = SYSLOG_LEVEL_NOT_SET;
 	options->num_log_verbose = 0;
@@ -3126,6 +3176,13 @@ dump_client_config(Options *o, const char *host)
 
 	/* Special cases */
 
+	/* PermitRemoteOpen */
+	if (o->num_permitted_remote_opens == 0)
+		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
+	else
+		dump_cfg_strarray_oneline(oPermitRemoteOpen,
+		    o->num_permitted_remote_opens, o->permitted_remote_opens);
+
 	/* AddKeysToAgent */
 	if (o->add_keys_to_agent_lifespan <= 0)
 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
diff --git a/readconf.h b/readconf.h
index 6e7e95e7..2fba866e 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.139 2021/01/26 05:32:21 dtucker Exp $ */
+/* $OpenBSD: readconf.h,v 1.140 2021/02/15 20:43:15 markus Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -110,6 +110,10 @@ typedef struct {
 	struct Forward *remote_forwards;
 	int	clear_forwardings;
 
+	/* Restrict remote dynamic forwarding */
+	char  **permitted_remote_opens;
+	u_int	num_permitted_remote_opens;
+
 	/* stdio forwarding (-W) host and port */
 	char   *stdio_forward_host;
 	int	stdio_forward_port;
diff --git a/ssh.1 b/ssh.1
index 5884b471..0a01767e 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh.1,v 1.418 2021/01/26 15:40:17 naddy Exp $
-.Dd $Mdocdate: January 26 2021 $
+.\" $OpenBSD: ssh.1,v 1.419 2021/02/15 20:43:15 markus Exp $
+.Dd $Mdocdate: February 15 2021 $
 .Dt SSH 1
 .Os
 .Sh NAME
@@ -531,6 +531,7 @@ For full details of the options listed below, and their possible values, see
 .It NumberOfPasswordPrompts
 .It PasswordAuthentication
 .It PermitLocalCommand
+.It PermitRemoteOpen
 .It PKCS11Provider
 .It Port
 .It PreferredAuthentications
diff --git a/ssh.c b/ssh.c
index 21f3fca7..220d2080 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.550 2021/02/02 22:36:59 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.551 2021/02/15 20:43:15 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1874,12 +1874,53 @@ ssh_init_stdio_forwarding(struct ssh *ssh)
 	channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
 }
 
+static void
+ssh_init_forward_permissions(struct ssh *ssh, const char *what, char **opens,
+    u_int num_opens)
+{
+	u_int i;
+	int port;
+	char *addr, *arg, *oarg, ch;
+	int where = FORWARD_LOCAL;
+
+	channel_clear_permission(ssh, FORWARD_ADM, where);
+	if (num_opens == 0)
+		return; /* permit any */
+
+	/* handle keywords: "any" / "none" */
+	if (num_opens == 1 && strcmp(opens[0], "any") == 0)
+		return;
+	if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
+		channel_disable_admin(ssh, where);
+		return;
+	}
+	/* Otherwise treat it as a list of permitted host:port */
+	for (i = 0; i < num_opens; i++) {
+		oarg = arg = xstrdup(opens[i]);
+		ch = '\0';
+		addr = hpdelim2(&arg, &ch);
+		if (addr == NULL || ch == '/')
+			fatal_f("missing host in %s", what);
+		addr = cleanhostname(addr);
+		if (arg == NULL || ((port = permitopen_port(arg)) < 0))
+			fatal_f("bad port number in %s", what);
+		/* Send it to channels layer */
+		channel_add_permission(ssh, FORWARD_ADM,
+		    where, addr, port);
+		free(oarg);
+	}
+}
+
 static void
 ssh_init_forwarding(struct ssh *ssh, char **ifname)
 {
 	int success = 0;
 	int i;
 
+	ssh_init_forward_permissions(ssh, "permitremoteopen",
+	    options.permitted_remote_opens,
+	    options.num_permitted_remote_opens);
+
 	if (options.exit_on_forward_failure)
 		forward_confirms_pending = 0; /* track pending requests */
 	/* Initiate local TCP/IP port forwardings. */
diff --git a/ssh_config.5 b/ssh_config.5
index fb3a3a41..8764e87b 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,7 +33,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh_config.5,v 1.346 2021/02/15 11:09:22 dlg Exp $
+.\" $OpenBSD: ssh_config.5,v 1.347 2021/02/15 20:43:15 markus Exp $
 .Dd $Mdocdate: February 15 2021 $
 .Dt SSH_CONFIG 5
 .Os
@@ -1290,6 +1290,42 @@ The argument must be
 or
 .Cm no
 (the default).
+.It Cm PermitRemoteOpen
+Specifies the destinations to which remote TCP port forwarding is permitted when
+.Cm RemoteForward
+is used as a SOCKS proxy.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Cm any
+can be used to remove all restrictions and permit any forwarding requests.
+An argument of
+.Cm none
+can be used to prohibit all forwarding requests.
+The wildcard
+.Sq *
+can be used for host or port to allow all hosts or ports respectively.
+Otherwise, no pattern matching or address lookups are performed on supplied
+names.
 .It Cm PKCS11Provider
 Specifies which PKCS#11 provider to use or
 .Cm none
@@ -1484,6 +1520,9 @@ If forwarding to a specific destination then the second argument must be
 or a Unix domain socket path,
 otherwise if no destination argument is specified then the remote forwarding
 will be established as a SOCKS proxy.
+When acting as a SOCKS proxy the destination of the connection can be
+restricted by
+.Cm PermitRemoteOpen .
 .Pp
 IPv6 addresses can be specified by enclosing addresses in square brackets.
 Multiple forwardings may be specified, and additional

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list