mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-28 00:04:30 +02:00
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@
This commit is contained in:
parent
2985d4062e
commit
c78e6eec78
@ -199,49 +199,50 @@ sys_tun_open(int tun, int mode)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(SSH_TUN_FILTER)
|
#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_INET 2
|
||||||
#define OPENBSD_AF_INET6 24
|
#define OPENBSD_AF_INET6 24
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_tun_infilter(struct Channel *c, char *buf, int len)
|
sys_tun_infilter(struct Channel *c, char *buf, int _len)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
size_t len;
|
||||||
|
char *ptr = buf;
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
char rbuf[CHAN_RBUF];
|
char rbuf[CHAN_RBUF];
|
||||||
struct ip *iph;
|
struct ip iph;
|
||||||
#endif
|
#endif
|
||||||
u_int32_t *af;
|
#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF)
|
||||||
char *ptr = buf;
|
u_int32_t af;
|
||||||
int r;
|
#endif
|
||||||
|
|
||||||
|
/* XXX update channel input filter API to use unsigned length */
|
||||||
|
if (_len < 0)
|
||||||
|
return -1;
|
||||||
|
len = _len;
|
||||||
|
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af)))
|
if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)
|
||||||
return (-1);
|
return -1;
|
||||||
ptr = (char *)&rbuf[0];
|
/* Determine address family from packet IP header. */
|
||||||
bcopy(buf, ptr + sizeof(u_int32_t), len);
|
memcpy(&iph, buf, sizeof(iph));
|
||||||
len += sizeof(u_int32_t);
|
af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;
|
||||||
af = (u_int32_t *)ptr;
|
/* Prepend address family to packet using OpenBSD constants */
|
||||||
|
memcpy(rbuf + 4, buf, len);
|
||||||
iph = (struct ip *)(ptr + sizeof(u_int32_t));
|
len += 4;
|
||||||
switch (iph->ip_v) {
|
POKE_U32(rbuf, af);
|
||||||
case 6:
|
ptr = rbuf;
|
||||||
*af = AF_INET6;
|
#elif defined(SSH_TUN_COMPAT_AF)
|
||||||
break;
|
/* Convert existing address family header to OpenBSD value */
|
||||||
case 4:
|
if (len <= 4)
|
||||||
default:
|
return -1;
|
||||||
*af = AF_INET;
|
af = PEEK_U32(buf);
|
||||||
break;
|
/* Put it back */
|
||||||
}
|
POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SSH_TUN_COMPAT_AF)
|
|
||||||
if (len < (int)sizeof(u_int32_t))
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
af = (u_int32_t *)ptr;
|
|
||||||
if (*af == htonl(AF_INET6))
|
|
||||||
*af = htonl(OPENBSD_AF_INET6);
|
|
||||||
else
|
|
||||||
*af = htonl(OPENBSD_AF_INET);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
|
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)
|
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
|
||||||
{
|
{
|
||||||
u_char *buf;
|
u_char *buf;
|
||||||
u_int32_t *af;
|
u_int32_t af;
|
||||||
int r;
|
int r;
|
||||||
size_t xxx_dlen;
|
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));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
if (dlen != NULL)
|
if (dlen != NULL)
|
||||||
*dlen = xxx_dlen;
|
*dlen = xxx_dlen;
|
||||||
if (*dlen < sizeof(*af))
|
if (*dlen < sizeof(af))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
buf = *data;
|
buf = *data;
|
||||||
|
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
*dlen -= sizeof(u_int32_t);
|
/* skip address family */
|
||||||
buf = *data + sizeof(u_int32_t);
|
*dlen -= sizeof(af);
|
||||||
|
buf = *data + sizeof(af);
|
||||||
#elif defined(SSH_TUN_COMPAT_AF)
|
#elif defined(SSH_TUN_COMPAT_AF)
|
||||||
af = ntohl(*(u_int32_t *)buf);
|
/* translate address family */
|
||||||
if (*af == OPENBSD_AF_INET6)
|
af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET;
|
||||||
*af = htonl(AF_INET6);
|
POKE_U32(buf, af);
|
||||||
else
|
|
||||||
*af = htonl(AF_INET);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
#endif /* SSH_TUN_FILTER */
|
#endif /* SSH_TUN_FILTER */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user