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;