[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