Index: tcp_input.c =================================================================== 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"); +#ifdef TCP_SIGNATURE +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, rfc2385, CTLFLAG_RW, 0, + "TCP-MD5 RFC2385 Verification"); + +static int tcp_checksigs = 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 = 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 = 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 = NULL; u_char *optp = NULL; int optlen = 0; - int len, tlen, off; + int len, tlen, off; /* XXX set len to 0 to shutup gcc? */ int drop_hdrlen; register struct tcpcb *tp = 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=%p, tlen=%d\n", + tp, tlen); +#endif + /* + * Header fields need to be restored to + * network byte order for MD5. Kludge. + */ + th->th_seq = htonl(th->th_seq); + th->th_ack = htonl(th->th_ack); + th->th_win = htons(th->th_win); + th->th_urp = 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) != 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 = ntohl(th->th_seq); + th->th_ack = ntohl(th->th_ack); + th->th_win = ntohs(th->th_win); + th->th_urp = ntohs(th->th_urp); + } +#endif /* TCP_SIGNATURE */ if (!syncache_add(&inc, &to, th, &so, m)) goto drop; if (so == 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 != TCPOLEN_SIGNATURE) + if (optlen != TCPOLEN_SIGNATURE) { +#ifdef TCPDEBUG + printf("%s: TCPOPT_SIGNATURE: optlen %d != %d", + __func__, optlen, TCPOLEN_SIGNATURE); +#endif + tcp_rcvbadsig++; continue; - to->to_flags |= (TOF_SIGNATURE | TOF_SIGLEN); + } + to->to_flags |= TOF_SIGNATURE; + bcopy((char *)cp + 2, (char *)&to->to_digest, + TCP_SIGLEN); break; -#endif +#endif /* TCP_SIGNATURE */ default: continue; } Index: tcp_var.h =================================================================== 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 }; #ifdef _NETINET_IN_PCB_H_