Index: netinet/tcp_input.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v retrieving revision 1.270 diff -u -p -r1.270 tcp_input.c --- netinet/tcp_input.c 2 Aug 2007 13:06:30 -0000 1.270 +++ netinet/tcp_input.c 14 Aug 2007 11:33:34 -0000 @@ -981,6 +981,10 @@ tcp_input(struct mbuf *m, ...) #endif u_int8_t *optp = NULL; int optlen = 0; +#ifdef TCP_SIGNATURE + u_int8_t *soptp = NULL; + int soptlen = 0; +#endif int len, tlen, toff, hdroptlen = 0; struct tcpcb *tp = 0; int tiflags; @@ -1142,6 +1146,10 @@ tcp_input(struct mbuf *m, ...) KASSERT(TCP_HDR_ALIGNED_P(th)); optlen = off - sizeof (struct tcphdr); optp = ((u_int8_t *)th) + sizeof(struct tcphdr); +#ifdef TCP_SIGNATURE + soptp = optp; + soptlen = optlen; +#endif /* * Do quick retrieval of timestamp options ("options * prediction?"). If timestamp is the only option and it's @@ -1616,13 +1624,17 @@ after_listen: * Process options. */ #ifdef TCP_SIGNATURE - if (optp || (tp->t_flags & TF_SIGNATURE)) + if (optp || (tp->t_flags & TF_SIGNATURE)) { + if (!optp) { + optp = soptp; + optlen = soptlen; + } #else - if (optp) + if (optp) { #endif if (tcp_dooptions(tp, optp, optlen, th, m, toff, &opti) < 0) goto drop; - + } if (TCP_SACK_ENABLED(tp)) { tcp_del_sackholes(tp, th); } @@ -2229,7 +2241,12 @@ after_listen: if (tiflags & TH_SYN) { if (tp->rcv_nxt == th->th_seq) { tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack - 1, - TH_ACK); + TH_ACK, +#ifdef TCP_SIGNATURE + tp->t_flags & TF_SIGNATURE); +#else + 0); +#endif if (tcp_saveti) m_freem(tcp_saveti); return; @@ -2759,13 +2776,26 @@ dropwithreset: goto drop; } - if (tiflags & TH_ACK) - (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack, TH_RST); - else { + if (tiflags & TH_ACK) { +#ifdef TCP_SIGNATURE + if(tcp_checksignature(soptp, soptlen)) + (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack, + TH_RST, TF_SIGNATURE); + else +#endif + (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack, + TH_RST, 0); + } else { if (tiflags & TH_SYN) tlen++; - (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, (tcp_seq)0, - TH_RST|TH_ACK); +#ifdef TCP_SIGNATURE + if(tcp_checksignature(soptp, soptlen)) + (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, + (tcp_seq)0, TH_RST|TH_ACK, TF_SIGNATURE); + else +#endif + (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, (tcp_seq)0, + TH_RST|TH_ACK, 0); } if (tcp_saveti) m_freem(tcp_saveti); @@ -2806,7 +2836,7 @@ tcp_signature_apply(void *fstate, void * } struct secasvar * -tcp_signature_getsav(struct mbuf *m, struct tcphdr *th) +tcp_signature_getsav(struct mbuf *m) { struct secasvar *sav; #ifdef FAST_IPSEC @@ -2855,7 +2885,7 @@ tcp_signature_getsav(struct mbuf *m, str sav = key_allocsa(AF_INET6, (void *)&ip6->ip6_src, (void *)&ip6->ip6_dst, IPPROTO_TCP, htonl(TCP_SIG_SPI), 0, 0); -#endif +#endif /* FAST_IPSEC */ return (sav); /* freesav must be performed by caller */ } @@ -2928,7 +2958,34 @@ tcp_signature(struct mbuf *m, struct tcp return (0); } -#endif + +/* + * Checks if signature option is present + */ +int +tcp_checksignature(const u_char *cp, int cnt) +{ + int i = 0; + + if (cp == NULL) + return 0; + + while (i < cnt) { + if (cp[i] == TCPOPT_EOL) + return 0; + if (cp[i] == TCPOPT_NOP) { + i++; + continue; + } + if (cp[i] == TCPOPT_SIGNATURE) + return 1; + i += cp[i+1]; + } + +return 0; +} + +#endif /* TCP_SIGNATURE */ static int tcp_dooptions(struct tcpcb *tp, const u_char *cp, int cnt, @@ -3049,7 +3106,7 @@ tcp_dooptions(struct tcpcb *tp, const u_ case TCPOPT_SIGNATURE: if (optlen != TCPOLEN_SIGNATURE) continue; - if (sigp && bcmp(sigp, cp + 2, TCP_SIGLEN)) + if (sigp && memcmp(sigp, cp + 2, TCP_SIGLEN)) return (-1); sigp = sigbuf; @@ -3063,7 +3120,7 @@ tcp_dooptions(struct tcpcb *tp, const u_ #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) { - sav = tcp_signature_getsav(m, th); + sav = tcp_signature_getsav(m); if (sav == NULL && tp->t_state == TCPS_LISTEN) return (-1); @@ -3097,7 +3154,7 @@ tcp_dooptions(struct tcpcb *tp, const u_ } TCP_FIELDS_TO_HOST(th); - if (bcmp(sig, sigp, TCP_SIGLEN)) { + if (memcmp(sig, sigp, TCP_SIGLEN)) { tcpstat.tcps_badsig++; if (sav == NULL) return (-1); @@ -3521,8 +3578,8 @@ syn_cache_lookup(const struct sockaddr * sc = TAILQ_NEXT(sc, sc_bucketq)) { if (sc->sc_hash != hash) continue; - if (!bcmp(&sc->sc_src, src, src->sa_len) && - !bcmp(&sc->sc_dst, dst, dst->sa_len)) { + if (!memcmp(&sc->sc_src, src, src->sa_len) && + !memcmp(&sc->sc_dst, dst, dst->sa_len)) { splx(s); return (sc); } @@ -3849,7 +3906,8 @@ syn_cache_get(struct sockaddr *src, stru return (so); resetandabort: - (void)tcp_respond(NULL, m, m, th, (tcp_seq)0, th->th_ack, TH_RST); + /* XXX: TCP_SIGNATURE ? */ + (void)tcp_respond(NULL, m, m, th, (tcp_seq)0, th->th_ack, TH_RST, 0); abort: if (so != NULL) (void) soabort(so); @@ -4334,7 +4392,7 @@ syn_cache_respond(struct syn_cache *sc, struct secasvar *sav; u_int8_t *sigp; - sav = tcp_signature_getsav(m, th); + sav = tcp_signature_getsav(m); if (sav == NULL) { if (m) Index: netinet/tcp_output.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v retrieving revision 1.161 diff -u -p -r1.161 tcp_output.c --- netinet/tcp_output.c 2 Aug 2007 13:12:35 -0000 1.161 +++ netinet/tcp_output.c 14 Aug 2007 11:33:34 -0000 @@ -578,6 +578,7 @@ tcp_output(struct tcpcb *tp) struct sackhole *p; #ifdef TCP_SIGNATURE int sigoff = 0; + struct secasvar *sav; #endif #ifdef DIAGNOSTIC @@ -1152,9 +1153,16 @@ send: cp[0] = TCPOPT_SACK_PERMITTED; cp[1] = 2; - cp[2] = TCPOPT_NOP; - cp[3] = TCPOPT_NOP; - optlen += 4; +#ifdef TCP_SIGNATURE + if (tp->t_flags & TF_SIGNATURE) + optlen += 2; + else +#endif + { + cp[2] = TCPOPT_NOP; + cp[3] = TCPOPT_NOP; + optlen += 4; + } } } } @@ -1220,18 +1228,19 @@ send: * Initialize TCP-MD5 option (RFC2385) */ bp = (u_char *)opt + optlen; - *bp++ = TCPOPT_SIGNATURE; - *bp++ = TCPOLEN_SIGNATURE; + memset(bp, 0, TCPOLEN_SIGNATURE); + bp[0] = TCPOPT_SIGNATURE; + bp[1] = TCPOLEN_SIGNATURE; sigoff = optlen + 2; - bzero(bp, TCP_SIGLEN); - bp += TCP_SIGLEN; - optlen += TCPOLEN_SIGNATURE; + /* - * Terminate options list and maintain 32-bit alignment. + * maintain 32-bit alignment as this looks + * to be our last option XXX */ - *bp++ = TCPOPT_NOP; - *bp++ = TCPOPT_EOL; - optlen += 2; + optlen += TCPOLEN_SIGNATURE; + for (bp += TCPOLEN_SIGNATURE; optlen % 4; optlen++, bp++) + *bp = 0; + } #endif /* TCP_SIGNATURE */ @@ -1430,10 +1439,9 @@ send: #ifdef TCP_SIGNATURE if (sigoff && (tp->t_flags & TF_SIGNATURE)) { - struct secasvar *sav; u_int8_t *sigp; - sav = tcp_signature_getsav(m, th); + sav = tcp_signature_getsav(m); if (sav == NULL) { if (m) Index: netinet/tcp_subr.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v retrieving revision 1.218 diff -u -p -r1.218 tcp_subr.c --- netinet/tcp_subr.c 2 Aug 2007 02:42:41 -0000 1.218 +++ netinet/tcp_subr.c 14 Aug 2007 11:33:34 -0000 @@ -595,7 +595,7 @@ tcp_template(struct tcpcb *tp) */ int tcp_respond(struct tcpcb *tp, struct mbuf *template, struct mbuf *m, - struct tcphdr *th0, tcp_seq ack, tcp_seq seq, int flags) + struct tcphdr *th0, tcp_seq ack, tcp_seq seq, int flags, int opts) { struct route *ro; int error, tlen, win = 0; @@ -607,6 +607,9 @@ tcp_respond(struct tcpcb *tp, struct mbu int family; /* family on packet, not inpcb/in6pcb! */ struct tcphdr *th; struct socket *so; +#ifdef TCP_SIGNATURE + struct secasvar *sav; +#endif if (tp != NULL && (flags & TH_RST) == 0) { #ifdef DIAGNOSTIC @@ -726,12 +729,25 @@ tcp_respond(struct tcpcb *tp, struct mbu tlen = sizeof(*th0); else tlen = th0->th_off << 2; - +#ifdef TCP_SIGNATURE + if (opts & TF_SIGNATURE) + tlen += TCPOLEN_SIGLEN; +#endif if (m->m_len > hlen + tlen && (m->m_flags & M_EXT) == 0 && mtod(m, char *) + hlen == (char *)th0) { m->m_len = hlen + tlen; m_freem(m->m_next); m->m_next = NULL; +#ifdef TCP_SIGNATURE + if (opts & TF_SIGNATURE) { + char *sigplace; + sigplace = mtod(m, char*); + sigplace += hlen + tlen - TCPOLEN_SIGLEN; + memset(sigplace, 0, TCPOLEN_SIGLEN); + sigplace[0] = TCPOPT_SIGNATURE; + sigplace[1] = TCPOLEN_SIGNATURE; + } +#endif } else { struct mbuf *n; @@ -758,8 +774,20 @@ tcp_respond(struct tcpcb *tp, struct mbu n->m_data += max_linkhdr; n->m_len = hlen + tlen; m_copyback(n, 0, hlen, mtod(m, void *)); +#ifndef TCP_SIGNATURE m_copyback(n, hlen, tlen, (void *)th0); - +#else + if (opts & TF_SIGNATURE) { + char sigplace[TCPOLEN_SIGLEN]; + m_copyback(n, hlen, tlen - TCPOLEN_SIGLEN, (void *)th0); + memset(sigplace, 0, TCPOLEN_SIGLEN); + sigplace[0] = TCPOPT_SIGNATURE; + sigplace[1] = TCPOLEN_SIGNATURE; + m_copyback(n, hlen + tlen - TCPOLEN_SIGLEN, TCPOLEN_SIGLEN, + (void*)sigplace); + } else + m_copyback(n, hlen, tlen, (void *)th0); +#endif m_freem(m); m = n; n = NULL; @@ -807,12 +835,33 @@ tcp_respond(struct tcpcb *tp, struct mbu tlen += sizeof(*th); } else tlen += th->th_off << 2; +#ifdef TCP_SIGNATURE + /* again and again */ + if (opts & TF_SIGNATURE) { + tlen += TCPOLEN_SIGLEN; + th->th_off += TCPOLEN_SIGLEN >> 2; + } +#endif m->m_len = hlen + tlen; m->m_pkthdr.len = hlen + tlen; m->m_pkthdr.rcvif = (struct ifnet *) 0; th->th_flags = flags; th->th_urp = 0; - +#ifdef TCP_SIGNATURE + sav = tcp_signature_getsav(m); + if (sav) { + tcp_signature(m, th, (char *)th - mtod(m, char *), + sav, (char*)th + (th->th_off << 2) - TCPOLEN_SIGNATURE); + key_sa_recordxfer(sav, m); +#ifdef FAST_IPSEC + KEY_FREESAV(&sav); +#else + key_freesav(sav); +#endif + } else + memset((char*)th + (th->th_off << 2) - TCPOLEN_SIGNATURE, 0, + TCPOLEN_SIGNATURE); +#endif /* TCP_SIGNATURE */ switch (family) { #ifdef INET case AF_INET: Index: netinet/tcp_timer.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_timer.c,v retrieving revision 1.77 diff -u -p -r1.77 tcp_timer.c --- netinet/tcp_timer.c 20 Jun 2007 15:29:18 -0000 1.77 +++ netinet/tcp_timer.c 14 Aug 2007 11:33:34 -0000 @@ -569,11 +569,21 @@ tcp_timer_keep(void *arg) */ (void)tcp_respond(tp, tp->t_template, (struct mbuf *)NULL, NULL, tp->rcv_nxt - 1, - tp->snd_una - 1, 0); + tp->snd_una - 1, 0, +#ifdef TCP_SIGNATURE + tp->t_flags & TF_SIGNATURE); +#else + 0); +#endif } else { (void)tcp_respond(tp, tp->t_template, (struct mbuf *)NULL, NULL, tp->rcv_nxt, - tp->snd_una - 1, 0); + tp->snd_una - 1, 0, +#ifdef TCP_SIGNATURE + tp->t_flags & TF_SIGNATURE); +#else + 0); +#endif } TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepintvl); } else Index: netinet/tcp_usrreq.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.136 diff -u -p -r1.136 tcp_usrreq.c --- netinet/tcp_usrreq.c 2 Aug 2007 02:42:41 -0000 1.136 +++ netinet/tcp_usrreq.c 14 Aug 2007 11:33:34 -0000 @@ -722,10 +722,10 @@ tcp_ctloutput(int op, struct socket *so, #ifdef TCP_SIGNATURE case TCP_MD5SIG: - if (m == NULL || m->m_len < sizeof (int)) + if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; - if (error) break; + } if (*mtod(m, int *) > 0) tp->t_flags |= TF_SIGNATURE; else Index: netinet/tcp_var.h =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_var.h,v retrieving revision 1.150 diff -u -p -r1.150 tcp_var.h --- netinet/tcp_var.h 2 Aug 2007 02:42:42 -0000 1.150 +++ netinet/tcp_var.h 14 Aug 2007 11:33:34 -0000 @@ -851,9 +851,10 @@ struct tcpcb * tcp_drop(struct tcpcb *, int); #ifdef TCP_SIGNATURE int tcp_signature_apply(void *, void *, u_int); -struct secasvar *tcp_signature_getsav(struct mbuf *, struct tcphdr *); +struct secasvar *tcp_signature_getsav(struct mbuf *); int tcp_signature(struct mbuf *, struct tcphdr *, int, struct secasvar *, char *); +int tcp_checksignature(const u_char *, int); #endif void tcp_drain(void); void tcp_established(struct tcpcb *); @@ -886,7 +887,7 @@ struct ipqent *tcpipqent_alloc(void); void tcpipqent_free(struct ipqent *); int tcp_respond(struct tcpcb *, struct mbuf *, struct mbuf *, - struct tcphdr *, tcp_seq, tcp_seq, int); + struct tcphdr *, tcp_seq, tcp_seq, int, int); void tcp_rmx_rtt(struct tcpcb *); void tcp_setpersist(struct tcpcb *); #ifdef TCP_SIGNATURE Index: netkey/key.c =================================================================== RCS file: /cvsroot/src/sys/netkey/key.c,v retrieving revision 1.156 diff -u -p -r1.156 key.c --- netkey/key.c 9 Jul 2007 21:11:14 -0000 1.156 +++ netkey/key.c 14 Aug 2007 11:33:35 -0000 @@ -8232,7 +8232,8 @@ key_sa_routechange(dst) LIST_FOREACH(sah, &sahtree, chain) { ro = &sah->sa_route; - if (dst->sa_len == rtcache_getdst(ro)->sa_len && + if (sah->saidx.proto != IPPROTO_TCP && + dst->sa_len == rtcache_getdst(ro)->sa_len && memcmp(dst, rtcache_getdst(ro), dst->sa_len) == 0) rtcache_free(ro); }