Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Apr 2004 14:06:59 +0100
From:      Bruce M Simpson <bms@spc.org>
To:        freebsd-net@FreeBSD.org
Cc:        mike@sentex.net
Subject:   [PATCH] First part of TCP-MD5 inbound verification
Message-ID:  <20040422130659.GG722@empiric.dek.spc.org>

next in thread | raw e-mail | index | archive | help

--yRA+Bmk8aPhU85Qt
Content-Type: multipart/mixed; boundary="OZkY3AIuv2LYvjdk"
Content-Disposition: inline


--OZkY3AIuv2LYvjdk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hey guys,

I'm really pressed for time at the moment and people are demanding a lot of
other things from me. So I'd like to float this patch set against HEAD
which does inbound TCP-MD5 verification, so far for SYNs only.

I took a decision to use sysctls rather than enlarge struct tcpstat to avoid
ABI breakage, as I know Luigi and Brooks amongst others are busy hacking
in netinet land.

I suspect the SYN validation can probably move into syncache_add() so as to
avoid code duplication in tcp_input(). Inlining it probably won't have
any real benefit. The check is essentially the same in both cases (non-SYN
for established connection, and SYN) but outcomes like 'goto drop', etc
may be different.

This appears to do the right thing with my existing test rig (Cisco 2501
running IOS 12.0(27)T).

Regards,
BMS

--OZkY3AIuv2LYvjdk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="2385-inbound.diff"
Content-Transfer-Encoding: quoted-printable

Index: tcp_input.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.233
diff -u -r1.233 tcp_input.c
--- tcp_input.c	7 Apr 2004 20:46:13 -0000	1.233
+++ tcp_input.c	20 Apr 2004 19:36:05 -0000
@@ -154,6 +154,26 @@
 	   &tcp_reass_overflows, 0,
 	   "Global number of TCP Segment Reassembly Queue Overflows");
=20
+#ifdef TCP_SIGNATURE
+SYSCTL_NODE(_net_inet_tcp, OID_AUTO, rfc2385, CTLFLAG_RW, 0,
+	    "TCP-MD5 RFC2385 Verification");
+
+static int tcp_checksigs =3D 0;
+SYSCTL_INT(_net_inet_tcp_rfc2385, OID_AUTO, verify_input, CTLFLAG_RW,
+	   &tcp_checksigs, 0,
+	   "Verify RFC2385 digests on inbound traffic");
+
+static int tcp_rcvgoodsig =3D 0;
+SYSCTL_INT(_net_inet_tcp_rfc2385, OID_AUTO, goodsegments, CTLFLAG_RD,
+	   &tcp_rcvgoodsig, 0,
+	   "Number of TCP segments with good RFC2385 digests");
+
+static int tcp_rcvbadsig =3D 0;
+SYSCTL_INT(_net_inet_tcp_rfc2385, OID_AUTO, badsegments, CTLFLAG_RD,
+	   &tcp_rcvbadsig, 0,
+	   "Number of TCP segments with bad RFC2385 digests");
+#endif
+
 struct inpcbhead tcb;
 #define	tcb6	tcb  /* for KAME src sync over BSD*'s */
 struct inpcbinfo tcbinfo;
@@ -414,7 +434,7 @@
 	register struct inpcb *inp =3D NULL;
 	u_char *optp =3D NULL;
 	int optlen =3D 0;
-	int len, tlen, off;
+	int len, tlen, off; /* XXX set len to 0 to shutup gcc? */
 	int drop_hdrlen;
 	register struct tcpcb *tp =3D 0;
 	register int thflags;
@@ -935,6 +955,57 @@
 				    (void *)tcp_saveipgen, &tcp_savetcp, 0);
 #endif
 			tcp_dooptions(&to, optp, optlen, 1);
+#ifdef TCP_SIGNATURE
+			/*
+			 * XXX Check should only happen if TCP_MD5SIG
+			 * socket option is present, right now we do it
+			 * regardless.
+			 * i.e. && tp->t_flags & TF_SIGNATURE
+			 * Header fields need to be in network byte order;
+			 * restore this temporarily. Kludgy.
+			 * XXX Move this to syncache?
+			 */
+#ifdef INET6
+			if (!isipv6)
+#endif
+			if (tcp_checksigs && (to.to_flags & TOF_SIGNATURE)) {
+				char tmpdigest[TCP_SIGLEN];
+
+#ifdef TCPDEBUG
+				printf("TCP_SIGNATURE: tcpcb=3D%p, tlen=3D%d\n",
+				    tp, tlen);
+#endif
+				/*
+				 * Header fields need to be restored to
+				 * network byte order for MD5. Kludge.
+				 */
+				th->th_seq =3D htonl(th->th_seq);
+				th->th_ack =3D htonl(th->th_ack);
+				th->th_win =3D htons(th->th_win);
+				th->th_urp =3D htons(th->th_urp);
+
+				tcp_signature_compute(m, off0, tlen, optlen,
+				   &tmpdigest[0], IPSEC_DIR_INBOUND);
+				if (bcmp(to.to_digest, &tmpdigest[0],
+				    TCP_SIGLEN) !=3D 0) {
+#ifdef TCPDEBUG
+					printf("dropped SYN due to bad "
+					    "RFC2385 digest\n");
+#endif
+					tcp_rcvbadsig++;
+					goto drop;
+				}
+				tcp_rcvgoodsig++;
+
+				/*
+				 * Restore pessimized host-byte-order fields.
+				 */
+				th->th_seq =3D ntohl(th->th_seq);
+				th->th_ack =3D ntohl(th->th_ack);
+				th->th_win =3D ntohs(th->th_win);
+				th->th_urp =3D ntohs(th->th_urp);
+			}
+#endif /* TCP_SIGNATURE */
 			if (!syncache_add(&inc, &to, th, &so, m))
 				goto drop;
 			if (so =3D=3D NULL) {
@@ -2597,13 +2668,25 @@
 		 * TCP_SIGNATURE option in its initial SYN, we have to
 		 * record the fact that the option was observed here
 		 * for the syncache code to perform the correct response.
+		 *
+		 * For inbound verification, we also need to keep a copy
+		 * of the digest itself, as this is discarded once the
+		 * options are stripped out from the mbuf chain.
 		 */
 		case TCPOPT_SIGNATURE:
-			if (optlen !=3D TCPOLEN_SIGNATURE)
+			if (optlen !=3D TCPOLEN_SIGNATURE) {
+#ifdef TCPDEBUG
+				printf("%s: TCPOPT_SIGNATURE: optlen %d !=3D %d",
+				    __func__, optlen, TCPOLEN_SIGNATURE);
+#endif
+				tcp_rcvbadsig++;
 				continue;
-			to->to_flags |=3D (TOF_SIGNATURE | TOF_SIGLEN);
+			}
+			to->to_flags |=3D TOF_SIGNATURE;
+			bcopy((char *)cp + 2, (char *)&to->to_digest,
+			    TCP_SIGLEN);
 			break;
-#endif
+#endif /* TCP_SIGNATURE */
 		default:
 			continue;
 		}
Index: tcp_var.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.103
diff -u -r1.103 tcp_var.h
--- tcp_var.h	20 Apr 2004 06:33:39 -0000	1.103
+++ tcp_var.h	20 Apr 2004 19:06:56 -0000
@@ -214,8 +214,7 @@
 #define	TOF_CCECHO	0x0008
 #define	TOF_MSS		0x0010
 #define	TOF_SCALE	0x0020
-#define	TOF_SIGNATURE	0x0040		/* signature option present */
-#define	TOF_SIGLEN	0x0080		/* sigature length valid (RFC2385) */
+#define	TOF_SIGNATURE	0x0040		/* digest option present (RFC2385) */
 	u_int32_t	to_tsval;
 	u_int32_t	to_tsecr;
 	tcp_cc		to_cc;		/* holds CC or CCnew */
@@ -223,6 +222,9 @@
 	u_int16_t	to_mss;
 	u_int8_t 	to_requested_s_scale;
 	u_int8_t 	to_pad;
+#ifdef TCP_SIGNATURE
+	u_int8_t	to_digest[TCP_SIGLEN];	/* RFC2385 digest if present */
+#endif
 };
=20
 #ifdef _NETINET_IN_PCB_H_

--OZkY3AIuv2LYvjdk--

--yRA+Bmk8aPhU85Qt
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Comment: ''

iD8DBQFAh8NyueUpAYYNtTsRAkF2AKCkGxdlcSZqBfoqpuR8se70801ucQCfeHiv
8lbVLwKzNJb/6qNVy4Sfyus=
=7Q8n
-----END PGP SIGNATURE-----

--yRA+Bmk8aPhU85Qt--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040422130659.GG722>