Subject: kern/26062: TCP_SIGNATURE code causes crashes and doesn't work
To: None <gnats-bugs@gnats.NetBSD.org>
From: Jeff Rizzo <riz@boogers.sf.ca.us>
List: netbsd-bugs
Date: 06/25/2004 16:00:02
>Number: 26062
>Category: kern
>Synopsis: TCP_SIGNATURE code causes crashes and doesn't work
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 25 23:01:01 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Jeff Rizzo
>Release: NetBSD 2.0F (source date 20040625)
>Organization:
Jeff Rizzo http://www.redcrowgroup.com/
>Environment:
System: NetBSD md5test.boogers.sf.ca.us 2.0F NetBSD 2.0F (MD5TEST) #14: Fri Jun 25 15:28:49 PDT 2004 riz@lychee.tastylime.net:/usr/src-current/sys/arch/i386/compile/MD5TEST i386
Architecture: i386
Machine: i386
>Description:
There are a few places where, if options TCP_SIGNATURE
is enabled, key_freesav() will be called with a NULL
pointer, causing a panic. In addition, the tcp_signature()
function doesn't correctly ignore the TCP options when
making the MD5 hash as required by RFC2385, so without the
patch I've appended, NetBSD won't interoperate with MD5
passwords on commercial routers.
In addition, it appears the line:
tb.t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
was inadvertantly removed in revision 1.206, which would
cause problems even if TCP_SIGNATURE was *not* enabled.
With the appended patch, I was able to get a patched quagga
BGP daemon (using Bruce M. Simpson's patches for quagga)
running on NetBSD to successfully peer with a Cisco router
using RFC2835 passwords.
Bruce M. Simpson's patches for quagga are available here:
http://people.freebsd.org/~bms/dump/quagga-tcpmd5/
>How-To-Repeat:
compile a kernel with options TCP_SIGNATURE and either options
IPSEC or options FAST_IPSEC. Watch the machine crash if
it gets packets with an MD5 signature if no SA is configured.
Even if the SA is properly configured, and the quagga BGP
daemon has been patched for RFC2385 support, it will not
interoperate with (for example) a Cisco.
>Fix:
Apply the following patch to sys/netinet/tcp_input.c :
Index: tcp_input.c
===================================================================
RCS file: /usr/mirror/main/src/sys/netinet/tcp_input.c,v
retrieving revision 1.207
diff -u -r1.207 tcp_input.c
--- tcp_input.c 23 May 2004 00:37:27 -0000 1.207
+++ tcp_input.c 25 Jun 2004 22:07:22 -0000
@@ -2630,11 +2630,13 @@
struct ippseudo ippseudo;
struct ip6_hdr_pseudo ip6pseudo;
struct tcphdr th0;
- int l;
+ int l, tcphdrlen;
if (sav == NULL)
return (-1);
+ tcphdrlen = th->th_off * 4;
+
switch (mtod(m, struct ip *)->ip_v) {
case 4:
ip = mtod(m, struct ip *);
@@ -2674,10 +2676,10 @@
th0.th_sum = 0;
MD5Update(&ctx, (char *)&th0, sizeof(th0));
- l = m->m_pkthdr.len - thoff - sizeof(struct tcphdr);
+ l = m->m_pkthdr.len - thoff - tcphdrlen;
if (l > 0)
- m_apply(m, thoff + sizeof(struct tcphdr),
- m->m_pkthdr.len - thoff - sizeof(struct tcphdr),
+ m_apply(m, thoff + tcphdrlen,
+ m->m_pkthdr.len - thoff - tcphdrlen,
tcp_signature_apply, &ctx);
MD5Update(&ctx, _KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
@@ -2834,6 +2836,8 @@
}
if ((sigp ? TF_SIGNATURE : 0) ^ (tp->t_flags & TF_SIGNATURE)) {
+ if (sav == NULL)
+ return (-1);
#ifdef FAST_IPSEC
KEY_FREESAV(&sav);
#else
@@ -2848,6 +2852,8 @@
TCP_FIELDS_TO_NET(th);
if (tcp_signature(m, th, toff, sav, sig) < 0) {
TCP_FIELDS_TO_HOST(th);
+ if (sav == NULL)
+ return (-1);
#ifdef FAST_IPSEC
KEY_FREESAV(&sav);
#else
@@ -2859,6 +2865,8 @@
if (bcmp(sig, sigp, TCP_SIGLEN)) {
tcpstat.tcps_badsig++;
+ if (sav == NULL)
+ return (-1);
#ifdef FAST_IPSEC
KEY_FREESAV(&sav);
#else
@@ -3798,6 +3806,10 @@
if (optp)
#endif
{
+ tb.t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
+#ifdef TCP_SIGNATURE
+ tb.t_flags |= (tp->t_flags & TF_SIGNATURE);
+#endif
if (tcp_dooptions(&tb, optp, optlen, th, m, m->m_pkthdr.len -
sizeof(struct tcphdr) - optlen - hlen, oi) < 0)
return (0);
>Release-Note:
>Audit-Trail:
>Unformatted: