netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* (unknown), 
@ 2012-02-01  0:50 Shawn Lu
  2012-02-01  0:50 ` [PATCH] tcp: md5: fix md5 RST when both sides have listener Shawn Lu
  0 siblings, 1 reply; 19+ messages in thread
From: Shawn Lu @ 2012-02-01  0:50 UTC (permalink / raw)
  To: eric.dumazet; +Cc: davem, netdev, xiaoclu

From: Shawn Lu <shawn.lu@ericsson.com>
Subject: [PATCH] tcp: md5: fix md5 RST when both sides have listener
In-Reply-To: RE: [PATCH] tcp: md5: fix md5 RST when both sides have listener

^ permalink raw reply	[flat|nested] 19+ messages in thread
* [PATCH] tcp: md5: fix md5 RST when both sides have listener
@ 2012-01-31  2:07 Shawn Lu
  2012-01-31  2:16 ` Eric Dumazet
  0 siblings, 1 reply; 19+ messages in thread
From: Shawn Lu @ 2012-01-31  2:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, xiaoclu

TCP RST mechanism is broken in TCP md5(RFC2385). When
connection is gone, md5 key is lost, sending RST without
md5 hash is deem to ignored by peer. This can be a problem
since RST help protocal like bgp fast recove from peer crash.

In most case, users of tcp md5, such as bgp and ldp, have listeners
on both sides. md5 keys for peers are saved in listening socket.
When passive side connection is gone, we can still get md5 key
from listening socket. When active side of connection is gone,
we can try to find listening socket through source port, and
then md5 key.
we are not loosing sercuriy here: packet is valified checked with
md5 hash. No RST is generated if md5 hash doesn't match or no md5
key can be found.

Signed-off-by: Shawn Lu <shawn.lu@ericsson.com>
---
 net/ipv4/tcp_ipv4.c |   31 ++++++++++++++++++++++++++++++-
 net/ipv6/tcp_ipv6.c |   34 ++++++++++++++++++++++++++++++++--
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 337ba4c..b2358b4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -601,6 +601,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 	struct ip_reply_arg arg;
 #ifdef CONFIG_TCP_MD5SIG
 	struct tcp_md5sig_key *key;
+	 __u8 *hash_location = NULL;
+	unsigned char newhash[16];
+	int genhash;
 #endif
 	struct net *net;
 
@@ -631,7 +634,33 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 	arg.iov[0].iov_len  = sizeof(rep.th);
 
 #ifdef CONFIG_TCP_MD5SIG
-	key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
+	hash_location = tcp_parse_md5sig_option(th);
+	if (!sk && hash_location) {
+		/*
+		 * active side is lost. Try to find listening socket through
+		 * source port, and then find md5 key through listening socket.
+		 * we are not loose security here:
+		 * Incoming packet is checked with md5 hash with finding key,
+		 * no RST generated if md5 hash doesn't match.
+		 */
+		sk = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
+					    &tcp_hashinfo, ip_hdr(skb)->daddr,
+					    ntohs(th->source), inet_iif(skb));
+		/* don't send rst if it can't find key */
+		if (!sk)
+			return;
+		key = tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr);
+		if (!key)
+			return;
+		genhash = tcp_v4_md5_hash_skb(newhash, key,
+					      NULL, NULL, skb);
+		if (genhash || memcmp(hash_location, newhash, 16) != 0)
+			return;
+
+	} else {
+		key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
+	}
+
 	if (key) {
 		rep.opt[0] = htonl((TCPOPT_NOP << 24) |
 				   (TCPOPT_NOP << 16) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3edd05a..1da99fd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1074,6 +1074,12 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 	const struct tcphdr *th = tcp_hdr(skb);
 	u32 seq = 0, ack_seq = 0;
 	struct tcp_md5sig_key *key = NULL;
+#ifdef CONFIG_TCP_MD5SIG
+	__u8 *hash_location = NULL;
+	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+	unsigned char newhash[16];
+	int genhash;
+#endif
 
 	if (th->rst)
 		return;
@@ -1082,8 +1088,32 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 		return;
 
 #ifdef CONFIG_TCP_MD5SIG
-	if (sk)
-		key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
+	hash_location = tcp_parse_md5sig_option(th);
+	if (!sk && hash_location) {
+		/*
+		 * active side is lost. Try to find listening socket through
+		 * source port, and then find md5 key through listening socket.
+		 * we are not loose security here:
+		 * Incoming packet is checked with md5 hash with finding key,
+		 * no RST generated if md5 hash doesn't match.
+		 */
+		sk = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
+					   &tcp_hashinfo, &ipv6h->daddr,
+					   ntohs(th->source), inet6_iif(skb));
+		if (!sk)
+			return;
+
+		key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
+		if (!key)
+			return;
+
+		genhash = tcp_v6_md5_hash_skb(newhash, key,
+					      NULL, NULL, skb);
+		if (genhash || memcmp(hash_location, newhash, 16) != 0)
+			return;
+	} else {
+		key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
+	}
 #endif
 
 	if (th->ack)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-02-01 18:48 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <RE: [PATCH] tcp: md5: fix md5 RST when both sides have listener>
2012-01-31 23:53 ` [PATCH] tcp: md5: fix md5 RST when both sides have listener Shawn Lu
2012-02-01  5:09   ` Eric Dumazet
2012-02-01  7:48     ` Shawn Lu
2012-02-01  7:53       ` Eric Dumazet
2012-02-01  8:11         ` Shawn Lu
2012-02-01  9:25           ` Eric Dumazet
2012-02-01  8:35 ` [PATCH] tcp: md5: RST: getting md5 key from listener Shawn Lu
2012-02-01  9:54   ` Eric Dumazet
2012-02-01 17:44     ` David Miller
2012-02-01 18:48     ` Shawn Lu
2012-02-01  0:50 (unknown), Shawn Lu
2012-02-01  0:50 ` [PATCH] tcp: md5: fix md5 RST when both sides have listener Shawn Lu
2012-02-01  4:08   ` Eric Dumazet
  -- strict thread matches above, loose matches on Subject: below --
2012-01-31  2:07 Shawn Lu
2012-01-31  2:16 ` Eric Dumazet
2012-01-31  2:37   ` Shawn Lu
2012-01-31  8:39   ` Shawn Lu
2012-01-31  9:05     ` Eric Dumazet
2012-01-31 13:33       ` Eric Dumazet
2012-01-31 18:15         ` Shawn Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).