[openssh-commits] [openssh] 01/01: fix problems in tunnel forwarding portability code
git+noreply at mindrot.org
git+noreply at mindrot.org
Fri Jul 28 13:23:10 AEST 2017
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit c78e6eec78c88acf8d51db90ae05a3e39458603d
Author: Damien Miller <djm at mindrot.org>
Date: Fri Jul 21 14:38:16 2017 +1000
fix problems in tunnel forwarding portability code
This fixes a few problems in the tun forwarding code, mostly to do
with host/network byte order confusion.
Based on a report and patch by stepe AT centaurus.uberspace.de;
bz#2735; ok dtucker@
---
openbsd-compat/port-tun.c | 85 +++++++++++++++++++++++------------------------
1 file changed, 42 insertions(+), 43 deletions(-)
diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c
index a444adf1..a7a5d949 100644
--- a/openbsd-compat/port-tun.c
+++ b/openbsd-compat/port-tun.c
@@ -199,49 +199,50 @@ sys_tun_open(int tun, int mode)
*/
#if defined(SSH_TUN_FILTER)
+/*
+ * The tunnel forwarding protocol prepends the address family of forwarded
+ * IP packets using OpenBSD's numbers.
+ */
#define OPENBSD_AF_INET 2
#define OPENBSD_AF_INET6 24
int
-sys_tun_infilter(struct Channel *c, char *buf, int len)
+sys_tun_infilter(struct Channel *c, char *buf, int _len)
{
-#if defined(SSH_TUN_PREPEND_AF)
- char rbuf[CHAN_RBUF];
- struct ip *iph;
-#endif
- u_int32_t *af;
+ int r;
+ size_t len;
char *ptr = buf;
- int r;
-
#if defined(SSH_TUN_PREPEND_AF)
- if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af)))
- return (-1);
- ptr = (char *)&rbuf[0];
- bcopy(buf, ptr + sizeof(u_int32_t), len);
- len += sizeof(u_int32_t);
- af = (u_int32_t *)ptr;
-
- iph = (struct ip *)(ptr + sizeof(u_int32_t));
- switch (iph->ip_v) {
- case 6:
- *af = AF_INET6;
- break;
- case 4:
- default:
- *af = AF_INET;
- break;
- }
+ char rbuf[CHAN_RBUF];
+ struct ip iph;
+#endif
+#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF)
+ u_int32_t af;
#endif
-#if defined(SSH_TUN_COMPAT_AF)
- if (len < (int)sizeof(u_int32_t))
- return (-1);
+ /* XXX update channel input filter API to use unsigned length */
+ if (_len < 0)
+ return -1;
+ len = _len;
- af = (u_int32_t *)ptr;
- if (*af == htonl(AF_INET6))
- *af = htonl(OPENBSD_AF_INET6);
- else
- *af = htonl(OPENBSD_AF_INET);
+#if defined(SSH_TUN_PREPEND_AF)
+ if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)
+ return -1;
+ /* Determine address family from packet IP header. */
+ memcpy(&iph, buf, sizeof(iph));
+ af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;
+ /* Prepend address family to packet using OpenBSD constants */
+ memcpy(rbuf + 4, buf, len);
+ len += 4;
+ POKE_U32(rbuf, af);
+ ptr = rbuf;
+#elif defined(SSH_TUN_COMPAT_AF)
+ /* Convert existing address family header to OpenBSD value */
+ if (len <= 4)
+ return -1;
+ af = PEEK_U32(buf);
+ /* Put it back */
+ POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
#endif
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
@@ -253,7 +254,7 @@ u_char *
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
{
u_char *buf;
- u_int32_t *af;
+ u_int32_t af;
int r;
size_t xxx_dlen;
@@ -262,21 +263,19 @@ sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (dlen != NULL)
*dlen = xxx_dlen;
- if (*dlen < sizeof(*af))
+ if (*dlen < sizeof(af))
return (NULL);
buf = *data;
#if defined(SSH_TUN_PREPEND_AF)
- *dlen -= sizeof(u_int32_t);
- buf = *data + sizeof(u_int32_t);
+ /* skip address family */
+ *dlen -= sizeof(af);
+ buf = *data + sizeof(af);
#elif defined(SSH_TUN_COMPAT_AF)
- af = ntohl(*(u_int32_t *)buf);
- if (*af == OPENBSD_AF_INET6)
- *af = htonl(AF_INET6);
- else
- *af = htonl(AF_INET);
+ /* translate address family */
+ af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET;
+ POKE_U32(buf, af);
#endif
-
return (buf);
}
#endif /* SSH_TUN_FILTER */
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list