[PATCH] global port forwarding restriction

Tony Finch dot at dotat.at
Wed Aug 14 05:50:07 EST 2002


Here's another patch for people providing ssh access to restricted
environments.

We allow our users to use port forwarding when logging into our mail
servers so that they can use it to fetch mail over an encrypted channel
using clients that don't support TLS, for example fetchmail.  (In fact,
fetchmail has built-in ssh support.) However we don't want them connecting
to other places pretending to be us, or using the feature to dig around
inside the system's private network, etc. etc.

This patch makes the existing permitopen="host:port" authorized_keys file
option available in sshd_config, enabling the administrator to make it
a global restriction rather than a per-key restriction.

Any comments and suggested improvements are welcome. In particular,
I'm not entirely sure that I have connected the pieces up in the most
elegant fashion. I did also consider creating two new directives -- one
for each direction of TCP forwarding -- so that enabling them could be
configured independently, but that got a bit ugly and anyway listening
ports bound to localhost aren't all that dodgy.

Tony.
-- 
f.a.n.finch <dot at dotat.at> http://dotat.at/
NORTHWEST ROCKALL MALIN HEBRIDES: SOUTHWEST 4 OR 5 BACKING SOUTHEAST 5 OR 6,
OCCASIONALLY 7 LATER. RAIN AT TIMES. MODERATE OR GOOD.



--- auth-options.c	26 Jul 2002 11:02:28 -0000	1.3
+++ auth-options.c	13 Aug 2002 19:16:27 -0000
@@ -221,8 +221,6 @@
 		}
 		cp = "permitopen=\"";
 		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
-			char host[256], sport[6];
-			u_short port;
 			char *patterns = xmalloc(strlen(opts) + 1);
 
 			opts += strlen(cp);
@@ -247,8 +245,7 @@
 			}
 			patterns[i] = 0;
 			opts++;
-			if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 &&
-			    sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) {
+			if (channel_add_permitted_opens(patterns) < 0) {
 				debug("%.100s, line %lu: Bad permitopen specification "
 				    "<%.100s>", file, linenum, patterns);
 				auth_debug_add("%.100s, line %lu: "
@@ -256,16 +253,6 @@
 				xfree(patterns);
 				goto bad_option;
 			}
-			if ((port = a2port(sport)) == 0) {
-				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
-				    file, linenum, sport);
-				auth_debug_add("%.100s, line %lu: "
-				    "Bad permitopen port", file, linenum);
-				xfree(patterns);
-				goto bad_option;
-			}
-			if (options.allow_tcp_forwarding)
-				channel_add_permitted_opens(host, port);
 			xfree(patterns);
 			goto next_option;
 		}
--- channels.c	24 Jul 2002 11:04:17 -0000	1.1.1.1
+++ channels.c	13 Aug 2002 19:17:08 -0000
@@ -96,6 +96,10 @@
 
 /* Number of permitted host/port pairs in the array. */
 static int num_permitted_opens = 0;
+
+/* Don't allow any more to be added. */
+static int fix_permitted_opens = 0;
+
 /*
  * If this is true, all opens are permitted.  This is the case on the server
  * on which we have to trust the client anyway, and the user could do
@@ -2212,10 +2216,31 @@
 		all_opens_permitted = 1;
 }
 
+/*
+ * If the server-wide configuration specifies some permitted_opens
+ * then don't allow users to add to them.
+ */
 void
-channel_add_permitted_opens(char *host, int port)
+channel_fix_permitted_opens(void)
 {
-	if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
+	if (num_permitted_opens != 0)
+		fix_permitted_opens = 1;
+}
+
+int
+channel_add_permitted_opens(char *hostport)
+{
+	char host[256], sport[6];
+	u_short port;
+
+	if (sscanf(hostport, "%255[^:]:%5[0-9]", host, sport) != 2 &&
+	    sscanf(hostport, "%255[^/]/%5[0-9]", host, sport) != 2)
+		return -1;
+	if ((port = a2port(sport)) == 0)
+		return -1;
+
+	if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION ||
+	    fix_permitted_opens)
 		fatal("channel_request_remote_forwarding: too many forwards");
 	debug("allow port forwarding to host %s port %d", host, port);
 
@@ -2224,6 +2249,7 @@
 	num_permitted_opens++;
 
 	all_opens_permitted = 0;
+	return 0;
 }
 
 void
@@ -2231,6 +2257,8 @@
 {
 	int i;
 
+	if (fix_permitted_opens)
+		return;
 	for (i = 0; i < num_permitted_opens; i++)
 		xfree(permitted_opens[i].host_to_connect);
 	num_permitted_opens = 0;
--- channels.h	24 Jul 2002 11:04:17 -0000	1.1.1.1
+++ channels.h	13 Aug 2002 18:47:22 -0000
@@ -193,7 +193,8 @@
 /* tcp forwarding */
 void	 channel_set_af(int af);
 void     channel_permit_all_opens(void);
-void	 channel_add_permitted_opens(char *, int);
+void     channel_fix_permitted_opens(void);
+int	 channel_add_permitted_opens(char *);
 void	 channel_clear_permitted_opens(void);
 void     channel_input_port_forward_request(int, int);
 int	 channel_connect_to(const char *, u_short);
--- servconf.c	26 Jul 2002 11:02:28 -0000	1.3
+++ servconf.c	13 Aug 2002 18:50:33 -0000
@@ -41,6 +41,7 @@
 #include "cipher.h"
 #include "kex.h"
 #include "mac.h"
+#include "channels.h"
 
 static void add_listen_addr(ServerOptions *, char *, u_short);
 static void add_one_listen_addr(ServerOptions *, char *, u_short);
@@ -236,6 +237,7 @@
 		options->allow_tcp_forwarding = 1;
 	if (options->gateway_ports == -1)
 		options->gateway_ports = 0;
+	channel_fix_permitted_opens();
 	if (options->max_startups == -1)
 		options->max_startups = 10;
 	if (options->max_startups_rate == -1)
@@ -297,7 +299,7 @@
 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
 	sStrictModes, sEmptyPasswd, sKeepAlives,
 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
-	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sPermitTcpConnect,
 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
 	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
@@ -364,6 +366,7 @@
 	{ "compression", sCompression },
 	{ "keepalive", sKeepAlives },
 	{ "allowtcpforwarding", sAllowTcpForwarding },
+	{ "permittcpconnect", sPermitTcpConnect },
 	{ "allowusers", sAllowUsers },
 	{ "denyusers", sDenyUsers },
 	{ "allowgroups", sAllowGroups },
@@ -764,6 +767,18 @@
 	case sAllowTcpForwarding:
 		intptr = &options->allow_tcp_forwarding;
 		goto parse_flag;
+
+	case sPermitTcpConnect:
+		arg = strdelim(&cp);
+		p = NULL;
+		if (!arg || *arg == '\0')
+			p = "missing";
+		if (channel_add_permitted_opens(arg) < 0)
+			p = "bad";
+		if (p != NULL)
+			fatal("%.200s, line %d: %s inet addr:port.",
+			    filename, linenum, p);
+		break;
 
 	case sUsePrivilegeSeparation:
 		intptr = &use_privsep;



More information about the openssh-unix-dev mailing list