summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkus <markus@openbsd.org>2014-06-27 16:41:56 +0000
committermarkus <markus@openbsd.org>2014-06-27 16:41:56 +0000
commitf7ab312325305bcdb84d0903fe8fd84c4e3e7aa0 (patch)
treecf2cc38d91000082904fa7957b3434cfd7e5606a
parentDo not KASSERT an unsigned value being >= 0 after decrementing it; instead, (diff)
downloadwireguard-openbsd-f7ab312325305bcdb84d0903fe8fd84c4e3e7aa0.tar.xz
wireguard-openbsd-f7ab312325305bcdb84d0903fe8fd84c4e3e7aa0.zip
fix remote fwding with same listen port but different listen address
with gerhard@, ok djm@
-rw-r--r--usr.bin/ssh/channels.c96
-rw-r--r--usr.bin/ssh/channels.h5
-rw-r--r--usr.bin/ssh/clientloop.c4
-rw-r--r--usr.bin/ssh/ssh.c6
4 files changed, 79 insertions, 32 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c
index 5421e15215e..9ec2d45a710 100644
--- a/usr.bin/ssh/channels.c
+++ b/usr.bin/ssh/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.332 2014/04/28 03:09:18 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.333 2014/06/27 16:41:56 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -106,7 +106,8 @@ static int channel_max_fd = 0;
typedef struct {
char *host_to_connect; /* Connect to 'host'. */
u_short port_to_connect; /* Connect to 'port'. */
- u_short listen_port; /* Remote side should listen port number. */
+ char *listen_host; /* Remote side should listen address. */
+ u_short listen_port; /* Remote side should listen port. */
} ForwardPermission;
/* List of all permitted host/port pairs to connect by the user. */
@@ -3001,11 +3002,52 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
idx = num_permitted_opens++;
permitted_opens[idx].host_to_connect = xstrdup(host_to_connect);
permitted_opens[idx].port_to_connect = port_to_connect;
+ permitted_opens[idx].listen_host = listen_host ?
+ xstrdup(listen_host) : NULL;
permitted_opens[idx].listen_port = listen_port;
}
return (idx);
}
+static int
+open_match(ForwardPermission *allowed_open, const char *requestedhost,
+ u_short requestedport)
+{
+ if (allowed_open->host_to_connect == NULL)
+ return 0;
+ if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
+ allowed_open->port_to_connect != requestedport)
+ return 0;
+ if (strcmp(allowed_open->host_to_connect, requestedhost) != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Note that in he listen host/port case
+ * we don't support FWD_PERMIT_ANY_PORT and
+ * need to translate between the configured-host (listen_host)
+ * and what we've sent to the remote server (channel_rfwd_bind_host)
+ */
+static int
+open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
+ u_short requestedport, int translate)
+{
+ const char *allowed_host;
+
+ if (allowed_open->host_to_connect == NULL)
+ return 0;
+ if (allowed_open->listen_port != requestedport)
+ return 0;
+ allowed_host = translate ?
+ channel_rfwd_bind_host(allowed_open->listen_host) :
+ allowed_open->listen_host;
+ if (allowed_host == NULL ||
+ strcmp(allowed_host, requestedhost) != 0)
+ return 0;
+ return 1;
+}
+
/*
* Request cancellation of remote forwarding of connection host:port from
* local side.
@@ -3019,8 +3061,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
return -1;
for (i = 0; i < num_permitted_opens; i++) {
- if (permitted_opens[i].host_to_connect != NULL &&
- permitted_opens[i].listen_port == port)
+ if (open_listen_match(&permitted_opens[i], host, port, 0))
break;
}
if (i >= num_permitted_opens) {
@@ -3034,10 +3075,12 @@ channel_request_rforward_cancel(const char *host, u_short port)
packet_put_int(port);
packet_send();
- permitted_opens[i].listen_port = 0;
permitted_opens[i].port_to_connect = 0;
+ permitted_opens[i].listen_port = 0;
free(permitted_opens[i].host_to_connect);
permitted_opens[i].host_to_connect = NULL;
+ free(permitted_opens[i].listen_host);
+ permitted_opens[i].listen_host = NULL;
return 0;
}
@@ -3101,6 +3144,8 @@ channel_add_permitted_opens(char *host, int port)
num_permitted_opens + 1, sizeof(*permitted_opens));
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
permitted_opens[num_permitted_opens].port_to_connect = port;
+ permitted_opens[num_permitted_opens].listen_host = NULL;
+ permitted_opens[num_permitted_opens].listen_port = 0;
num_permitted_opens++;
all_opens_permitted = 0;
@@ -3132,6 +3177,8 @@ channel_update_permitted_opens(int idx, int newport)
permitted_opens[idx].port_to_connect = 0;
free(permitted_opens[idx].host_to_connect);
permitted_opens[idx].host_to_connect = NULL;
+ free(permitted_opens[idx].listen_host);
+ permitted_opens[idx].listen_host = NULL;
}
}
@@ -3145,6 +3192,8 @@ channel_add_adm_permitted_opens(char *host, int port)
permitted_adm_opens[num_adm_permitted_opens].host_to_connect
= xstrdup(host);
permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
+ permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
+ permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
return ++num_adm_permitted_opens;
}
@@ -3162,8 +3211,10 @@ channel_clear_permitted_opens(void)
{
int i;
- for (i = 0; i < num_permitted_opens; i++)
+ for (i = 0; i < num_permitted_opens; i++) {
free(permitted_opens[i].host_to_connect);
+ free(permitted_opens[i].listen_host);
+ }
free(permitted_opens);
permitted_opens = NULL;
num_permitted_opens = 0;
@@ -3174,8 +3225,10 @@ channel_clear_adm_permitted_opens(void)
{
int i;
- for (i = 0; i < num_adm_permitted_opens; i++)
+ for (i = 0; i < num_adm_permitted_opens; i++) {
free(permitted_adm_opens[i].host_to_connect);
+ free(permitted_adm_opens[i].listen_host);
+ }
free(permitted_adm_opens);
permitted_adm_opens = NULL;
num_adm_permitted_opens = 0;
@@ -3213,15 +3266,6 @@ permitopen_port(const char *p)
return -1;
}
-static int
-port_match(u_short allowedport, u_short requestedport)
-{
- if (allowedport == FWD_PERMIT_ANY_PORT ||
- allowedport == requestedport)
- return 1;
- return 0;
-}
-
/* Try to start non-blocking connect to next host in cctx list */
static int
connect_next(struct channel_connect *cctx)
@@ -3316,13 +3360,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
}
Channel *
-channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
+channel_connect_by_listen_address(const char *listen_host,
+ u_short listen_port, char *ctype, char *rname)
{
int i;
for (i = 0; i < num_permitted_opens; i++) {
- if (permitted_opens[i].host_to_connect != NULL &&
- port_match(permitted_opens[i].listen_port, listen_port)) {
+ if (open_listen_match(&permitted_opens[i], listen_host,
+ listen_port, 1)) {
return connect_to(
permitted_opens[i].host_to_connect,
permitted_opens[i].port_to_connect, ctype, rname);
@@ -3342,20 +3387,19 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
permit = all_opens_permitted;
if (!permit) {
for (i = 0; i < num_permitted_opens; i++)
- if (permitted_opens[i].host_to_connect != NULL &&
- port_match(permitted_opens[i].port_to_connect, port) &&
- strcmp(permitted_opens[i].host_to_connect, host) == 0)
+ if (open_match(&permitted_opens[i], host, port)) {
permit = 1;
+ break;
+ }
}
if (num_adm_permitted_opens > 0) {
permit_adm = 0;
for (i = 0; i < num_adm_permitted_opens; i++)
- if (permitted_adm_opens[i].host_to_connect != NULL &&
- port_match(permitted_adm_opens[i].port_to_connect, port) &&
- strcmp(permitted_adm_opens[i].host_to_connect, host)
- == 0)
+ if (open_match(&permitted_adm_opens[i], host, port)) {
permit_adm = 1;
+ break;
+ }
}
if (!permit || !permit_adm) {
diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h
index 9e5fe0e8bc1..a7537cb453c 100644
--- a/usr.bin/ssh/channels.h
+++ b/usr.bin/ssh/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.113 2013/06/07 15:37:52 dtucker Exp $ */
+/* $OpenBSD: channels.h,v 1.114 2014/06/27 16:41:56 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -263,7 +263,8 @@ void channel_print_adm_permitted_opens(void);
int channel_input_port_forward_request(int, int);
Channel *channel_connect_to(const char *, u_short, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
-Channel *channel_connect_by_listen_address(u_short, char *, char *);
+Channel *channel_connect_by_listen_address(const char *, u_short,
+ char *, char *);
int channel_request_remote_forwarding(const char *, u_short,
const char *, u_short);
int channel_setup_local_fwd_listener(const char *, u_short,
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
index b5227e6a108..4153688c8ca 100644
--- a/usr.bin/ssh/clientloop.c
+++ b/usr.bin/ssh/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.259 2014/04/29 13:10:30 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.260 2014/06/27 16:41:56 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1837,7 +1837,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
"originator %s port %d", listen_address, listen_port,
originator_address, originator_port);
- c = channel_connect_by_listen_address(listen_port,
+ c = channel_connect_by_listen_address(listen_address, listen_port,
"forwarded-tcpip", originator_address);
free(originator_address);
diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
index 2a1529d67c5..17f6363a236 100644
--- a/usr.bin/ssh/ssh.c
+++ b/usr.bin/ssh/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.403 2014/06/24 02:19:48 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.404 2014/06/27 16:41:56 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1231,8 +1231,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
Forward *rfwd = (Forward *)ctxt;
/* XXX verbose() on failure? */
- debug("remote forward %s for: listen %d, connect %s:%d",
+ debug("remote forward %s for: listen %s%s%d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
+ rfwd->listen_host == NULL ? "" : rfwd->listen_host,
+ rfwd->listen_host == NULL ? "" : ":",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
if (rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) {