lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 23 Apr 2009 18:04:56 +0200
From:	Christophe Saout <christophe@...ut.de>
To:	netdev@...r.kernel.org
Subject: [RFC][PATCH] Fixing up TCP/UDP checksum for UDP encap. ESP4
 packets in transport mode

Hi,

[resent from linux-net, as it turns out was the wrong mailing list]

I was happily running an transport-mode IPSEC connection where I was
running NAT at one endpoint.  This means that decrypted packets can be
forwarded to another machine, as opposed to being delivered to a local
application.

Later I was forced to encapsulate the IPSEC traffic into UDP because I
had no choice but pass through a NAT device.  Then, unfortunately,
things started to break.  The machine that would receive the answer to a
TCP/SYN packet from the gateway box (that decrypts the packed and then
forwards it) discarded the packets because of a wrong TCP checksum.

I checked the kernel code - esp4.c is just setting CHECKSUM_UNNECESSARY
on these packets, so that they are accepted by local applications.
However, when the packages leaves the machine via a NIC, the packet
still carries the broken checksum.  I checked the RFC on the issue and
one of the suggestions is to recompute the checksum for carried TCP/UDP
packets.

I have a working (but possibly inelegant version), which I am proposing.
I know there are obvious things that can be improved, but I'm just
posting it here for discussion.  Also, I'm not sure my skb handling is
fully correct.

diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 18bb383..b0eba8f 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -295,6 +295,33 @@ static int esp_input_done2(struct sk_buff *skb, int err)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
 
+	if (x->encap && x->props.mode == XFRM_MODE_TRANSPORT &&
+	    (nexthdr[1] == IPPROTO_TCP || nexthdr[1] == IPPROTO_UDP)) {
+		int datalen, thlen;
+		unsigned char *th;
+
+		if (nexthdr[1] == IPPROTO_TCP) {
+			thlen = sizeof(struct tcphdr);
+			skb->csum_offset = offsetof(struct tcphdr, check);
+		} else {
+			thlen = sizeof(struct udphdr);
+			skb->csum_offset = offsetof(struct udphdr, check);
+		}
+
+		datalen = skb->len - alen - padlen - 2 - hlen;
+		if (datalen < 0 || !pskb_may_pull(skb, hlen + thlen))
+			goto out;
+
+		iph = ip_hdr(skb);
+		th = skb_transport_header(skb) + hlen;
+
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		skb->csum_start = th - skb->head;
+		*(__u16 *)(th + skb->csum_offset) =
+				~csum_tcpudp_magic(iph->saddr, iph->daddr,
+				                   datalen, nexthdr[1], 0);
+	}
+
 	pskb_trim(skb, skb->len - alen - padlen - 2);
 	__skb_pull(skb, hlen);
 	skb_set_transport_header(skb, -ihl);


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists