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>